Skip to content

Add global Agent Plugins support and migration - #392

Merged
SudoJacky merged 6 commits into
masterfrom
feat/agent-plugins
Aug 7, 2026
Merged

Add global Agent Plugins support and migration#392
SudoJacky merged 6 commits into
masterfrom
feat/agent-plugins

Conversation

@SudoJacky

Copy link
Copy Markdown
Owner

Summary

  • add global Agent Plugins discovery and management under ~/.tinybot/plugins
  • validate plugin manifests while isolating invalid skill and MCP components
  • expose enabled plugin skills and MCP servers to the agent runtime
  • add install, enable, disable, remove, and legacy migration workflows
  • install successful migration output directly, enable it by default, and clean up temporary migration workspaces
  • refresh the Tools & Plugins UI for plugin inventory, import, migration progress, and installation guidance
  • preserve the model selected in the active chat when migration invokes the agent

Why

Tinybot previously managed skills and MCP configuration through separate paths, making discovery and reuse inconsistent across workspaces. Legacy skills or MCP packages also required manual restructuring before they could satisfy the Agent Plugins format.

Impact

Users can maintain one global plugin collection across projects, import compliant plugins, migrate legacy components through the agent, and manage activation from the Resources interface. Invalid sibling components are reported without discarding valid content.

Validation

  • cargo test plugins:: --jobs 4 — 12 passed
  • npm test -- src/app-core/native/desktopNativePlugins.test.ts src/app-core/native/nativeBackendContract.test.ts src/react-workbench/defaultServices.test.ts src/react-workbench/chat/ChatPage.test.tsx src/react-workbench/shell/DesktopShell.test.tsx — 154 passed

@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: aea0baadb0

ℹ️ 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".

setSaving(true);
try {
await onSave(buildProviderDefaultLlmPatch({ profileId, model }));
writeCurrentChatModel(model);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep models from non-default providers selectable

When the user chooses a model belonging to a non-default provider, this saves only its model ID, but normalizeChatModelOptions in defaultServices.ts limits the chat catalog to the default provider whenever one exists. On opening Chat, resolveComposerModel therefore treats the saved ID as stale, removes it from local storage, and selects the default provider's first model, silently discarding the user's selection. Include all enabled providers in the chat catalog or persist enough provider-routing information to restore this choice.

Useful? React with 👍 / 👎.

Comment on lines +51 to +52
let plugin = PluginStore::default_global().install_from_directory(&source)?;
reconcile_plugin_mcp_runtime(state.inner())?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restart MCP servers after replacing plugin packages

When an enabled plugin is re-imported with an unchanged mcp.json but updated executable or script contents, this reconciliation retains the running MCP child. The normalized server still has the same cache path and serialized configuration, while McpRuntime::reconcile only stops a server when that serialized fingerprint changes, so subsequent calls continue using the old plugin code until the application restarts. Stop the plugin's servers before replacement or incorporate the installed package revision/content into their runtime fingerprints.

Useful? React with 👍 / 👎.

...(Object.keys(metadata).length ? { extra: metadata } : {}),
...(model ? { model } : {}),
...(workingDirectory ? { workingDirectory } : {}),
...(Object.keys(extra).length ? { extra } : {}),

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 migration metadata in partial updates

When a user pins a plugin-migration conversation, sessionStore.pin supplies only { metadata: { pinned } }, and this helper turns that into extra: { pinned }. The Rust metadata patch replaces record.metadata.extra wholesale, so the existing pluginMigration value is erased; after the next refresh the conversation loses its migration status and install action even though the generated workspace remains. Merge partial extra fields with the thread's existing extra object, as the migration-status updater already does.

Useful? React with 👍 / 👎.

@SudoJacky
SudoJacky merged commit 94fae80 into master Aug 7, 2026
1 check failed
@SudoJacky
SudoJacky deleted the feat/agent-plugins branch August 7, 2026 12:58
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.

1 participant