Skip to content

feat(profile): infer plugin PI settings and add Remotion trailer - #59

Merged
jack-arturo merged 4 commits into
mainfrom
feat/plugin-settings-schema-and-trailer
Jul 18, 2026
Merged

feat(profile): infer plugin PI settings and add Remotion trailer#59
jack-arturo merged 4 commits into
mainfrom
feat/plugin-settings-schema-and-trailer

Conversation

@jack-arturo

Copy link
Copy Markdown
Member

Summary

  • Enrich streamdeck_read_plugins / list_plugins with best-effort Property Inspector settings_fields so agents know which Settings keys third-party actions expect
  • Update profile skills to document the new schema fields
  • Add a Remotion product trailer under trailer/ (source tracked; node_modules / out/ ignored)

Test plan

  • uv run pytest tests/test_profile_manager.py tests/test_profile_server.py -v
  • CI green on the PR
  • Codex review on current head addressed for P0/P1

Expose best-effort settings_fields from Property Inspectors so agents can author third-party actions, and ship a rebuildable product trailer under trailer/ (outputs ignored).
@jack-arturo

Copy link
Copy Markdown
Member Author

@codex review

Comment thread profile_manager.py Fixed
@jack-arturo

Copy link
Copy Markdown
Member Author

@codex review

CodeQL py/bad-tag-filter flagged the inline-script extractor for missing
optional whitespace before the closing tag angle bracket.
@jack-arturo

Copy link
Copy Markdown
Member Author

@codex review

Comment thread profile_manager.py Fixed
Satisfy CodeQL py/bad-tag-filter by accepting attributes/junk between
</script and the closing angle bracket.
@jack-arturo

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f20fa74cc9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread profile_manager.py
return False
if button.get("path") or button.get("action_type"):
return False
return bool(button.get("plugin_uuid")) and bool(button.get("action_uuid"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve built-in plugin actions during validation

When a button uses plugin_uuid/action_uuid, this predicate always sends it through the installed-plugin catalog; if the user has any readable third-party plugin installed, _build_third_party_action treats a missing catalog entry as fatal. That also catches built-in actions that are not installed under the user Plugins directory, such as com.elgato.streamdeck.profile which the bundled designer skill documents for profile switches (streamdeck_assets/skill/streamdeck-designer/SKILL.md:120), so those users can no longer create profile-switch buttons through the explicit fields and instead get plugin_uuid ... is not installed.

Useful? React with 👍 / 👎.

Comment thread profile_server.py
Comment on lines +674 to +677
plugins = manager.list_plugins(
plugin_id=arguments.get("plugin_id"),
include_raw_manifest=arguments.get("include_raw_manifest", False),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass through the plugin schema opt-out flag

The tool schema exposes include_settings_schema=false to skip Property Inspector parsing, but this handler neither coerces nor forwards that argument, so every streamdeck_read_plugins call still uses ProfileManager.list_plugins' default include_settings_schema=True. On installations with several PI files this defeats the advertised faster manifest-only mode and returns fields callers explicitly opted out of; add this argument to boolean coercion and pass it into list_plugins.

Useful? React with 👍 / 👎.

Comment thread profile_manager.py

# Styles B & C — keys live in inline and linked JS, not the HTML ids.
js_blobs: list[str] = [match.group(1) for match in INLINE_SCRIPT_PATTERN.finditer(html)]
for src in SCRIPT_SRC_PATTERN.findall(html)[:PI_MAX_SCRIPT_FILES]:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Count only scripts that can be scanned toward the PI cap

When a Property Inspector includes six library or remote <script> tags before its action-specific script, this slice is applied before the library/remote filtering below, so the real script is never examined. Those plugins then report empty settings_fields even though their custom JS declares payload.settings.* keys, leaving callers without the Settings keys or missing-settings warnings; apply the cap after filtering or count only files actually read.

Useful? React with 👍 / 👎.

Comment thread profile_manager.py
Comment on lines +175 to +177
HTML_ATTR_PATTERN = re.compile(r'([a-zA-Z_][\w:-]*)\s*=\s*"([^"]*)"')
DATA_SETTING_PATTERN = re.compile(r'\bdata-setting\s*=\s*"([^"]+)"')
SCRIPT_SRC_PATTERN = re.compile(r'<script\b[^>]*\bsrc\s*=\s*"([^"]+)"[^>]*>', re.IGNORECASE)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept single-quoted PI attributes

These regexes only match double-quoted HTML attributes, but valid Property Inspector markup commonly uses single quotes, e.g. <sdpi-textfield setting='entityId'> or <script src='pi.js'>. In that case the parser silently misses literal setting/data-setting fields and linked JS files, so streamdeck_read_plugins returns incomplete or empty settings_fields for otherwise supported PI styles.

Useful? React with 👍 / 👎.

Comment thread profile_manager.py
Comment on lines +869 to +873
for blob in js_blobs:
for key in JS_SETTINGS_DOT_PATTERN.findall(blob):
if key in PI_JS_NOISE_KEYS:
continue
fields.setdefault(key, {"name": key, "source": "javascript"})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Extract keys written through setSettings

For PIs that only persist values with setSettings({token: ...}) and do not also read payload.settings.token, this extraction loop never records token even though the module comment says setSettings payload literals are supported. The result is property_inspector_empty for that common style, so agents do not learn the Settings keys needed to author the action.

Useful? React with 👍 / 👎.

Comment thread profile_manager.py
Comment on lines +855 to +858
script_path = cls._resolve_plugin_relative_path(plugin_dir, src)
if script_path is None or not script_path.is_file():
# PI paths are often relative to the PI file, not the plugin root.
script_path = (pi_path.parent / src.lstrip("/")).resolve()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip URL suffixes before resolving PI scripts

If a local Property Inspector script uses a cache-busting URL such as <script src="pi.js?v=2">, the browser loads pi.js but this resolver looks for a literal file named pi.js?v=2 and then skips it. Those plugins lose all settings inferred from that linked JS, so remove query/fragment suffixes before applying the plugin-root and PI-relative path checks.

Useful? React with 👍 / 👎.

Comment thread profile_manager.py
f"{missing_required} but they were not provided "
f"(settings keys given: {sorted(provided)})."
)
elif field_names and not provided:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Warn when partial declared settings are omitted

For actions whose PI exposes fields without required metadata, providing only one setting makes provided non-empty and bypasses this warning entirely, even when other declared fields are missing. That contradicts the tool description that missing declared fields are reported, and it leaves partially authored plugin buttons (e.g. entityId supplied but mode omitted) with no warning despite having an incomplete Settings payload.

Useful? React with 👍 / 👎.

@jack-arturo
jack-arturo merged commit 9d7c66b into main Jul 18, 2026
7 checks passed
@jack-arturo
jack-arturo deleted the feat/plugin-settings-schema-and-trailer branch July 18, 2026 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants