@xopcai/xopc 0.0.395 → 0.0.397

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/src/plugin.js +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BRtkz-ZU.js → agent-avatar-dicebear-CIEGrioy.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-Dqg2NOn-.js → agent-defaults-settings-panel-CzKNVkRn.js} +1 -1
  6. package/dist/gateway/static/root/assets/agent-plugin-dialog-mpA9rwYd.js +1 -0
  7. package/dist/gateway/static/root/assets/{agents-0zgLsfVA.js → agents-7VMa7Rzo.js} +3 -3
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BZS8FvoL.js → app-management-settings-panel-DIJ0ii-n.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-RxXMAxiB.js → appearance-settings-BGnyHS-p.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-CvqDUvof.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-DEnHq3OR.js → archive-plugin-CR8FcRAa.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automations-page-BwkugzB8.js → automations-page-BLInZo7N.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-workspace-K8aDhoYt.js → automations-workspace-DvTSHLt3.js} +1 -1
  14. package/dist/gateway/static/root/assets/{binary-plugins-NWeXhh1k.js → binary-plugins-DW9pu205.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-D_bKN3BN.js → block-editor-ClgTc5v8.js} +1 -1
  16. package/dist/gateway/static/root/assets/{browser-automation-inputs-vtPkXfJ8.js → browser-automation-inputs-Bn7kDuUB.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-automations-page-DBPbwOG8.js → browser-automations-page-CJGBhDnv.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-settings-page-VBZDYoXD.js → browser-settings-page-tsi5W-cJ.js} +1 -1
  19. package/dist/gateway/static/root/assets/capabilities-page-CfbGk8q_.js +2 -0
  20. package/dist/gateway/static/root/assets/{capabilities-settings-panel-C_OMsW_8.js → capabilities-settings-panel-BkO7QEyA.js} +1 -1
  21. package/dist/gateway/static/root/assets/{capability-header-actions-CMJXWq8a.js → capability-header-actions-9ZG71-BO.js} +1 -1
  22. package/dist/gateway/static/root/assets/{channels-C_TVCc1N.js → channels-D0CwJktG.js} +1 -1
  23. package/dist/gateway/static/root/assets/{chat-terminal-dock-9YRAokOl.js → chat-terminal-dock-x1W2_hwc.js} +1 -1
  24. package/dist/gateway/static/root/assets/{computer-settings-page-BPYAZ4ks.js → computer-settings-page-D_b_bFVz.js} +1 -1
  25. package/dist/gateway/static/root/assets/{connector-service-page-B81cEAEX.js → connector-service-page-Kf8kaNm_.js} +1 -1
  26. package/dist/gateway/static/root/assets/{connectors-page-C0NvAP2V.js → connectors-page-DlpfL2Rc.js} +1 -1
  27. package/dist/gateway/static/root/assets/{date-picker-BvKP4P3n.js → date-picker-d5kiPUG0.js} +1 -1
  28. package/dist/gateway/static/root/assets/{dependency-picker-TvrNaf8y.js → dependency-picker-BcH76tQC.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-De-_QNSD.js → desktop-pet-B-925tPX.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-CRSRTIwT.js → desktop-pet-settings-3XJ4qR65.js} +1 -1
  31. package/dist/gateway/static/root/assets/device-pairing-wizard-12m5Z9-8.js +1 -0
  32. package/dist/gateway/static/root/assets/{directory-picker-path-field-DOPXwYNR.js → directory-picker-path-field-B-qZCjGR.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-debug-page-DzXvpUwj.js → extension-debug-page-BlQu1u6X.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-C0S1zNeP.js → extension-page-CXxM1M62.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-C3Z7bFjy.js → extension-settings-page-AF5nvsPP.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-settings-Btc2wTQe.js → gateway-settings-ABXvW_yL.js} +1 -1
  37. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-BFYBbh1P.js → highlighted-body-KQOG7T2V-Czdbbi0H.js} +1 -1
  38. package/dist/gateway/static/root/assets/{home-page-C5sLR47Q.js → home-page-LXGxGwVl.js} +1 -1
  39. package/dist/gateway/static/root/assets/{image-generation-api-Vqcyqnzb.js → image-generation-api-DPFPJ2ps.js} +1 -1
  40. package/dist/gateway/static/root/assets/{imports-page-BJGHrzhX.js → imports-page-Bwyotfbt.js} +1 -1
  41. package/dist/gateway/static/root/assets/index-BKHxJaGD.css +1 -0
  42. package/dist/gateway/static/root/assets/{index-BNRLzxpH.js → index-Dsp_gNdl.js} +116 -116
  43. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BQkQoPmm.js → keyboard-shortcuts-settings-C20gl-l7.js} +1 -1
  44. package/dist/gateway/static/root/assets/{local-app-workbench-page-DbxLz9Ms.js → local-app-workbench-page-o0M_OSjC.js} +1 -1
  45. package/dist/gateway/static/root/assets/{local-apps-page-CaatwSrK.js → local-apps-page-DoWJCmOq.js} +1 -1
  46. package/dist/gateway/static/root/assets/{logs-page-3Wo4Lmts.js → logs-page-BFTL93RX.js} +1 -1
  47. package/dist/gateway/static/root/assets/{management-settings-BHlbM8IM.js → management-settings-C52cuMg1.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-Cq1uLrd8.js → media-plugins-DLrTRF0a.js} +1 -1
  49. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-CPYJsRUJ.js +1 -0
  50. package/dist/gateway/static/root/assets/{note-detail-panel-MjKND8HC.js → note-detail-panel-CNN41byS.js} +3 -3
  51. package/dist/gateway/static/root/assets/{notes-page-Cv040hVD.js → notes-page-BsfBp_8z.js} +1 -1
  52. package/dist/gateway/static/root/assets/{page-context-capture-button-Cp71nTq2.js → page-context-capture-button-YTVWZ02-.js} +1 -1
  53. package/dist/gateway/static/root/assets/{personal-page-CyEUWV2n.js → personal-page-N4KoCZYG.js} +1 -1
  54. package/dist/gateway/static/root/assets/plugin-details-page-DcrrzQI-.js +1 -0
  55. package/dist/gateway/static/root/assets/{preview-open-alternatives-gzCecXc4.js → preview-open-alternatives-DzA__S54.js} +1 -1
  56. package/dist/gateway/static/root/assets/{product-open-page-CWFT7VuQ.js → product-open-page-DvlMKj0T.js} +1 -1
  57. package/dist/gateway/static/root/assets/{product-preview-content-Dh111Kca.js → product-preview-content-qdFyo4NG.js} +1 -1
  58. package/dist/gateway/static/root/assets/{project-detail-page-CyhyZiTi.js → project-detail-page-y67s_fA8.js} +1 -1
  59. package/dist/gateway/static/root/assets/{projects-page-QUdyJino.js → projects-page-D5iYgi0O.js} +1 -1
  60. package/dist/gateway/static/root/assets/{remote-access-hub-Cd8P0Dxs.js → remote-access-hub-DeFF7Re-.js} +1 -1
  61. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-bTjVfYm5.js → runtime-tools-settings-panel-BCHLh-KQ.js} +1 -1
  62. package/dist/gateway/static/root/assets/{schema-form-BGOzfVyj.js → schema-form-CJvaVHkx.js} +1 -1
  63. package/dist/gateway/static/root/assets/{sessions-page-BGMemJF6.js → sessions-page-DZ93_D5M.js} +1 -1
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-F1WX7vxq.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-form-section-Bqm1IKvR.js → settings-form-section-B3eODxNv.js} +1 -1
  66. package/dist/gateway/static/root/assets/{settings-page-CniJVL-o.js → settings-page-Dg86uCnr.js} +1 -1
  67. package/dist/gateway/static/root/assets/{setup-status-panel-JPs4-QRw.js → setup-status-panel-ruFzAArp.js} +1 -1
  68. package/dist/gateway/static/root/assets/{share-preview-page-BnDGFgBR.js → share-preview-page-DCy1f25V.js} +1 -1
  69. package/dist/gateway/static/root/assets/{shares-settings-Cgp5BuLt.js → shares-settings-DeIVZvpJ.js} +1 -1
  70. package/dist/gateway/static/root/assets/{skill-api-CFdrz6tl.js → skill-api-RisyPAMA.js} +1 -1
  71. package/dist/gateway/static/root/assets/{skill-reload-api-Cy5jVfms.js → skill-reload-api-Dwkm1Fof.js} +1 -1
  72. package/dist/gateway/static/root/assets/{skills-page-CxaA3P5E.js → skills-page-UiTLsrFc.js} +1 -1
  73. package/dist/gateway/static/root/assets/{style-C_MAnir7.js → style-CwMX73G7.js} +1 -1
  74. package/dist/gateway/static/root/assets/{system-settings-panel-BjnIlilP.js → system-settings-panel-Cma37Pfm.js} +1 -1
  75. package/dist/gateway/static/root/assets/{task-detail-page-Bg79rPnF.js → task-detail-page-BKOF_kxS.js} +1 -1
  76. package/dist/gateway/static/root/assets/{tracing-settings-page-BCI0tUbe.js → tracing-settings-page-DC-kLysq.js} +1 -1
  77. package/dist/gateway/static/root/assets/{tunnel-api-0knnta9z.js → tunnel-api-BgdhbR1L.js} +1 -1
  78. package/dist/gateway/static/root/assets/{usage-page-D5aT1eie.js → usage-page-BSlFg3Xj.js} +1 -1
  79. package/dist/gateway/static/root/assets/{use-autosave-Ds_mbAfe.js → use-autosave-iKvZ1pvC.js} +1 -1
  80. package/dist/gateway/static/root/assets/{user-model-page-D7L0-pDt.js → user-model-page-D4GB8QsM.js} +1 -1
  81. package/dist/gateway/static/root/assets/{voice-api-key-field-CPoGdarN.js → voice-api-key-field-CESbtuwM.js} +1 -1
  82. package/dist/gateway/static/root/assets/{work-discovery-overlay-CWNguy2Z.js → work-discovery-overlay-dtPpmYyh.js} +1 -1
  83. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BcDMFfkT.js → workflow-run-setup-panel-DmFn3E_B.js} +1 -1
  84. package/dist/gateway/static/root/assets/{workflows-page-BwZB-s4N.js → workflows-page-DEtaRuxH.js} +1 -1
  85. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-DlKr98VO.js → xopc-cloud-account-card-DTZnabfg.js} +1 -1
  86. package/dist/gateway/static/root/index.html +2 -2
  87. package/dist/package.js +1 -1
  88. package/dist/src/agent/embedded/codemode-extension.d.ts +1 -0
  89. package/dist/src/agent/embedded/codemode-extension.js +6 -1
  90. package/dist/src/agent/embedded/run-for-session.js +1 -1
  91. package/dist/src/agent/embedded/run-turn.js +34 -2
  92. package/dist/src/agent/embedded/session-runner.js +1 -1
  93. package/dist/src/agent/mcp/config.d.ts +2 -0
  94. package/dist/src/agent/mcp/config.js +2 -2
  95. package/dist/src/agent/mcp/connection-setup.js +13 -1
  96. package/dist/src/agent/mcp/effective-server.d.ts +3 -0
  97. package/dist/src/agent/mcp/effective-server.js +27 -0
  98. package/dist/src/agent/mcp/native-mcp.d.ts +1 -1
  99. package/dist/src/agent/mcp/native-mcp.js +13 -4
  100. package/dist/src/agent/mcp/tool-catalog.js +2 -1
  101. package/dist/src/agent/skills/index.d.ts +1 -0
  102. package/dist/src/agent/skills/index.js +6 -2
  103. package/dist/src/agent/skills/skill-manager.d.ts +1 -0
  104. package/dist/src/agent/skills/skill-manager.js +6 -1
  105. package/dist/src/agent/skills/skill-sources.d.ts +1 -0
  106. package/dist/src/agent/skills/skill-sources.js +4 -3
  107. package/dist/src/agent/skills/types.d.ts +1 -0
  108. package/dist/src/agent/workspace-runtime/registry.js +6 -2
  109. package/dist/src/browser/native-messaging-host.js +1 -1
  110. package/dist/src/browser/providers/browser-ext-install.js +2 -2
  111. package/dist/src/channels/index.js +1 -1
  112. package/dist/src/channels/manager.js +1 -1
  113. package/dist/src/cli/commands/channels.js +1 -1
  114. package/dist/src/cli/commands/connectors.js +1 -1
  115. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  116. package/dist/src/cli/commands/extension-agent-plugin.js +92 -7
  117. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  118. package/dist/src/cli/commands/extension.js +1 -1
  119. package/dist/src/cli/commands/mcp.js +6 -4
  120. package/dist/src/cli/commands/models.js +1 -1
  121. package/dist/src/cli/commands/onboard/model.js +1 -1
  122. package/dist/src/cli/commands/onboard.js +1 -1
  123. package/dist/src/extensions/agent-plugins/auth.d.ts +7 -1
  124. package/dist/src/extensions/agent-plugins/auth.js +53 -12
  125. package/dist/src/extensions/agent-plugins/branding.d.ts +6 -0
  126. package/dist/src/extensions/agent-plugins/branding.js +44 -0
  127. package/dist/src/extensions/agent-plugins/cli-authorization.d.ts +22 -0
  128. package/dist/src/extensions/agent-plugins/cli-authorization.js +198 -0
  129. package/dist/src/extensions/agent-plugins/connection-reuse.d.ts +10 -0
  130. package/dist/src/extensions/agent-plugins/connection-reuse.js +23 -0
  131. package/dist/src/extensions/agent-plugins/credentials.js +24 -1
  132. package/dist/src/extensions/agent-plugins/formats.d.ts +27 -0
  133. package/dist/src/extensions/agent-plugins/formats.js +208 -0
  134. package/dist/src/extensions/agent-plugins/inventory.d.ts +142 -2
  135. package/dist/src/extensions/agent-plugins/inventory.js +39 -5
  136. package/dist/src/extensions/agent-plugins/mcp-adapter.d.ts +2 -1
  137. package/dist/src/extensions/agent-plugins/mcp-adapter.js +42 -8
  138. package/dist/src/extensions/agent-plugins/mcp-format.d.ts +2 -0
  139. package/dist/src/extensions/agent-plugins/mcp-format.js +82 -0
  140. package/dist/src/extensions/agent-plugins/resources.d.ts +14 -0
  141. package/dist/src/extensions/agent-plugins/resources.js +112 -0
  142. package/dist/src/extensions/agent-plugins/setup-contract.d.ts +54 -0
  143. package/dist/src/extensions/agent-plugins/setup-contract.js +58 -0
  144. package/dist/src/extensions/agent-plugins/setup.d.ts +119 -0
  145. package/dist/src/extensions/agent-plugins/setup.js +491 -0
  146. package/dist/src/extensions/agent-plugins/source-catalog.d.ts +21 -0
  147. package/dist/src/extensions/agent-plugins/source-catalog.js +175 -0
  148. package/dist/src/extensions/agent-plugins/sources.d.ts +1 -1
  149. package/dist/src/extensions/agent-plugins/sources.js +12 -3
  150. package/dist/src/extensions/agent-plugins/store.d.ts +33 -2
  151. package/dist/src/extensions/agent-plugins/store.js +175 -25
  152. package/dist/src/extensions/agent-plugins/user-config.d.ts +5 -0
  153. package/dist/src/extensions/agent-plugins/user-config.js +49 -0
  154. package/dist/src/extensions/agent-plugins/validation.d.ts +26 -1
  155. package/dist/src/extensions/agent-plugins/validation.js +142 -27
  156. package/dist/src/extensions/sdk/index.js +1 -1
  157. package/dist/src/gateway/hono/app.js +1 -1
  158. package/dist/src/gateway/hono/routes/agent-plugins.js +120 -9
  159. package/dist/src/gateway/hono/routes/browser-install.js +1 -1
  160. package/dist/src/gateway/hono/routes/composer-history.js +22 -4
  161. package/dist/src/gateway/hono/routes/mcp.js +6 -4
  162. package/dist/src/gateway/hono/routes/provider-setup.js +7 -0
  163. package/dist/src/gateway/service.js +11 -9
  164. package/dist/src/gateway/session-context-summary.js +1 -1
  165. package/dist/src/gateway/xopc-cloud-capability-setup.d.ts +4 -0
  166. package/dist/src/gateway/xopc-cloud-capability-setup.js +90 -26
  167. package/dist/src/home-intelligence/host.js +2 -2
  168. package/dist/src/providers/setup/engine.js +12 -10
  169. package/dist/src/providers/setup/voice.js +24 -6
  170. package/dist/src/storage/sqlite/composer-input-history-repository.d.ts +4 -3
  171. package/dist/src/storage/sqlite/composer-input-history-repository.js +10 -8
  172. package/dist/src/storage/sqlite/device-pairing-approval.js +1 -1
  173. package/dist/src/storage/sqlite/migrations/257_session_composer_history.sql +11 -0
  174. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  175. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  176. package/dist/src/storage/sqlite/schema.js +1 -1
  177. package/dist/src/tui/backends/embedded-backend.d.ts +2 -2
  178. package/dist/src/tui/backends/embedded-backend.js +4 -4
  179. package/dist/src/tui/backends/gateway-realtime-backend.d.ts +2 -2
  180. package/dist/src/tui/backends/gateway-realtime-backend.js +7 -4
  181. package/dist/src/tui/composer-history.d.ts +14 -0
  182. package/dist/src/tui/composer-history.js +85 -0
  183. package/dist/src/tui/tui-backend.d.ts +4 -3
  184. package/dist/src/tui/tui.js +19 -46
  185. package/package.json +12 -4
  186. package/dist/gateway/static/root/assets/agent-plugin-dialog-CKK95Jmr.js +0 -1
  187. package/dist/gateway/static/root/assets/apps-page-mGU9WLjP.js +0 -1
  188. package/dist/gateway/static/root/assets/capabilities-page-CQsGp9Sx.js +0 -2
  189. package/dist/gateway/static/root/assets/device-pairing-wizard-DnyJ8Bja.js +0 -1
  190. package/dist/gateway/static/root/assets/index-zIgp-ZTu.css +0 -1
  191. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-XhlIBp5t.js +0 -1
  192. package/dist/gateway/static/root/assets/settings-advanced-gate-BiySFw1N.js +0 -1
@@ -14,4 +14,4 @@ export interface AgentPluginSourceProvenance {
14
14
  export declare function isAgentPluginArchive(buffer: Buffer): boolean;
15
15
  export declare function withAgentPluginArchive<T>(buffer: Buffer, fn: (local: string) => T): T;
16
16
  /** Resolve remote artifacts only for explicit inspect/install requests, never during discovery. */
17
- export declare function withAgentPluginSource<T>(source: string, config: Config | undefined, fn: (local: string, provenance?: AgentPluginSourceProvenance) => T): Promise<T>;
17
+ export declare function withAgentPluginSource<T>(source: string, config: Config | undefined, fn: (local: string, provenance?: AgentPluginSourceProvenance, resolvedCommit?: string, importManifest?: Record<string, unknown>) => T, depth?: number): Promise<T>;
@@ -1,4 +1,6 @@
1
1
  import { createPluginSourceFetch } from "./source-http-fetch.js";
2
+ import { PLUGIN_MANIFEST_PATHS } from "./formats.js";
3
+ import { PluginSourceRedirect, isGitPluginSource, withCatalogSource } from "./source-catalog.js";
2
4
  import { tmpdir } from "node:os";
3
5
  import { join } from "node:path";
4
6
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
@@ -14,11 +16,11 @@ function isAgentPluginArchive(buffer) {
14
16
  return Boolean(JSON.parse(entry.getData().toString("utf8"))?.xopc?.extension);
15
17
  };
16
18
  if (paths.includes("xopc.extension.json")) return false;
17
- if (paths.includes("plugin.json")) return !nativeMetadata("package.json");
19
+ if (PLUGIN_MANIFEST_PATHS.some((path) => paths.includes(path))) return !nativeMetadata("package.json");
18
20
  const first = new Set(paths.map((path) => path.split("/")[0]));
19
21
  if (first.size !== 1) return false;
20
22
  const root = [...first][0];
21
- return paths.includes(`${root}/plugin.json`) && !paths.includes(`${root}/xopc.extension.json`) && !nativeMetadata(`${root}/package.json`);
23
+ return PLUGIN_MANIFEST_PATHS.some((path) => paths.includes(`${root}/${path}`)) && !paths.includes(`${root}/xopc.extension.json`) && !nativeMetadata(`${root}/package.json`);
22
24
  }
23
25
  function withAgentPluginArchive(buffer, fn) {
24
26
  const dir = mkdtempSync(join(tmpdir(), "xopc-plugin-download-"));
@@ -34,7 +36,14 @@ function withAgentPluginArchive(buffer, fn) {
34
36
  }
35
37
  }
36
38
  /** Resolve remote artifacts only for explicit inspect/install requests, never during discovery. */
37
- async function withAgentPluginSource(source, config, fn) {
39
+ async function withAgentPluginSource(source, config, fn, depth = 0) {
40
+ if (depth > 4) throw new Error("Marketplace source nesting exceeds limits");
41
+ if (isGitPluginSource(source) || !source.startsWith("https://") && !source.startsWith("store:") && (!source.toLowerCase().endsWith(".zip") || source.includes("#"))) try {
42
+ return await withCatalogSource(source, (local, metadata) => fn(local, void 0, metadata.commit, metadata.importManifest));
43
+ } catch (error) {
44
+ if (error instanceof PluginSourceRedirect) return withAgentPluginSource(error.source, config, fn, depth + 1);
45
+ throw error;
46
+ }
38
47
  if (!source.startsWith("https://") && !source.startsWith("store:")) return fn(source);
39
48
  let buffer;
40
49
  let provenance;
@@ -31,6 +31,14 @@ declare const receiptSchema: z.ZodObject<{
31
31
  "local-exec": "local-exec";
32
32
  }>>;
33
33
  }, z.core.$strict>>;
34
+ adapterVersion: z.ZodOptional<z.ZodString>;
35
+ credentialScope: z.ZodOptional<z.ZodLiteral<"revision">>;
36
+ workspacePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
+ resourceHashes: z.ZodOptional<z.ZodArray<z.ZodString>>;
38
+ oauthServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
39
+ importManifest: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
40
+ resolvedCommit: z.ZodOptional<z.ZodString>;
41
+ declaredName: z.ZodOptional<z.ZodString>;
34
42
  previous: z.ZodOptional<z.ZodObject<{
35
43
  id: z.ZodString;
36
44
  revision: z.ZodString;
@@ -61,6 +69,14 @@ declare const receiptSchema: z.ZodObject<{
61
69
  "local-exec": "local-exec";
62
70
  }>>;
63
71
  }, z.core.$strict>>;
72
+ adapterVersion: z.ZodOptional<z.ZodString>;
73
+ credentialScope: z.ZodOptional<z.ZodLiteral<"revision">>;
74
+ workspacePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ resourceHashes: z.ZodOptional<z.ZodArray<z.ZodString>>;
76
+ oauthServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
77
+ importManifest: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
78
+ resolvedCommit: z.ZodOptional<z.ZodString>;
79
+ declaredName: z.ZodOptional<z.ZodString>;
64
80
  }, z.core.$strip>>;
65
81
  }, z.core.$strip>;
66
82
  export type PluginReceipt = z.infer<typeof receiptSchema>;
@@ -71,6 +87,7 @@ export interface InstalledAgentPlugin extends PluginInspection {
71
87
  readiness: 'ready' | 'setup_required' | 'degraded' | 'blocked';
72
88
  }
73
89
  export interface PluginInstallPlan extends PluginInspection {
90
+ installId: string;
74
91
  integrity: string;
75
92
  reviewHash: string;
76
93
  addedCapabilities: string[];
@@ -88,9 +105,11 @@ export declare class AgentPluginStore {
88
105
  private write;
89
106
  private mutate;
90
107
  get(id: string): InstalledAgentPlugin | undefined;
108
+ private fromReceipt;
91
109
  list(): InstalledAgentPlugin[];
92
- active(): InstalledAgentPlugin[];
93
- inspect(source: string): PluginInstallPlan;
110
+ active(_agentId?: string, workspaceDir?: string): InstalledAgentPlugin[];
111
+ private setupReady;
112
+ inspect(source: string, sourceLabel?: string, importManifest?: Record<string, unknown>): PluginInstallPlan;
94
113
  private plan;
95
114
  install(source: string, options?: {
96
115
  reviewHash?: string;
@@ -98,8 +117,20 @@ export declare class AgentPluginStore {
98
117
  expectedId?: string;
99
118
  sourceLabel?: string;
100
119
  provenance?: AgentPluginSourceProvenance;
120
+ stage?: boolean;
121
+ resolvedCommit?: string;
122
+ importManifest?: Record<string, unknown>;
101
123
  }): InstalledAgentPlugin;
124
+ history(id: string): InstalledAgentPlugin[];
125
+ /** Publish synchronous resource changes while the package lifecycle lock is held. */
126
+ withRevision<T>(id: string, revision: string, fn: () => T): T;
127
+ private pendingPath;
128
+ pendingReceipt(id: string): PluginReceipt | undefined;
129
+ pending(id: string): InstalledAgentPlugin | undefined;
130
+ commitPending(id: string): void;
131
+ discardPending(id: string): void;
102
132
  setEnabled(id: string, enabled: boolean): InstalledAgentPlugin;
133
+ setWorkspaceScope(id: string, workspacePaths?: string[] | null): InstalledAgentPlugin;
103
134
  rollback(id: string): InstalledAgentPlugin;
104
135
  remove(id: string, removeData?: boolean): void;
105
136
  private withSource;
@@ -3,10 +3,13 @@ import { createLogger } from "../../utils/logger/index.js";
3
3
  import { init_logger } from "../../utils/logger.js";
4
4
  import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
5
5
  import { computeExtensionDirectoryIntegrity } from "../lockfile.js";
6
+ import { prunePluginResourceCache } from "./resources.js";
7
+ import { PLUGIN_MANIFEST_PATHS } from "./formats.js";
6
8
  import { containedPath, inspectAgentPlugin, pluginName } from "./validation.js";
9
+ import { pluginSourceKey } from "./source-catalog.js";
7
10
  import { tmpdir } from "node:os";
8
11
  import { dirname, join, resolve } from "node:path";
9
- import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
12
+ import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
10
13
  import { createHash, randomUUID } from "node:crypto";
11
14
  import { z } from "zod";
12
15
  import AdmZip from "adm-zip";
@@ -39,7 +42,15 @@ const receiptFields = z.object({
39
42
  enabled: z.boolean(),
40
43
  integrity: z.string(),
41
44
  capabilities: z.array(z.string()),
42
- provenance: provenanceSchema.optional()
45
+ provenance: provenanceSchema.optional(),
46
+ adapterVersion: z.string().min(1).max(64).optional(),
47
+ credentialScope: z.literal("revision").optional(),
48
+ workspacePaths: z.array(z.string()).max(100).optional(),
49
+ resourceHashes: z.array(z.string()).optional(),
50
+ oauthServers: z.record(z.string(), z.string()).optional(),
51
+ importManifest: z.record(z.string(), z.unknown()).optional(),
52
+ resolvedCommit: z.string().regex(/^[a-f0-9]{40,64}$/).optional(),
53
+ declaredName: pluginName.optional()
43
54
  });
44
55
  const receiptSchema = receiptFields.extend({ previous: receiptFields.optional() });
45
56
  const log = createLogger("AgentPlugins");
@@ -54,7 +65,8 @@ var AgentPluginStore = class {
54
65
  if (!existsSync(this.receiptsDir())) return "";
55
66
  return readdirSync(this.receiptsDir()).filter((name) => name.endsWith(".json")).sort().map((name) => {
56
67
  try {
57
- return `${name}:${statSync(join(this.receiptsDir(), name)).mtimeMs}`;
68
+ const setupPath = join(this.stateDir, "plugin-setup", name);
69
+ return createHash("sha256").update(readFileSync(join(this.receiptsDir(), name))).update(existsSync(setupPath) ? readFileSync(setupPath) : "").digest("hex");
58
70
  } catch {
59
71
  return "";
60
72
  }
@@ -93,17 +105,29 @@ var AgentPluginStore = class {
93
105
  }
94
106
  get(id) {
95
107
  const receipt = this.receipt(id);
96
- if (!receipt) return void 0;
108
+ return receipt ? this.fromReceipt(receipt) : void 0;
109
+ }
110
+ fromReceipt(receipt) {
111
+ const id = receipt.id;
97
112
  const rootDir = this.revisionDir(id, receipt.revision);
98
113
  try {
99
114
  validatePackageTree(rootDir);
100
- const inspection = inspectAgentPlugin(rootDir, this.dataDir(id));
115
+ const inspection = inspectAgentPlugin(rootDir, this.dataDir(id), receipt.importManifest);
101
116
  const valid = computeExtensionDirectoryIntegrity(rootDir) === receipt.integrity;
102
117
  if (!valid) inspection.diagnostics.push({
103
118
  component: "package",
104
119
  message: "Installed files differ from the reviewed package"
105
120
  });
106
- const readiness = !valid ? "blocked" : inspection.diagnostics.length ? "degraded" : "ready";
121
+ const previouslyReviewed = new Set(receipt.capabilities);
122
+ const adapterChanged = receipt.adapterVersion !== void 0 && receipt.adapterVersion !== inspection.layout?.adapterVersion;
123
+ const capabilityChanged = inspection.capabilities.some((capability) => !previouslyReviewed.has(capability) && !(receipt.adapterVersion === void 0 && previouslyReviewed.has(capability.replace(/:\{\}:\{\}$/, ""))));
124
+ if (adapterChanged || capabilityChanged) inspection.diagnostics.push({
125
+ component: "review",
126
+ message: "Adapter interpretation changed capabilities. Inspect and review this package again."
127
+ });
128
+ const setupPath = join(this.stateDir, "plugin-setup", `${id}.json`);
129
+ const setup = existsSync(setupPath) ? JSON.parse(readFileSync(setupPath, "utf8")) : void 0;
130
+ const readiness = !valid || adapterChanged || capabilityChanged || inspection.layout?.compatibility.some((item) => item.component === "hooks" || item.component === "authorizations" && item.support === "invalid") ? "blocked" : setup?.packageRevision === receipt.revision && setup.state !== "completed" && !setup.installed ? "setup_required" : inspection.diagnostics.length || setup?.packageRevision === receipt.revision && (setup.partial || setup.installed && (setup.missingConfig?.length || setup.connections?.some((value) => value.state !== "connected") || setup.authorizations?.some((value) => value.state !== "connected"))) ? "degraded" : "ready";
107
131
  return {
108
132
  ...inspection,
109
133
  id,
@@ -149,23 +173,43 @@ var AgentPluginStore = class {
149
173
  }
150
174
  });
151
175
  }
152
- active() {
176
+ active(_agentId, workspaceDir) {
153
177
  if (["1", "true"].includes(process.env.XOPC_SKIP_EXTENSIONS ?? "")) return [];
154
- return this.list().filter((p) => p.receipt.enabled && p.readiness !== "blocked");
178
+ return this.list().filter((p) => p.receipt.enabled && p.readiness !== "blocked" && (p.receipt.workspacePaths === void 0 || workspaceDir !== void 0 && p.receipt.workspacePaths.includes(existsSync(workspaceDir) ? realpathSync(workspaceDir) : resolve(workspaceDir))) && this.setupReady(p));
179
+ }
180
+ setupReady(plugin) {
181
+ const path = join(this.stateDir, "plugin-setup", `${plugin.id}.json`);
182
+ if (!existsSync(path)) return true;
183
+ try {
184
+ const job = JSON.parse(readFileSync(path, "utf8"));
185
+ return job.packageRevision !== plugin.receipt.revision || job.state === "completed" || job.installed === true;
186
+ } catch {
187
+ return false;
188
+ }
155
189
  }
156
- inspect(source) {
157
- return this.withSource(source, (root) => this.plan(root));
190
+ inspect(source, sourceLabel = source, importManifest) {
191
+ return this.withSource(source, (root) => this.plan(root, sourceLabel, importManifest));
158
192
  }
159
- plan(root) {
193
+ plan(root, sourceLabel, importManifest) {
160
194
  validatePackageTree(root);
161
- const initial = inspectAgentPlugin(root);
162
- const inspection = inspectAgentPlugin(root, this.dataDir(initial.manifest.name));
195
+ const initial = inspectAgentPlugin(root, void 0, importManifest);
196
+ const existing = this.list().find((p) => p.receipt.source === sourceLabel && p.manifest.name === initial.manifest.name);
197
+ const scoped = initial.layout?.dialect !== "portable" || /^(?:git\+|github:|https:\/\/github\.com\/)/.test(sourceLabel) || sourceLabel.includes("#plugin=");
198
+ const installId = existing?.id ?? (scoped ? `${initial.manifest.name.slice(0, 48).replace(/[.-]+$/, "")}-${pluginSourceKey(sourceLabel)}` : initial.manifest.name);
199
+ const inspection = inspectAgentPlugin(root, this.dataDir(installId), importManifest);
163
200
  const integrity = computeExtensionDirectoryIntegrity(root);
164
- const current = this.receipt(inspection.manifest.name);
201
+ const current = this.receipt(installId);
165
202
  const addedCapabilities = inspection.capabilities.filter((c) => !current?.capabilities.includes(c));
166
- const reviewHash = createHash("sha256").update(JSON.stringify([integrity, inspection.capabilities])).digest("hex");
203
+ const reviewHash = createHash("sha256").update(JSON.stringify([
204
+ "plugin-adapter-v1",
205
+ integrity,
206
+ inspection.capabilities,
207
+ installId,
208
+ importManifest
209
+ ])).digest("hex");
167
210
  return {
168
211
  ...inspection,
212
+ installId,
169
213
  integrity,
170
214
  reviewHash,
171
215
  addedCapabilities,
@@ -174,12 +218,15 @@ var AgentPluginStore = class {
174
218
  }
175
219
  install(source, options = {}) {
176
220
  return this.mutate(() => this.withSource(source, (root) => {
177
- const plan = this.plan(root);
178
- const id = plan.manifest.name;
179
- if (options.expectedId && options.expectedId !== id) throw new Error("Update package identity does not match installed plugin");
221
+ const plan = this.plan(root, options.sourceLabel ?? source, options.importManifest);
222
+ const id = options.expectedId ?? plan.installId;
223
+ const expected = this.receipt(id);
224
+ if (expected && (expected.declaredName ?? expected.id) !== plan.manifest.name) throw new Error("Update package identity does not match installed plugin");
225
+ if (options.expectedId && !expected) throw new Error("Update package identity does not match installed plugin");
180
226
  const current = this.receipt(id);
181
227
  if (current && !options.replace) throw new Error("Plugin already installed; use update");
182
- if ((!current || plan.addedCapabilities.length > 0) && options.reviewHash !== plan.reviewHash) throw new Error("Package capability review is required");
228
+ const changedExecutable = current && current.integrity !== plan.integrity && (plan.capabilities.some((capability) => capability.startsWith("runtime.")) || current.capabilities.some((capability) => capability.startsWith("runtime.")));
229
+ if ((!current || plan.addedCapabilities.length > 0 || changedExecutable) && options.reviewHash !== plan.reviewHash) throw new Error("Package capability review is required");
183
230
  if (options.reviewHash && options.reviewHash !== plan.reviewHash) throw new Error("Package changed after review; inspect again");
184
231
  validatePackageTree(root);
185
232
  const revision = randomUUID();
@@ -192,35 +239,119 @@ var AgentPluginStore = class {
192
239
  verbatimSymlinks: true
193
240
  });
194
241
  validatePackageTree(target);
195
- const installed = inspectAgentPlugin(target, this.dataDir(id));
242
+ const installed = inspectAgentPlugin(target, this.dataDir(id), options.importManifest);
196
243
  const integrity = computeExtensionDirectoryIntegrity(target);
197
244
  if (integrity !== plan.integrity) throw new Error("Package changed during installation");
198
245
  const label = options.sourceLabel ?? source;
199
- this.write({
246
+ const receipt = {
200
247
  id,
201
248
  revision,
202
- source: /^(https:\/\/|store:)/.test(label) ? label : resolve(label),
249
+ source: /^(https:\/\/|store:|git\+|github:)/.test(label) ? label : resolve(label),
203
250
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
251
+ declaredName: installed.manifest.name,
252
+ adapterVersion: installed.layout?.adapterVersion,
253
+ credentialScope: "revision",
254
+ oauthServers: Object.fromEntries(Object.entries(installed.servers).filter(([, server]) => server.type !== "stdio").map(([name, server]) => [name, server.type !== "stdio" ? server.url : ""])),
255
+ importManifest: options.importManifest,
256
+ resolvedCommit: options.resolvedCommit,
257
+ workspacePaths: current?.workspacePaths,
258
+ resourceHashes: plan.resources?.map((resource) => resource.sha256),
204
259
  enabled: current?.enabled ?? false,
205
260
  integrity,
206
261
  capabilities: installed.capabilities,
207
262
  ...options.provenance ? { provenance: provenanceSchema.parse(options.provenance) } : {},
208
263
  previous: current ? receiptFields.parse(current) : void 0
209
- });
264
+ };
265
+ writeTextAtomicSync(join(this.stateDir, "plugin-revisions", id, `${revision}.json`), JSON.stringify(receiptFields.parse(receipt)));
266
+ if (options.stage && current) writeTextAtomicSync(this.pendingPath(id), JSON.stringify(receipt));
267
+ else this.write(receipt);
210
268
  } catch (error) {
211
269
  rmSync(target, {
212
270
  recursive: true,
213
271
  force: true
214
272
  });
273
+ rmSync(join(this.stateDir, "plugin-revisions", id, `${revision}.json`), { force: true });
215
274
  throw error;
216
275
  }
217
- return this.get(id);
276
+ return options.stage && current ? this.pending(id) : this.get(id);
218
277
  }));
219
278
  }
279
+ history(id) {
280
+ const current = this.receipt(id), pending = this.pending(id);
281
+ const receipts = /* @__PURE__ */ new Map();
282
+ for (const receipt of [
283
+ current,
284
+ current?.previous,
285
+ pending?.receipt
286
+ ]) if (receipt) receipts.set(receipt.revision, receipt);
287
+ const directory = join(this.stateDir, "plugin-revisions", pluginName.parse(id));
288
+ if (existsSync(directory)) for (const name of readdirSync(directory)) {
289
+ if (!name.endsWith(".json")) continue;
290
+ const receipt = receiptFields.parse(JSON.parse(readFileSync(join(directory, name), "utf8")));
291
+ if (receipt.id !== id) throw new Error("Plugin history identity mismatch");
292
+ receipts.set(receipt.revision, receipt);
293
+ }
294
+ return [...receipts.values()].map((receipt) => this.fromReceipt(receipt));
295
+ }
296
+ /** Publish synchronous resource changes while the package lifecycle lock is held. */
297
+ withRevision(id, revision, fn) {
298
+ return this.mutate(() => {
299
+ if (this.receipt(id)?.revision !== revision && this.pending(id)?.receipt.revision !== revision) throw new Error("Plugin revision changed or was removed");
300
+ return fn();
301
+ });
302
+ }
303
+ pendingPath(id) {
304
+ return join(this.stateDir, "plugin-pending", `${pluginName.parse(id)}.json`);
305
+ }
306
+ pendingReceipt(id) {
307
+ const path = this.pendingPath(id);
308
+ if (!existsSync(path)) return void 0;
309
+ const receipt = receiptSchema.parse(JSON.parse(readFileSync(path, "utf8")));
310
+ if (receipt.id !== id) throw new Error("Staged plugin identity mismatch");
311
+ return receipt;
312
+ }
313
+ pending(id) {
314
+ const receipt = this.pendingReceipt(id);
315
+ return receipt ? this.fromReceipt(receipt) : void 0;
316
+ }
317
+ commitPending(id) {
318
+ this.mutate(() => {
319
+ const pending = this.pending(id);
320
+ if (!pending) return;
321
+ if (pending.readiness === "blocked" || pending.receipt.previous?.revision !== this.receipt(id)?.revision) throw new Error("Staged update changed; inspect again");
322
+ this.write(pending.receipt);
323
+ rmSync(this.pendingPath(id), { force: true });
324
+ });
325
+ }
326
+ discardPending(id) {
327
+ this.mutate(() => {
328
+ const pending = this.pending(id);
329
+ if (!pending) return;
330
+ rmSync(this.pendingPath(id), { force: true });
331
+ rmSync(pending.rootDir, {
332
+ recursive: true,
333
+ force: true
334
+ });
335
+ try {
336
+ const data = this.dataDir(id);
337
+ rmSync(containedPath(data, join(data, "resources", pending.receipt.revision)), {
338
+ recursive: true,
339
+ force: true
340
+ });
341
+ } catch (err) {
342
+ log.warn({
343
+ err,
344
+ pluginId: id
345
+ }, "Could not clean staged plugin resources");
346
+ }
347
+ prunePluginResourceCache(this);
348
+ });
349
+ }
220
350
  setEnabled(id, enabled) {
221
351
  return this.mutate(() => {
222
352
  const plugin = this.get(id);
223
353
  if (!plugin) throw new Error("Plugin not installed");
354
+ if (enabled && plugin.layout?.compatibility.some((item) => item.component === "hooks")) throw new Error("This plugin requires unsupported lifecycle hooks and cannot be enabled by this compatibility version");
224
355
  if (enabled && plugin.readiness === "blocked") throw new Error("Repair the plugin before enabling it");
225
356
  this.write({
226
357
  ...plugin.receipt,
@@ -229,6 +360,17 @@ var AgentPluginStore = class {
229
360
  return this.get(id);
230
361
  });
231
362
  }
363
+ setWorkspaceScope(id, workspacePaths) {
364
+ return this.mutate(() => {
365
+ const plugin = this.get(id);
366
+ if (!plugin) throw new Error("Plugin not installed");
367
+ this.write({
368
+ ...plugin.receipt,
369
+ workspacePaths: workspacePaths === void 0 ? plugin.receipt.workspacePaths : workspacePaths === null ? void 0 : [...new Set(workspacePaths.map((path) => existsSync(path) ? realpathSync(path) : resolve(path)))]
370
+ });
371
+ return this.get(id);
372
+ });
373
+ }
232
374
  rollback(id) {
233
375
  return this.mutate(() => {
234
376
  const receipt = this.receipt(id);
@@ -238,6 +380,7 @@ var AgentPluginStore = class {
238
380
  this.write({
239
381
  ...previous,
240
382
  enabled: receipt.enabled,
383
+ workspacePaths: receipt.workspacePaths,
241
384
  previous: receiptFields.parse(receipt)
242
385
  });
243
386
  return this.get(id);
@@ -251,14 +394,21 @@ var AgentPluginStore = class {
251
394
  recursive: true,
252
395
  force: true
253
396
  });
397
+ rmSync(join(this.stateDir, "plugin-revisions", id), {
398
+ recursive: true,
399
+ force: true
400
+ });
254
401
  rmSync(join(this.stateDir, "plugin-health", id), {
255
402
  recursive: true,
256
403
  force: true
257
404
  });
405
+ rmSync(this.pendingPath(id), { force: true });
406
+ rmSync(join(this.stateDir, "plugin-setup", `${id}.json`), { force: true });
258
407
  if (removeData) rmSync(this.dataDir(id), {
259
408
  recursive: true,
260
409
  force: true
261
410
  });
411
+ prunePluginResourceCache(this);
262
412
  });
263
413
  }
264
414
  withSource(source, fn) {
@@ -292,7 +442,7 @@ var AgentPluginStore = class {
292
442
  }
293
443
  }
294
444
  const children = readdirSync(temp);
295
- return fn(existsSync(join(temp, "plugin.json")) ? temp : children.length === 1 ? join(temp, children[0]) : temp);
445
+ return fn(PLUGIN_MANIFEST_PATHS.some((path) => existsSync(join(temp, path))) ? temp : children.length === 1 ? join(temp, children[0]) : temp);
296
446
  } finally {
297
447
  rmSync(temp, {
298
448
  recursive: true,
@@ -0,0 +1,5 @@
1
+ import type { AgentPluginStore, InstalledAgentPlugin } from './store.js';
2
+ export declare function readPluginUserConfig(store: AgentPluginStore, id: string, revision: string): Record<string, unknown>;
3
+ export declare function savePluginUserConfig(store: AgentPluginStore, plugin: InstalledAgentPlugin, input: Record<string, unknown>): Promise<void>;
4
+ export declare function pluginConfigMissing(store: AgentPluginStore, plugin: InstalledAgentPlugin): string[];
5
+ export declare function expandUserConfig(value: string, values: Record<string, unknown>): unknown;
@@ -0,0 +1,49 @@
1
+ import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
2
+ import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
3
+ import { pluginAuthorizations } from "./setup-contract.js";
4
+ import { pluginName } from "./validation.js";
5
+ import { pluginCredentialProviderPrefix } from "./auth.js";
6
+ import { join } from "node:path";
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ import { createHash } from "node:crypto";
9
+ //#region src/extensions/agent-plugins/user-config.ts
10
+ init_credentials();
11
+ init_write_file_atomic();
12
+ function readPluginUserConfig(store, id, revision) {
13
+ const path = join(store.stateDir, "plugin-config", `${pluginName.parse(id)}-${revision}.json`);
14
+ return existsSync(path) ? JSON.parse(readFileSync(path, "utf8")) : {};
15
+ }
16
+ async function savePluginUserConfig(store, plugin, input) {
17
+ const fields = plugin.layout?.userConfig ?? {};
18
+ const values = readPluginUserConfig(store, plugin.id, plugin.receipt.revision);
19
+ for (const [key, value] of Object.entries(input)) {
20
+ const field = fields[key];
21
+ if (!field || typeof value !== field.type || typeof value === "string" && (value.length > 16384 || value.includes("\0"))) throw new Error(`Invalid configuration: ${key}`);
22
+ if (field.sensitive) {
23
+ const provider = `${pluginCredentialProviderPrefix(plugin.id)}config-${createHash("sha256").update(`${plugin.receipt.revision}:${key}`).digest("hex")}`;
24
+ await new CredentialResolver({ stateDir: store.stateDir }).saveApiKey(provider, String(value));
25
+ values[key] = { xopcSecretRef: {
26
+ provider,
27
+ fieldKey: key,
28
+ prefix: ""
29
+ } };
30
+ } else values[key] = value;
31
+ }
32
+ writeTextAtomicSync(join(store.stateDir, "plugin-config", `${plugin.id}-${plugin.receipt.revision}.json`), JSON.stringify(values));
33
+ }
34
+ function pluginConfigMissing(store, plugin) {
35
+ const saved = readPluginUserConfig(store, plugin.id, plugin.receipt.revision);
36
+ const accountFields = new Set(pluginAuthorizations(plugin.manifest).flatMap((value) => value.methods.flatMap((method) => method.type === "form" || method.type === "cli" ? method.fields : [])));
37
+ return Object.entries(plugin.layout?.userConfig ?? {}).filter(([key, field]) => !accountFields.has(key) && field.required && (saved[key] === void 0 || saved[key] === "") && field.default === void 0).map(([key]) => key);
38
+ }
39
+ function expandUserConfig(value, values) {
40
+ const exact = value.match(/^\$\{user_config\.([A-Za-z_][A-Za-z0-9_]*)\}$/);
41
+ if (exact && typeof values[exact[1]] === "object") return values[exact[1]];
42
+ return value.replace(/\$\{user_config\.([A-Za-z_][A-Za-z0-9_]*)\}/g, (_all, key) => {
43
+ if (values[key] === void 0) throw new Error(`Configure ${key} before starting tools`);
44
+ if (typeof values[key] === "object") throw new Error("Sensitive configuration must occupy an entire environment/header value");
45
+ return String(values[key]);
46
+ });
47
+ }
48
+ //#endregion
49
+ export { expandUserConfig, pluginConfigMissing, readPluginUserConfig, savePluginUserConfig };
@@ -1,3 +1,5 @@
1
+ import { pluginResources } from './resources.js';
2
+ import { type PluginLayout } from './formats.js';
1
3
  import { z } from 'zod';
2
4
  export declare const PLUGIN_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json";
3
5
  export declare const MCP_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json";
@@ -28,6 +30,27 @@ declare const serverSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
28
30
  type: z.ZodLiteral<"streamable-http">;
29
31
  url: z.ZodString;
30
32
  headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
33
+ oauth: z.ZodOptional<z.ZodObject<{
34
+ scope: z.ZodOptional<z.ZodString>;
35
+ clientId: z.ZodOptional<z.ZodString>;
36
+ callbackPort: z.ZodOptional<z.ZodNumber>;
37
+ callbackUrl: z.ZodOptional<z.ZodString>;
38
+ clientName: z.ZodOptional<z.ZodString>;
39
+ clientRegistration: z.ZodOptional<z.ZodEnum<{
40
+ dcr: "dcr";
41
+ cimd: "cimd";
42
+ }>>;
43
+ authServerMetadataUrl: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strict>>;
45
+ connectionAuth: z.ZodOptional<z.ZodObject<{
46
+ mode: z.ZodEnum<{
47
+ none: "none";
48
+ oauth: "oauth";
49
+ "api-key": "api-key";
50
+ }>;
51
+ headerName: z.ZodOptional<z.ZodString>;
52
+ prefix: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strict>>;
31
54
  }, z.core.$strict>], "type">;
32
55
  export type PluginManifest = z.infer<typeof manifestSchema>;
33
56
  export type PluginServer = z.infer<typeof serverSchema>;
@@ -36,6 +59,8 @@ export interface PluginDiagnostic {
36
59
  message: string;
37
60
  }
38
61
  export interface PluginInspection {
62
+ resources?: ReturnType<typeof pluginResources>;
63
+ layout?: PluginLayout;
39
64
  manifest: PluginManifest;
40
65
  rootDir: string;
41
66
  skills: Array<{
@@ -50,6 +75,6 @@ export declare function containedPath(root: string, path: string): string;
50
75
  export declare function expandPluginVariables(value: string, root: string, data: string): string;
51
76
  export declare function resolvePluginCwd(cwd: string | undefined, root: string, data: string): string;
52
77
  export declare function validatePluginServer(raw: unknown, root: string, data: string): PluginServer;
53
- export declare function inspectAgentPlugin(rootDir: string, dataDir?: string): PluginInspection;
78
+ export declare function inspectAgentPlugin(rootDir: string, dataDir?: string, importManifest?: Record<string, unknown>): PluginInspection;
54
79
  export declare function pluginServerId(pluginId: string, serverName: string): string;
55
80
  export {};