@xopcai/xopc 0.0.23 → 0.0.25

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 (170) hide show
  1. package/dist/extensions/feishu/xopc.extension.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/agents-C_bPhtBs.js +216 -0
  4. package/dist/gateway/static/root/assets/agents-C_bPhtBs.js.map +1 -0
  5. package/dist/gateway/static/root/assets/apps-page-DbzO48lg.js +2 -0
  6. package/dist/gateway/static/root/assets/apps-page-DbzO48lg.js.map +1 -0
  7. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CebH7fCz.js → attachment-preview-renderer-CxMJMbD2.js} +4 -4
  8. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CebH7fCz.js.map → attachment-preview-renderer-CxMJMbD2.js.map} +1 -1
  9. package/dist/gateway/static/root/assets/{attachment-process-heavy-Dbf1--O6.js → attachment-process-heavy-EFXPGfWk.js} +6 -6
  10. package/dist/gateway/static/root/assets/{attachment-process-heavy-Dbf1--O6.js.map → attachment-process-heavy-EFXPGfWk.js.map} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-utils-core-Dt6UxMPV.js → attachment-utils-core-ECbeoa9H.js} +1 -1
  12. package/dist/gateway/static/root/assets/attachment-utils-core-ECbeoa9H.js.map +1 -0
  13. package/dist/gateway/static/root/assets/channels-settings-CeGoU9v8.js +9 -0
  14. package/dist/gateway/static/root/assets/{channels-settings-CGzrrBlT.js.map → channels-settings-CeGoU9v8.js.map} +1 -1
  15. package/dist/gateway/static/root/assets/cn-BMCV0OMB.js +2 -0
  16. package/dist/gateway/static/root/assets/cn-BMCV0OMB.js.map +1 -0
  17. package/dist/gateway/static/root/assets/cron-page-DpEYUvxB.js +2 -0
  18. package/dist/gateway/static/root/assets/{cron-page-BGCdDf2w.js.map → cron-page-DpEYUvxB.js.map} +1 -1
  19. package/dist/gateway/static/root/assets/cron-utils-Cvv0F3pa.js +3 -0
  20. package/dist/gateway/static/root/assets/{cron-utils-Dnks4wWv.js.map → cron-utils-Cvv0F3pa.js.map} +1 -1
  21. package/dist/gateway/static/root/assets/dist-C41N3YrO.js +2 -0
  22. package/dist/gateway/static/root/assets/{dist-BG1ChbY9.js.map → dist-C41N3YrO.js.map} +1 -1
  23. package/dist/gateway/static/root/assets/{docx-preview-DxcHM3sR.js → docx-preview-F-jKDMNv.js} +2 -2
  24. package/dist/gateway/static/root/assets/{docx-preview-DxcHM3sR.js.map → docx-preview-F-jKDMNv.js.map} +1 -1
  25. package/dist/gateway/static/root/assets/{excel-worksheet-utils-Dk66snKA.js → excel-worksheet-utils-DPfAinZn.js} +1 -1
  26. package/dist/gateway/static/root/assets/{excel-worksheet-utils-Dk66snKA.js.map → excel-worksheet-utils-DPfAinZn.js.map} +1 -1
  27. package/dist/gateway/static/root/assets/extension-debug-page-CkkYZjNP.js +2 -0
  28. package/dist/gateway/static/root/assets/{extension-debug-page-CRC16AbL.js.map → extension-debug-page-CkkYZjNP.js.map} +1 -1
  29. package/dist/gateway/static/root/assets/extension-page-BjUIPVNG.js +2 -0
  30. package/dist/gateway/static/root/assets/{extension-page-BagrJnbm.js.map → extension-page-BjUIPVNG.js.map} +1 -1
  31. package/dist/gateway/static/root/assets/extension-settings-page-CwuFDOdk.js +2 -0
  32. package/dist/gateway/static/root/assets/extension-settings-page-CwuFDOdk.js.map +1 -0
  33. package/dist/gateway/static/root/assets/index-DwzwDCjW.js +150 -0
  34. package/dist/gateway/static/root/assets/index-DwzwDCjW.js.map +1 -0
  35. package/dist/gateway/static/root/assets/index-dhtHG1nU.css +1 -0
  36. package/dist/gateway/static/root/assets/{jszip.min-DVUfmhpE.js → jszip.min-CL3dfyxs.js} +1 -1
  37. package/dist/gateway/static/root/assets/{jszip.min-DVUfmhpE.js.map → jszip.min-CL3dfyxs.js.map} +1 -1
  38. package/dist/gateway/static/root/assets/logs-page-BtwGPuw2.js +2 -0
  39. package/dist/gateway/static/root/assets/{logs-page-Bo9EsE_D.js.map → logs-page-BtwGPuw2.js.map} +1 -1
  40. package/dist/gateway/static/root/assets/{pdf--jE7rvON.js → pdf-CX6ji-QC.js} +1 -1
  41. package/dist/gateway/static/root/assets/{pdf--jE7rvON.js.map → pdf-CX6ji-QC.js.map} +1 -1
  42. package/dist/gateway/static/root/assets/sessions-page-4rKFDn2k.js +2 -0
  43. package/dist/gateway/static/root/assets/{sessions-page-CDgXq8qp.js.map → sessions-page-4rKFDn2k.js.map} +1 -1
  44. package/dist/gateway/static/root/assets/settings-page-iYLSxQYc.js +2 -0
  45. package/dist/gateway/static/root/assets/settings-page-iYLSxQYc.js.map +1 -0
  46. package/dist/gateway/static/root/assets/skills-page-_siDuHeF.js +3 -0
  47. package/dist/gateway/static/root/assets/{skills-page-BRS5qYTw.js.map → skills-page-_siDuHeF.js.map} +1 -1
  48. package/dist/gateway/static/root/assets/vendor-swr-B5fPo7KK.js +2 -0
  49. package/dist/gateway/static/root/assets/{vendor-swr-Dp4nzp5h.js.map → vendor-swr-B5fPo7KK.js.map} +1 -1
  50. package/dist/gateway/static/root/assets/{xlsx-DVk38js7.js → xlsx-CPtvfmVF.js} +1 -1
  51. package/dist/gateway/static/root/assets/{xlsx-DVk38js7.js.map → xlsx-CPtvfmVF.js.map} +1 -1
  52. package/dist/gateway/static/root/index.html +5 -4
  53. package/dist/package.js +1 -1
  54. package/dist/src/agent/image/tool-model-config.js +2 -2
  55. package/dist/src/agent/image/tool-model-config.js.map +1 -1
  56. package/dist/src/agent/memory/dreaming/config.d.ts +20 -0
  57. package/dist/src/agent/memory/dreaming/config.js +44 -0
  58. package/dist/src/agent/memory/dreaming/config.js.map +1 -0
  59. package/dist/src/agent/memory/dreaming/constants.d.ts +8 -0
  60. package/dist/src/agent/memory/dreaming/constants.js +14 -0
  61. package/dist/src/agent/memory/dreaming/constants.js.map +1 -0
  62. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +22 -0
  63. package/dist/src/agent/memory/dreaming/deep-promotion.js +337 -0
  64. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -0
  65. package/dist/src/agent/memory/dreaming/preview.d.ts +26 -0
  66. package/dist/src/agent/memory/dreaming/preview.js +176 -0
  67. package/dist/src/agent/memory/dreaming/preview.js.map +1 -0
  68. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +45 -0
  69. package/dist/src/agent/memory/dreaming/short-term-store.js +187 -0
  70. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -0
  71. package/dist/src/agent/orchestration/agent-orchestrator.js +17 -0
  72. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  73. package/dist/src/agent/service.d.ts +6 -0
  74. package/dist/src/agent/service.js +52 -0
  75. package/dist/src/agent/service.js.map +1 -1
  76. package/dist/src/agent/tools/dreaming-tool.d.ts +7 -0
  77. package/dist/src/agent/tools/dreaming-tool.js +102 -0
  78. package/dist/src/agent/tools/dreaming-tool.js.map +1 -0
  79. package/dist/src/agent/tools/execute-code-tool.js +1 -1
  80. package/dist/src/agent/tools/execute-code-tool.js.map +1 -1
  81. package/dist/src/agent/tools/factory.js +5 -0
  82. package/dist/src/agent/tools/factory.js.map +1 -1
  83. package/dist/src/agent/tools/index.d.ts +1 -0
  84. package/dist/src/agent/tools/index.js +2 -1
  85. package/dist/src/agent/tools/memory-tool.js +9 -2
  86. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  87. package/dist/src/cli/commands/extension-dev.d.ts +2 -0
  88. package/dist/src/cli/commands/extension-dev.js +196 -0
  89. package/dist/src/cli/commands/extension-dev.js.map +1 -0
  90. package/dist/src/cli/commands/extension-marketplace.d.ts +4 -0
  91. package/dist/src/cli/commands/extension-marketplace.js +145 -0
  92. package/dist/src/cli/commands/extension-marketplace.js.map +1 -0
  93. package/dist/src/cli/commands/extension-pack.d.ts +2 -0
  94. package/dist/src/cli/commands/extension-pack.js +242 -0
  95. package/dist/src/cli/commands/extension-pack.js.map +1 -0
  96. package/dist/src/cli/commands/extension.js +13 -0
  97. package/dist/src/cli/commands/extension.js.map +1 -1
  98. package/dist/src/cli/index.js +5 -1
  99. package/dist/src/cli/index.js.map +1 -1
  100. package/dist/src/config/schema.d.ts +39 -0
  101. package/dist/src/config/schema.js +17 -2
  102. package/dist/src/config/schema.js.map +1 -1
  103. package/dist/src/extensions/api.d.ts +6 -1
  104. package/dist/src/extensions/api.js +30 -0
  105. package/dist/src/extensions/api.js.map +1 -1
  106. package/dist/src/extensions/engine-check.d.ts +14 -0
  107. package/dist/src/extensions/engine-check.js +148 -0
  108. package/dist/src/extensions/engine-check.js.map +1 -0
  109. package/dist/src/extensions/loader.js +23 -0
  110. package/dist/src/extensions/loader.js.map +1 -1
  111. package/dist/src/extensions/marketplace.d.ts +24 -0
  112. package/dist/src/extensions/marketplace.js +98 -0
  113. package/dist/src/extensions/marketplace.js.map +1 -0
  114. package/dist/src/extensions/normalize-manifest.js +16 -4
  115. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  116. package/dist/src/extensions/sdk/index.d.ts +2 -0
  117. package/dist/src/extensions/sdk/index.js +2 -1
  118. package/dist/src/extensions/sdk/index.js.map +1 -1
  119. package/dist/src/extensions/sdk/testing.d.ts +49 -3
  120. package/dist/src/extensions/sdk/testing.js +174 -5
  121. package/dist/src/extensions/sdk/testing.js.map +1 -1
  122. package/dist/src/extensions/types/core.d.ts +5 -0
  123. package/dist/src/extensions/types/manifest.d.ts +17 -0
  124. package/dist/src/extensions/when-context.d.ts +6 -0
  125. package/dist/src/extensions/when-context.js +28 -0
  126. package/dist/src/extensions/when-context.js.map +1 -0
  127. package/dist/src/extensions/when-expression.d.ts +11 -0
  128. package/dist/src/extensions/when-expression.js +215 -0
  129. package/dist/src/extensions/when-expression.js.map +1 -0
  130. package/dist/src/gateway/hono/app.js +1 -1
  131. package/dist/src/gateway/hono/app.js.map +1 -1
  132. package/dist/src/gateway/hono/lib/config-payload.d.ts +13 -0
  133. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +28 -0
  134. package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
  135. package/dist/src/gateway/hono/routes/config.js +48 -0
  136. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  137. package/dist/src/gateway/hono/routes/dreaming.d.ts +3 -0
  138. package/dist/src/gateway/hono/routes/dreaming.js +198 -0
  139. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -0
  140. package/dist/src/gateway/hono/routes/index.js +2 -0
  141. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  142. package/dist/src/gateway/lock.js +1 -1
  143. package/dist/src/gateway/service.js +7 -0
  144. package/dist/src/gateway/service.js.map +1 -1
  145. package/dist/src/providers/index.d.ts +6 -3
  146. package/dist/src/providers/index.js +12 -23
  147. package/dist/src/providers/index.js.map +1 -1
  148. package/package.json +2 -1
  149. package/dist/gateway/static/root/assets/agents-BY_DaknM.js +0 -216
  150. package/dist/gateway/static/root/assets/agents-BY_DaknM.js.map +0 -1
  151. package/dist/gateway/static/root/assets/apps-page-BO3nQbJY.js +0 -2
  152. package/dist/gateway/static/root/assets/apps-page-BO3nQbJY.js.map +0 -1
  153. package/dist/gateway/static/root/assets/attachment-utils-core-Dt6UxMPV.js.map +0 -1
  154. package/dist/gateway/static/root/assets/channels-settings-CGzrrBlT.js +0 -9
  155. package/dist/gateway/static/root/assets/cron-page-BGCdDf2w.js +0 -2
  156. package/dist/gateway/static/root/assets/cron-utils-Dnks4wWv.js +0 -3
  157. package/dist/gateway/static/root/assets/dist-BG1ChbY9.js +0 -2
  158. package/dist/gateway/static/root/assets/extension-debug-page-CRC16AbL.js +0 -2
  159. package/dist/gateway/static/root/assets/extension-page-BagrJnbm.js +0 -2
  160. package/dist/gateway/static/root/assets/extension-settings-page-DEpxRKKK.js +0 -2
  161. package/dist/gateway/static/root/assets/extension-settings-page-DEpxRKKK.js.map +0 -1
  162. package/dist/gateway/static/root/assets/index-CYVs9x8D.css +0 -1
  163. package/dist/gateway/static/root/assets/index-KNzRh6gu.js +0 -150
  164. package/dist/gateway/static/root/assets/index-KNzRh6gu.js.map +0 -1
  165. package/dist/gateway/static/root/assets/logs-page-Bo9EsE_D.js +0 -2
  166. package/dist/gateway/static/root/assets/sessions-page-CDgXq8qp.js +0 -2
  167. package/dist/gateway/static/root/assets/settings-page-BWMTFST6.js +0 -2
  168. package/dist/gateway/static/root/assets/settings-page-BWMTFST6.js.map +0 -1
  169. package/dist/gateway/static/root/assets/skills-page-BRS5qYTw.js +0 -3
  170. package/dist/gateway/static/root/assets/vendor-swr-Dp4nzp5h.js +0 -2
@@ -12,6 +12,12 @@ function normalizeReload(raw) {
12
12
  ...supportsHotReload !== void 0 ? { supportsHotReload } : {}
13
13
  };
14
14
  }
15
+ function normalizeEngines(raw) {
16
+ if (!isRecord(raw)) return void 0;
17
+ const xopc = typeof raw.xopc === "string" && raw.xopc.length > 0 ? raw.xopc : void 0;
18
+ if (!xopc) return void 0;
19
+ return { xopc };
20
+ }
15
21
  function normalizeManifestCommands(raw) {
16
22
  if (!Array.isArray(raw)) return void 0;
17
23
  const out = [];
@@ -60,6 +66,7 @@ function normalizeExtensionManifest(raw) {
60
66
  contracts: normalizeContracts(raw.contracts),
61
67
  setup: normalizeSetup(raw.setup),
62
68
  reload: normalizeReload(raw.reload),
69
+ engines: normalizeEngines(raw.engines),
63
70
  commands: normalizeManifestCommands(raw.commands),
64
71
  ui: normalizeUiManifest(raw.ui)
65
72
  };
@@ -129,7 +136,8 @@ function normalizeSidebarPanels(raw) {
129
136
  title,
130
137
  entrypoint,
131
138
  icon: typeof item.icon === "string" ? item.icon : void 0,
132
- defaultVisible: typeof item.defaultVisible === "boolean" ? item.defaultVisible : void 0
139
+ defaultVisible: typeof item.defaultVisible === "boolean" ? item.defaultVisible : void 0,
140
+ when: typeof item.when === "string" && item.when.length > 0 ? item.when : void 0
133
141
  });
134
142
  }
135
143
  return out.length ? out : void 0;
@@ -203,7 +211,8 @@ function normalizePages(raw) {
203
211
  path,
204
212
  entrypoint,
205
213
  showInNav: typeof item.showInNav === "boolean" ? item.showInNav : void 0,
206
- navIcon: typeof item.navIcon === "string" ? item.navIcon : void 0
214
+ navIcon: typeof item.navIcon === "string" ? item.navIcon : void 0,
215
+ when: typeof item.when === "string" && item.when.length > 0 ? item.when : void 0
207
216
  });
208
217
  }
209
218
  return out.length ? out : void 0;
@@ -220,7 +229,9 @@ function normalizeCommands(raw) {
220
229
  id,
221
230
  title,
222
231
  shortcut: typeof item.shortcut === "string" ? item.shortcut : void 0,
223
- opensPanel: typeof item.opensPanel === "string" ? item.opensPanel : void 0
232
+ opensPanel: typeof item.opensPanel === "string" ? item.opensPanel : void 0,
233
+ chatAlias: typeof item.chatAlias === "string" && item.chatAlias.length > 0 ? item.chatAlias : void 0,
234
+ when: typeof item.when === "string" && item.when.length > 0 ? item.when : void 0
224
235
  });
225
236
  }
226
237
  return out.length ? out : void 0;
@@ -238,7 +249,8 @@ function normalizeStatusBarItems(raw) {
238
249
  id,
239
250
  entrypoint,
240
251
  position: position === "left" || position === "right" ? position : void 0,
241
- width: typeof item.width === "number" ? item.width : void 0
252
+ width: typeof item.width === "number" ? item.width : void 0,
253
+ when: typeof item.when === "string" && item.when.length > 0 ? item.when : void 0
242
254
  });
243
255
  }
244
256
  return out.length ? out : void 0;
@@ -1 +1 @@
1
- {"version":3,"file":"normalize-manifest.js","names":[],"sources":["../../../src/extensions/normalize-manifest.ts"],"sourcesContent":["import type {\n ActivationDeclaration,\n ChatWidgetContribution,\n ChatWidgetMatch,\n CommandContribution,\n ContractDeclaration,\n ExtensionManifest,\n ExtensionManifestCommand,\n ExtensionUiContributions,\n ExtensionUiManifest,\n ExtensionUiPermission,\n ModelSupportDeclaration,\n PageContribution,\n ProviderAuthChoice,\n SettingsPanelContribution,\n SetupDeclaration,\n SidebarPanelContribution,\n StatusBarItemContribution,\n} from './types/manifest.js';\nimport type { ExtensionKind } from './types/core.js';\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction normalizeReload(raw: unknown): ExtensionManifest['reload'] {\n if (!isRecord(raw)) return undefined;\n const configPrefixes = Array.isArray(raw.configPrefixes)\n ? raw.configPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const supportsHotReload =\n typeof raw.supportsHotReload === 'boolean' ? raw.supportsHotReload : undefined;\n if (!configPrefixes?.length && supportsHotReload === undefined) return undefined;\n return {\n ...(configPrefixes?.length ? { configPrefixes } : {}),\n ...(supportsHotReload !== undefined ? { supportsHotReload } : {}),\n };\n}\n\nfunction normalizeManifestCommands(raw: unknown): ExtensionManifestCommand[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ExtensionManifestCommand[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const name = typeof item.name === 'string' ? item.name.trim() : '';\n const description = typeof item.description === 'string' ? item.description : '';\n if (!name || !description) continue;\n const aliases = Array.isArray(item.aliases)\n ? item.aliases.filter((x): x is string => typeof x === 'string')\n : undefined;\n const scope = Array.isArray(item.scope)\n ? item.scope.filter(\n (x): x is 'global' | 'private' | 'group' =>\n x === 'global' || x === 'private' || x === 'group',\n )\n : undefined;\n const examples = Array.isArray(item.examples)\n ? item.examples.filter((x): x is string => typeof x === 'string')\n : undefined;\n out.push({\n name,\n description,\n ...(aliases?.length ? { aliases } : {}),\n ...(scope?.length ? { scope } : {}),\n ...(examples?.length ? { examples } : {}),\n });\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * Normalize raw JSON manifest into ExtensionManifest with stable optional fields.\n */\nexport function normalizeExtensionManifest(raw: Record<string, unknown>): ExtensionManifest {\n const id = String(raw.id ?? '');\n return {\n id,\n name: typeof raw.name === 'string' && raw.name.length > 0 ? raw.name : id,\n description: typeof raw.description === 'string' ? raw.description : undefined,\n version: typeof raw.version === 'string' ? raw.version : undefined,\n kind: raw.kind as ExtensionKind | undefined,\n main: typeof raw.main === 'string' ? raw.main : undefined,\n configSchema: isRecord(raw.configSchema) ? (raw.configSchema as Record<string, unknown>) : undefined,\n dependencies: isRecord(raw.dependencies) ? (raw.dependencies as Record<string, string>) : undefined,\n\n enabledByDefault: typeof raw.enabledByDefault === 'boolean' ? raw.enabledByDefault : undefined,\n legacyExtensionIds: Array.isArray(raw.legacyExtensionIds)\n ? raw.legacyExtensionIds.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n providers: Array.isArray(raw.providers)\n ? raw.providers.filter((x): x is string => typeof x === 'string')\n : undefined,\n providerAuthEnvVars: normalizeStringArrayMap(raw.providerAuthEnvVars),\n providerAuthChoices: normalizeProviderAuthChoices(raw.providerAuthChoices),\n modelSupport: normalizeModelSupport(raw.modelSupport),\n autoEnableWhenConfiguredProviders: Array.isArray(raw.autoEnableWhenConfiguredProviders)\n ? raw.autoEnableWhenConfiguredProviders.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n channels: Array.isArray(raw.channels)\n ? raw.channels.filter((x): x is string => typeof x === 'string')\n : undefined,\n channelEnvVars: normalizeStringArrayMap(raw.channelEnvVars),\n\n activation: normalizeActivation(raw.activation),\n contracts: normalizeContracts(raw.contracts),\n setup: normalizeSetup(raw.setup),\n reload: normalizeReload(raw.reload),\n commands: normalizeManifestCommands(raw.commands),\n ui: normalizeUiManifest(raw.ui),\n };\n}\n\nconst VALID_UI_PERMISSIONS = new Set<ExtensionUiPermission>([\n 'agent.send',\n 'agent.subscribe',\n 'session.read',\n 'session.write',\n 'config.read',\n 'config.write',\n 'storage',\n 'notification',\n 'clipboard',\n 'theme',\n 'workspace.read',\n 'workspace.write',\n]);\n\nexport function normalizeUiManifest(raw: unknown): ExtensionUiManifest | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!isRecord(raw)) return undefined;\n const main = typeof raw.main === 'string' && raw.main.length > 0 ? raw.main : undefined;\n const icon = typeof raw.icon === 'string' && raw.icon.length > 0 ? raw.icon : undefined;\n let permissions: ExtensionUiPermission[] | undefined;\n if (Array.isArray(raw.permissions)) {\n const p = raw.permissions.filter(\n (x): x is ExtensionUiPermission =>\n typeof x === 'string' && VALID_UI_PERMISSIONS.has(x as ExtensionUiPermission),\n );\n permissions = p.length ? p : undefined;\n }\n const contributions = normalizeUiContributions(raw.contributions);\n if (!main && !icon && !permissions && !contributions) return undefined;\n return {\n ...(main !== undefined ? { main } : {}),\n ...(icon !== undefined ? { icon } : {}),\n ...(permissions !== undefined ? { permissions } : {}),\n ...(contributions !== undefined ? { contributions } : {}),\n };\n}\n\nfunction normalizeUiContributions(raw: unknown): ExtensionUiContributions | undefined {\n if (!isRecord(raw)) return undefined;\n const sidebarPanels = normalizeSidebarPanels(raw.sidebarPanels);\n const settingsPanels = normalizeSettingsPanels(raw.settingsPanels);\n const chatWidgets = normalizeChatWidgets(raw.chatWidgets);\n const pages = normalizePages(raw.pages);\n const commands = normalizeCommands(raw.commands);\n const statusBarItems = normalizeStatusBarItems(raw.statusBarItems);\n const out: ExtensionUiContributions = {\n ...(sidebarPanels ? { sidebarPanels } : {}),\n ...(settingsPanels ? { settingsPanels } : {}),\n ...(chatWidgets ? { chatWidgets } : {}),\n ...(pages ? { pages } : {}),\n ...(commands ? { commands } : {}),\n ...(statusBarItems ? { statusBarItems } : {}),\n };\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeSidebarPanels(raw: unknown): SidebarPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SidebarPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n icon: typeof item.icon === 'string' ? item.icon : undefined,\n defaultVisible: typeof item.defaultVisible === 'boolean' ? item.defaultVisible : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeSettingsPanels(raw: unknown): SettingsPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SettingsPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n order: typeof item.order === 'number' ? item.order : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeChatWidgetMatch(raw: unknown): ChatWidgetMatch | undefined {\n if (!isRecord(raw)) return undefined;\n const toolName = typeof raw.toolName === 'string' ? raw.toolName : undefined;\n const contentType = typeof raw.contentType === 'string' ? raw.contentType : undefined;\n let metadata: Record<string, unknown> | undefined;\n if (isRecord(raw.metadata)) {\n metadata = { ...raw.metadata };\n }\n if (!toolName && !contentType && !metadata) return undefined;\n return { toolName, contentType, metadata };\n}\n\nfunction normalizeChatWidgets(raw: unknown): ChatWidgetContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ChatWidgetContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n const match = normalizeChatWidgetMatch(item.match);\n if (!match) continue;\n out.push({\n id,\n title,\n entrypoint,\n match,\n maxHeight: typeof item.maxHeight === 'number' ? item.maxHeight : undefined,\n interactive: typeof item.interactive === 'boolean' ? item.interactive : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizePages(raw: unknown): PageContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: PageContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const path = item.path;\n const entrypoint = item.entrypoint;\n if (\n typeof id !== 'string' ||\n typeof title !== 'string' ||\n typeof path !== 'string' ||\n typeof entrypoint !== 'string'\n ) {\n continue;\n }\n out.push({\n id,\n title,\n path,\n entrypoint,\n showInNav: typeof item.showInNav === 'boolean' ? item.showInNav : undefined,\n navIcon: typeof item.navIcon === 'string' ? item.navIcon : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeCommands(raw: unknown): CommandContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: CommandContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n if (typeof id !== 'string' || typeof title !== 'string') continue;\n out.push({\n id,\n title,\n shortcut: typeof item.shortcut === 'string' ? item.shortcut : undefined,\n opensPanel: typeof item.opensPanel === 'string' ? item.opensPanel : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStatusBarItems(raw: unknown): StatusBarItemContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: StatusBarItemContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof entrypoint !== 'string') continue;\n const position = item.position;\n out.push({\n id,\n entrypoint,\n position: position === 'left' || position === 'right' ? position : undefined,\n width: typeof item.width === 'number' ? item.width : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStringArrayMap(\n raw: unknown,\n): Record<string, string[]> | undefined {\n if (!isRecord(raw)) return undefined;\n const out: Record<string, string[]> = {};\n for (const [k, v] of Object.entries(raw)) {\n if (Array.isArray(v)) {\n const arr = v.filter((x): x is string => typeof x === 'string');\n if (arr.length) out[k] = arr;\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeProviderAuthChoices(raw: unknown): ProviderAuthChoice[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ProviderAuthChoice[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const provider = item.provider;\n const method = item.method;\n const choiceId = item.choiceId;\n const choiceLabel = item.choiceLabel;\n if (\n typeof provider !== 'string' ||\n typeof choiceId !== 'string' ||\n typeof choiceLabel !== 'string' ||\n (method !== 'api-key' && method !== 'oauth' && method !== 'cli' && method !== 'env')\n ) {\n continue;\n }\n out.push({\n provider,\n method,\n choiceId,\n choiceLabel,\n choiceHint: typeof item.choiceHint === 'string' ? item.choiceHint : undefined,\n groupId: typeof item.groupId === 'string' ? item.groupId : undefined,\n groupLabel: typeof item.groupLabel === 'string' ? item.groupLabel : undefined,\n groupHint: typeof item.groupHint === 'string' ? item.groupHint : undefined,\n cliFlag: typeof item.cliFlag === 'string' ? item.cliFlag : undefined,\n cliOption: typeof item.cliOption === 'string' ? item.cliOption : undefined,\n cliDescription: typeof item.cliDescription === 'string' ? item.cliDescription : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeModelSupport(raw: unknown): ModelSupportDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const modelPrefixes = Array.isArray(raw.modelPrefixes)\n ? raw.modelPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const modelPatterns = Array.isArray(raw.modelPatterns)\n ? raw.modelPatterns.filter((x): x is string => typeof x === 'string')\n : undefined;\n if (!modelPrefixes?.length && !modelPatterns?.length) return undefined;\n return { modelPrefixes, modelPatterns };\n}\n\nfunction normalizeActivation(raw: unknown): ActivationDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const onProviders = Array.isArray(raw.onProviders)\n ? raw.onProviders.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onCommands = Array.isArray(raw.onCommands)\n ? raw.onCommands.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onChannels = Array.isArray(raw.onChannels)\n ? raw.onChannels.filter((x): x is string => typeof x === 'string')\n : undefined;\n const capRaw = raw.onCapabilities;\n const onCapabilities = Array.isArray(capRaw)\n ? capRaw.filter(\n (x): x is 'provider' | 'channel' | 'tool' | 'hook' =>\n x === 'provider' || x === 'channel' || x === 'tool' || x === 'hook',\n )\n : undefined;\n if (!onProviders?.length && !onCommands?.length && !onChannels?.length && !onCapabilities?.length) {\n return undefined;\n }\n return { onProviders, onCommands, onChannels, onCapabilities };\n}\n\nfunction normalizeContracts(raw: unknown): ContractDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const pick = (k: string) =>\n Array.isArray(raw[k]) ? raw[k].filter((x: unknown): x is string => typeof x === 'string') : undefined;\n const c: ContractDeclaration = {\n mediaUnderstandingProviders: pick('mediaUnderstandingProviders'),\n speechProviders: pick('speechProviders'),\n imageGenerationProviders: pick('imageGenerationProviders'),\n webSearchProviders: pick('webSearchProviders'),\n memoryProviders: pick('memoryProviders'),\n };\n if (\n !c.mediaUnderstandingProviders?.length &&\n !c.speechProviders?.length &&\n !c.imageGenerationProviders?.length &&\n !c.webSearchProviders?.length &&\n !c.memoryProviders?.length\n ) {\n return undefined;\n }\n return c;\n}\n\nfunction normalizeSetup(raw: unknown): SetupDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const requiresRuntime = typeof raw.requiresRuntime === 'boolean' ? raw.requiresRuntime : undefined;\n let providers: SetupDeclaration['providers'];\n if (Array.isArray(raw.providers)) {\n providers = [];\n for (const p of raw.providers) {\n if (!isRecord(p) || typeof p.id !== 'string') continue;\n providers.push({\n id: p.id,\n authMethods: Array.isArray(p.authMethods)\n ? p.authMethods.filter((x): x is string => typeof x === 'string')\n : undefined,\n envVars: Array.isArray(p.envVars)\n ? p.envVars.filter((x): x is string => typeof x === 'string')\n : undefined,\n });\n }\n if (providers.length === 0) providers = undefined;\n }\n if (!providers && requiresRuntime === undefined) return undefined;\n return { providers, requiresRuntime };\n}\n"],"mappings":";AAqBA,SAAS,SAAS,GAA0C;AAC1D,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,EAAE;;AAGjE,SAAS,gBAAgB,KAA2C;AAClE,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,iBAAiB,MAAM,QAAQ,IAAI,eAAe,GACpD,IAAI,eAAe,QAAQ,MAAmB,OAAO,MAAM,SAAS,GACpE,KAAA;CACJ,MAAM,oBACJ,OAAO,IAAI,sBAAsB,YAAY,IAAI,oBAAoB,KAAA;AACvE,KAAI,CAAC,gBAAgB,UAAU,sBAAsB,KAAA,EAAW,QAAO,KAAA;AACvE,QAAO;EACL,GAAI,gBAAgB,SAAS,EAAE,gBAAgB,GAAG,EAAE;EACpD,GAAI,sBAAsB,KAAA,IAAY,EAAE,mBAAmB,GAAG,EAAE;EACjE;;AAGH,SAAS,0BAA0B,KAAsD;AACvF,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAAkC,EAAE;AAC1C,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,KAAK,MAAM,GAAG;EAChE,MAAM,cAAc,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAC9E,MAAI,CAAC,QAAQ,CAAC,YAAa;EAC3B,MAAM,UAAU,MAAM,QAAQ,KAAK,QAAQ,GACvC,KAAK,QAAQ,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAC9D,KAAA;EACJ,MAAM,QAAQ,MAAM,QAAQ,KAAK,MAAM,GACnC,KAAK,MAAM,QACR,MACC,MAAM,YAAY,MAAM,aAAa,MAAM,QAC9C,GACD,KAAA;EACJ,MAAM,WAAW,MAAM,QAAQ,KAAK,SAAS,GACzC,KAAK,SAAS,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAC/D,KAAA;AACJ,MAAI,KAAK;GACP;GACA;GACA,GAAI,SAAS,SAAS,EAAE,SAAS,GAAG,EAAE;GACtC,GAAI,OAAO,SAAS,EAAE,OAAO,GAAG,EAAE;GAClC,GAAI,UAAU,SAAS,EAAE,UAAU,GAAG,EAAE;GACzC,CAAC;;AAEJ,QAAO,IAAI,SAAS,IAAI,MAAM,KAAA;;;;;AAMhC,SAAgB,2BAA2B,KAAiD;CAC1F,MAAM,KAAK,OAAO,IAAI,MAAM,GAAG;AAC/B,QAAO;EACL;EACA,MAAM,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO;EACvE,aAAa,OAAO,IAAI,gBAAgB,WAAW,IAAI,cAAc,KAAA;EACrE,SAAS,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU,KAAA;EACzD,MAAM,IAAI;EACV,MAAM,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,KAAA;EAChD,cAAc,SAAS,IAAI,aAAa,GAAI,IAAI,eAA2C,KAAA;EAC3F,cAAc,SAAS,IAAI,aAAa,GAAI,IAAI,eAA0C,KAAA;EAE1F,kBAAkB,OAAO,IAAI,qBAAqB,YAAY,IAAI,mBAAmB,KAAA;EACrF,oBAAoB,MAAM,QAAQ,IAAI,mBAAmB,GACrD,IAAI,mBAAmB,QAAQ,MAAmB,OAAO,MAAM,SAAS,GACxE,KAAA;EAEJ,WAAW,MAAM,QAAQ,IAAI,UAAU,GACnC,IAAI,UAAU,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAC/D,KAAA;EACJ,qBAAqB,wBAAwB,IAAI,oBAAoB;EACrE,qBAAqB,6BAA6B,IAAI,oBAAoB;EAC1E,cAAc,sBAAsB,IAAI,aAAa;EACrD,mCAAmC,MAAM,QAAQ,IAAI,kCAAkC,GACnF,IAAI,kCAAkC,QAAQ,MAAmB,OAAO,MAAM,SAAS,GACvF,KAAA;EAEJ,UAAU,MAAM,QAAQ,IAAI,SAAS,GACjC,IAAI,SAAS,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAC9D,KAAA;EACJ,gBAAgB,wBAAwB,IAAI,eAAe;EAE3D,YAAY,oBAAoB,IAAI,WAAW;EAC/C,WAAW,mBAAmB,IAAI,UAAU;EAC5C,OAAO,eAAe,IAAI,MAAM;EAChC,QAAQ,gBAAgB,IAAI,OAAO;EACnC,UAAU,0BAA0B,IAAI,SAAS;EACjD,IAAI,oBAAoB,IAAI,GAAG;EAChC;;AAGH,MAAM,uBAAuB,IAAI,IAA2B;CAC1D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAgB,oBAAoB,KAA+C;AACjF,KAAI,QAAQ,KAAA,KAAa,QAAQ,KAAM,QAAO,KAAA;AAC9C,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,OAAO,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO,KAAA;CAC9E,MAAM,OAAO,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO,KAAA;CAC9E,IAAI;AACJ,KAAI,MAAM,QAAQ,IAAI,YAAY,EAAE;EAClC,MAAM,IAAI,IAAI,YAAY,QACvB,MACC,OAAO,MAAM,YAAY,qBAAqB,IAAI,EAA2B,CAChF;AACD,gBAAc,EAAE,SAAS,IAAI,KAAA;;CAE/B,MAAM,gBAAgB,yBAAyB,IAAI,cAAc;AACjE,KAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,cAAe,QAAO,KAAA;AAC7D,QAAO;EACL,GAAI,SAAS,KAAA,IAAY,EAAE,MAAM,GAAG,EAAE;EACtC,GAAI,SAAS,KAAA,IAAY,EAAE,MAAM,GAAG,EAAE;EACtC,GAAI,gBAAgB,KAAA,IAAY,EAAE,aAAa,GAAG,EAAE;EACpD,GAAI,kBAAkB,KAAA,IAAY,EAAE,eAAe,GAAG,EAAE;EACzD;;AAGH,SAAS,yBAAyB,KAAoD;AACpF,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,gBAAgB,uBAAuB,IAAI,cAAc;CAC/D,MAAM,iBAAiB,wBAAwB,IAAI,eAAe;CAClE,MAAM,cAAc,qBAAqB,IAAI,YAAY;CACzD,MAAM,QAAQ,eAAe,IAAI,MAAM;CACvC,MAAM,WAAW,kBAAkB,IAAI,SAAS;CAChD,MAAM,iBAAiB,wBAAwB,IAAI,eAAe;CAClE,MAAM,MAAgC;EACpC,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;EAC1C,GAAI,iBAAiB,EAAE,gBAAgB,GAAG,EAAE;EAC5C,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;EACtC,GAAI,QAAQ,EAAE,OAAO,GAAG,EAAE;EAC1B,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;EAChC,GAAI,iBAAiB,EAAE,gBAAgB,GAAG,EAAE;EAC7C;AACD,QAAO,OAAO,KAAK,IAAI,CAAC,SAAS,MAAM,KAAA;;AAGzC,SAAS,uBAAuB,KAAsD;AACpF,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAAkC,EAAE;AAC1C,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,KAAK,KAAK;EAChB,MAAM,QAAQ,KAAK;EACnB,MAAM,aAAa,KAAK;AACxB,MAAI,OAAO,OAAO,YAAY,OAAO,UAAU,YAAY,OAAO,eAAe,SAC/E;AAEF,MAAI,KAAK;GACP;GACA;GACA;GACA,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAA;GAClD,gBAAgB,OAAO,KAAK,mBAAmB,YAAY,KAAK,iBAAiB,KAAA;GAClF,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,wBAAwB,KAAuD;AACtF,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAAmC,EAAE;AAC3C,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,KAAK,KAAK;EAChB,MAAM,QAAQ,KAAK;EACnB,MAAM,aAAa,KAAK;AACxB,MAAI,OAAO,OAAO,YAAY,OAAO,UAAU,YAAY,OAAO,eAAe,SAC/E;AAEF,MAAI,KAAK;GACP;GACA;GACA;GACA,OAAO,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA;GACtD,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,yBAAyB,KAA2C;AAC3E,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW,KAAA;CACnE,MAAM,cAAc,OAAO,IAAI,gBAAgB,WAAW,IAAI,cAAc,KAAA;CAC5E,IAAI;AACJ,KAAI,SAAS,IAAI,SAAS,CACxB,YAAW,EAAE,GAAG,IAAI,UAAU;AAEhC,KAAI,CAAC,YAAY,CAAC,eAAe,CAAC,SAAU,QAAO,KAAA;AACnD,QAAO;EAAE;EAAU;EAAa;EAAU;;AAG5C,SAAS,qBAAqB,KAAoD;AAChF,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAAgC,EAAE;AACxC,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,KAAK,KAAK;EAChB,MAAM,QAAQ,KAAK;EACnB,MAAM,aAAa,KAAK;AACxB,MAAI,OAAO,OAAO,YAAY,OAAO,UAAU,YAAY,OAAO,eAAe,SAC/E;EAEF,MAAM,QAAQ,yBAAyB,KAAK,MAAM;AAClD,MAAI,CAAC,MAAO;AACZ,MAAI,KAAK;GACP;GACA;GACA;GACA;GACA,WAAW,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY,KAAA;GACjE,aAAa,OAAO,KAAK,gBAAgB,YAAY,KAAK,cAAc,KAAA;GACzE,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,eAAe,KAA8C;AACpE,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAA0B,EAAE;AAClC,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,KAAK,KAAK;EAChB,MAAM,QAAQ,KAAK;EACnB,MAAM,OAAO,KAAK;EAClB,MAAM,aAAa,KAAK;AACxB,MACE,OAAO,OAAO,YACd,OAAO,UAAU,YACjB,OAAO,SAAS,YAChB,OAAO,eAAe,SAEtB;AAEF,MAAI,KAAK;GACP;GACA;GACA;GACA;GACA,WAAW,OAAO,KAAK,cAAc,YAAY,KAAK,YAAY,KAAA;GAClE,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAA;GAC5D,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,kBAAkB,KAAiD;AAC1E,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAA6B,EAAE;AACrC,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,KAAK,KAAK;EAChB,MAAM,QAAQ,KAAK;AACnB,MAAI,OAAO,OAAO,YAAY,OAAO,UAAU,SAAU;AACzD,MAAI,KAAK;GACP;GACA;GACA,UAAU,OAAO,KAAK,aAAa,WAAW,KAAK,WAAW,KAAA;GAC9D,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa,KAAA;GACrE,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,wBAAwB,KAAuD;AACtF,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAAmC,EAAE;AAC3C,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,KAAK,KAAK;EAChB,MAAM,aAAa,KAAK;AACxB,MAAI,OAAO,OAAO,YAAY,OAAO,eAAe,SAAU;EAC9D,MAAM,WAAW,KAAK;AACtB,MAAI,KAAK;GACP;GACA;GACA,UAAU,aAAa,UAAU,aAAa,UAAU,WAAW,KAAA;GACnE,OAAO,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA;GACtD,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,wBACP,KACsC;AACtC,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,MAAgC,EAAE;AACxC,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,IAAI,CACtC,KAAI,MAAM,QAAQ,EAAE,EAAE;EACpB,MAAM,MAAM,EAAE,QAAQ,MAAmB,OAAO,MAAM,SAAS;AAC/D,MAAI,IAAI,OAAQ,KAAI,KAAK;;AAG7B,QAAO,OAAO,KAAK,IAAI,CAAC,SAAS,MAAM,KAAA;;AAGzC,SAAS,6BAA6B,KAAgD;AACpF,KAAI,CAAC,MAAM,QAAQ,IAAI,CAAE,QAAO,KAAA;CAChC,MAAM,MAA4B,EAAE;AACpC,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,CAAC,SAAS,KAAK,CAAE;EACrB,MAAM,WAAW,KAAK;EACtB,MAAM,SAAS,KAAK;EACpB,MAAM,WAAW,KAAK;EACtB,MAAM,cAAc,KAAK;AACzB,MACE,OAAO,aAAa,YACpB,OAAO,aAAa,YACpB,OAAO,gBAAgB,YACtB,WAAW,aAAa,WAAW,WAAW,WAAW,SAAS,WAAW,MAE9E;AAEF,MAAI,KAAK;GACP;GACA;GACA;GACA;GACA,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa,KAAA;GACpE,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAA;GAC3D,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa,KAAA;GACpE,WAAW,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY,KAAA;GACjE,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAA;GAC3D,WAAW,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY,KAAA;GACjE,gBAAgB,OAAO,KAAK,mBAAmB,WAAW,KAAK,iBAAiB,KAAA;GACjF,CAAC;;AAEJ,QAAO,IAAI,SAAS,MAAM,KAAA;;AAG5B,SAAS,sBAAsB,KAAmD;AAChF,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,gBAAgB,MAAM,QAAQ,IAAI,cAAc,GAClD,IAAI,cAAc,QAAQ,MAAmB,OAAO,MAAM,SAAS,GACnE,KAAA;CACJ,MAAM,gBAAgB,MAAM,QAAQ,IAAI,cAAc,GAClD,IAAI,cAAc,QAAQ,MAAmB,OAAO,MAAM,SAAS,GACnE,KAAA;AACJ,KAAI,CAAC,eAAe,UAAU,CAAC,eAAe,OAAQ,QAAO,KAAA;AAC7D,QAAO;EAAE;EAAe;EAAe;;AAGzC,SAAS,oBAAoB,KAAiD;AAC5E,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,cAAc,MAAM,QAAQ,IAAI,YAAY,GAC9C,IAAI,YAAY,QAAQ,MAAmB,OAAO,MAAM,SAAS,GACjE,KAAA;CACJ,MAAM,aAAa,MAAM,QAAQ,IAAI,WAAW,GAC5C,IAAI,WAAW,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAChE,KAAA;CACJ,MAAM,aAAa,MAAM,QAAQ,IAAI,WAAW,GAC5C,IAAI,WAAW,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAChE,KAAA;CACJ,MAAM,SAAS,IAAI;CACnB,MAAM,iBAAiB,MAAM,QAAQ,OAAO,GACxC,OAAO,QACJ,MACC,MAAM,cAAc,MAAM,aAAa,MAAM,UAAU,MAAM,OAChE,GACD,KAAA;AACJ,KAAI,CAAC,aAAa,UAAU,CAAC,YAAY,UAAU,CAAC,YAAY,UAAU,CAAC,gBAAgB,OACzF;AAEF,QAAO;EAAE;EAAa;EAAY;EAAY;EAAgB;;AAGhE,SAAS,mBAAmB,KAA+C;AACzE,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,QAAQ,MACZ,MAAM,QAAQ,IAAI,GAAG,GAAG,IAAI,GAAG,QAAQ,MAA4B,OAAO,MAAM,SAAS,GAAG,KAAA;CAC9F,MAAM,IAAyB;EAC7B,6BAA6B,KAAK,8BAA8B;EAChE,iBAAiB,KAAK,kBAAkB;EACxC,0BAA0B,KAAK,2BAA2B;EAC1D,oBAAoB,KAAK,qBAAqB;EAC9C,iBAAiB,KAAK,kBAAkB;EACzC;AACD,KACE,CAAC,EAAE,6BAA6B,UAChC,CAAC,EAAE,iBAAiB,UACpB,CAAC,EAAE,0BAA0B,UAC7B,CAAC,EAAE,oBAAoB,UACvB,CAAC,EAAE,iBAAiB,OAEpB;AAEF,QAAO;;AAGT,SAAS,eAAe,KAA4C;AAClE,KAAI,CAAC,SAAS,IAAI,CAAE,QAAO,KAAA;CAC3B,MAAM,kBAAkB,OAAO,IAAI,oBAAoB,YAAY,IAAI,kBAAkB,KAAA;CACzF,IAAI;AACJ,KAAI,MAAM,QAAQ,IAAI,UAAU,EAAE;AAChC,cAAY,EAAE;AACd,OAAK,MAAM,KAAK,IAAI,WAAW;AAC7B,OAAI,CAAC,SAAS,EAAE,IAAI,OAAO,EAAE,OAAO,SAAU;AAC9C,aAAU,KAAK;IACb,IAAI,EAAE;IACN,aAAa,MAAM,QAAQ,EAAE,YAAY,GACrC,EAAE,YAAY,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAC/D,KAAA;IACJ,SAAS,MAAM,QAAQ,EAAE,QAAQ,GAC7B,EAAE,QAAQ,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAC3D,KAAA;IACL,CAAC;;AAEJ,MAAI,UAAU,WAAW,EAAG,aAAY,KAAA;;AAE1C,KAAI,CAAC,aAAa,oBAAoB,KAAA,EAAW,QAAO,KAAA;AACxD,QAAO;EAAE;EAAW;EAAiB"}
1
+ {"version":3,"file":"normalize-manifest.js","names":[],"sources":["../../../src/extensions/normalize-manifest.ts"],"sourcesContent":["import type {\n ActivationDeclaration,\n ChatWidgetContribution,\n ChatWidgetMatch,\n CommandContribution,\n ContractDeclaration,\n EnginesDeclaration,\n ExtensionManifest,\n ExtensionManifestCommand,\n ExtensionUiContributions,\n ExtensionUiManifest,\n ExtensionUiPermission,\n ModelSupportDeclaration,\n PageContribution,\n ProviderAuthChoice,\n SettingsPanelContribution,\n SetupDeclaration,\n SidebarPanelContribution,\n StatusBarItemContribution,\n} from './types/manifest.js';\nimport type { ExtensionKind } from './types/core.js';\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction normalizeReload(raw: unknown): ExtensionManifest['reload'] {\n if (!isRecord(raw)) return undefined;\n const configPrefixes = Array.isArray(raw.configPrefixes)\n ? raw.configPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const supportsHotReload =\n typeof raw.supportsHotReload === 'boolean' ? raw.supportsHotReload : undefined;\n if (!configPrefixes?.length && supportsHotReload === undefined) return undefined;\n return {\n ...(configPrefixes?.length ? { configPrefixes } : {}),\n ...(supportsHotReload !== undefined ? { supportsHotReload } : {}),\n };\n}\n\nfunction normalizeEngines(raw: unknown): EnginesDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const xopc = typeof raw.xopc === 'string' && raw.xopc.length > 0 ? raw.xopc : undefined;\n if (!xopc) return undefined;\n return { xopc };\n}\n\nfunction normalizeManifestCommands(raw: unknown): ExtensionManifestCommand[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ExtensionManifestCommand[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const name = typeof item.name === 'string' ? item.name.trim() : '';\n const description = typeof item.description === 'string' ? item.description : '';\n if (!name || !description) continue;\n const aliases = Array.isArray(item.aliases)\n ? item.aliases.filter((x): x is string => typeof x === 'string')\n : undefined;\n const scope = Array.isArray(item.scope)\n ? item.scope.filter(\n (x): x is 'global' | 'private' | 'group' =>\n x === 'global' || x === 'private' || x === 'group',\n )\n : undefined;\n const examples = Array.isArray(item.examples)\n ? item.examples.filter((x): x is string => typeof x === 'string')\n : undefined;\n out.push({\n name,\n description,\n ...(aliases?.length ? { aliases } : {}),\n ...(scope?.length ? { scope } : {}),\n ...(examples?.length ? { examples } : {}),\n });\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * Normalize raw JSON manifest into ExtensionManifest with stable optional fields.\n */\nexport function normalizeExtensionManifest(raw: Record<string, unknown>): ExtensionManifest {\n const id = String(raw.id ?? '');\n return {\n id,\n name: typeof raw.name === 'string' && raw.name.length > 0 ? raw.name : id,\n description: typeof raw.description === 'string' ? raw.description : undefined,\n version: typeof raw.version === 'string' ? raw.version : undefined,\n kind: raw.kind as ExtensionKind | undefined,\n main: typeof raw.main === 'string' ? raw.main : undefined,\n configSchema: isRecord(raw.configSchema) ? (raw.configSchema as Record<string, unknown>) : undefined,\n dependencies: isRecord(raw.dependencies) ? (raw.dependencies as Record<string, string>) : undefined,\n\n enabledByDefault: typeof raw.enabledByDefault === 'boolean' ? raw.enabledByDefault : undefined,\n legacyExtensionIds: Array.isArray(raw.legacyExtensionIds)\n ? raw.legacyExtensionIds.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n providers: Array.isArray(raw.providers)\n ? raw.providers.filter((x): x is string => typeof x === 'string')\n : undefined,\n providerAuthEnvVars: normalizeStringArrayMap(raw.providerAuthEnvVars),\n providerAuthChoices: normalizeProviderAuthChoices(raw.providerAuthChoices),\n modelSupport: normalizeModelSupport(raw.modelSupport),\n autoEnableWhenConfiguredProviders: Array.isArray(raw.autoEnableWhenConfiguredProviders)\n ? raw.autoEnableWhenConfiguredProviders.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n channels: Array.isArray(raw.channels)\n ? raw.channels.filter((x): x is string => typeof x === 'string')\n : undefined,\n channelEnvVars: normalizeStringArrayMap(raw.channelEnvVars),\n\n activation: normalizeActivation(raw.activation),\n contracts: normalizeContracts(raw.contracts),\n setup: normalizeSetup(raw.setup),\n reload: normalizeReload(raw.reload),\n engines: normalizeEngines(raw.engines),\n commands: normalizeManifestCommands(raw.commands),\n ui: normalizeUiManifest(raw.ui),\n };\n}\n\nconst VALID_UI_PERMISSIONS = new Set<ExtensionUiPermission>([\n 'agent.send',\n 'agent.subscribe',\n 'session.read',\n 'session.write',\n 'config.read',\n 'config.write',\n 'storage',\n 'notification',\n 'clipboard',\n 'theme',\n 'workspace.read',\n 'workspace.write',\n]);\n\nexport function normalizeUiManifest(raw: unknown): ExtensionUiManifest | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!isRecord(raw)) return undefined;\n const main = typeof raw.main === 'string' && raw.main.length > 0 ? raw.main : undefined;\n const icon = typeof raw.icon === 'string' && raw.icon.length > 0 ? raw.icon : undefined;\n let permissions: ExtensionUiPermission[] | undefined;\n if (Array.isArray(raw.permissions)) {\n const p = raw.permissions.filter(\n (x): x is ExtensionUiPermission =>\n typeof x === 'string' && VALID_UI_PERMISSIONS.has(x as ExtensionUiPermission),\n );\n permissions = p.length ? p : undefined;\n }\n const contributions = normalizeUiContributions(raw.contributions);\n if (!main && !icon && !permissions && !contributions) return undefined;\n return {\n ...(main !== undefined ? { main } : {}),\n ...(icon !== undefined ? { icon } : {}),\n ...(permissions !== undefined ? { permissions } : {}),\n ...(contributions !== undefined ? { contributions } : {}),\n };\n}\n\nfunction normalizeUiContributions(raw: unknown): ExtensionUiContributions | undefined {\n if (!isRecord(raw)) return undefined;\n const sidebarPanels = normalizeSidebarPanels(raw.sidebarPanels);\n const settingsPanels = normalizeSettingsPanels(raw.settingsPanels);\n const chatWidgets = normalizeChatWidgets(raw.chatWidgets);\n const pages = normalizePages(raw.pages);\n const commands = normalizeCommands(raw.commands);\n const statusBarItems = normalizeStatusBarItems(raw.statusBarItems);\n const out: ExtensionUiContributions = {\n ...(sidebarPanels ? { sidebarPanels } : {}),\n ...(settingsPanels ? { settingsPanels } : {}),\n ...(chatWidgets ? { chatWidgets } : {}),\n ...(pages ? { pages } : {}),\n ...(commands ? { commands } : {}),\n ...(statusBarItems ? { statusBarItems } : {}),\n };\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeSidebarPanels(raw: unknown): SidebarPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SidebarPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n icon: typeof item.icon === 'string' ? item.icon : undefined,\n defaultVisible: typeof item.defaultVisible === 'boolean' ? item.defaultVisible : undefined,\n when: typeof item.when === 'string' && item.when.length > 0 ? item.when : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeSettingsPanels(raw: unknown): SettingsPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SettingsPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n order: typeof item.order === 'number' ? item.order : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeChatWidgetMatch(raw: unknown): ChatWidgetMatch | undefined {\n if (!isRecord(raw)) return undefined;\n const toolName = typeof raw.toolName === 'string' ? raw.toolName : undefined;\n const contentType = typeof raw.contentType === 'string' ? raw.contentType : undefined;\n let metadata: Record<string, unknown> | undefined;\n if (isRecord(raw.metadata)) {\n metadata = { ...raw.metadata };\n }\n if (!toolName && !contentType && !metadata) return undefined;\n return { toolName, contentType, metadata };\n}\n\nfunction normalizeChatWidgets(raw: unknown): ChatWidgetContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ChatWidgetContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n const match = normalizeChatWidgetMatch(item.match);\n if (!match) continue;\n out.push({\n id,\n title,\n entrypoint,\n match,\n maxHeight: typeof item.maxHeight === 'number' ? item.maxHeight : undefined,\n interactive: typeof item.interactive === 'boolean' ? item.interactive : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizePages(raw: unknown): PageContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: PageContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const path = item.path;\n const entrypoint = item.entrypoint;\n if (\n typeof id !== 'string' ||\n typeof title !== 'string' ||\n typeof path !== 'string' ||\n typeof entrypoint !== 'string'\n ) {\n continue;\n }\n out.push({\n id,\n title,\n path,\n entrypoint,\n showInNav: typeof item.showInNav === 'boolean' ? item.showInNav : undefined,\n navIcon: typeof item.navIcon === 'string' ? item.navIcon : undefined,\n when: typeof item.when === 'string' && item.when.length > 0 ? item.when : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeCommands(raw: unknown): CommandContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: CommandContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n if (typeof id !== 'string' || typeof title !== 'string') continue;\n out.push({\n id,\n title,\n shortcut: typeof item.shortcut === 'string' ? item.shortcut : undefined,\n opensPanel: typeof item.opensPanel === 'string' ? item.opensPanel : undefined,\n chatAlias:\n typeof item.chatAlias === 'string' && item.chatAlias.length > 0 ? item.chatAlias : undefined,\n when: typeof item.when === 'string' && item.when.length > 0 ? item.when : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStatusBarItems(raw: unknown): StatusBarItemContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: StatusBarItemContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof entrypoint !== 'string') continue;\n const position = item.position;\n out.push({\n id,\n entrypoint,\n position: position === 'left' || position === 'right' ? position : undefined,\n width: typeof item.width === 'number' ? item.width : undefined,\n when: typeof item.when === 'string' && item.when.length > 0 ? item.when : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStringArrayMap(\n raw: unknown,\n): Record<string, string[]> | undefined {\n if (!isRecord(raw)) return undefined;\n const out: Record<string, string[]> = {};\n for (const [k, v] of Object.entries(raw)) {\n if (Array.isArray(v)) {\n const arr = v.filter((x): x is string => typeof x === 'string');\n if (arr.length) out[k] = arr;\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeProviderAuthChoices(raw: unknown): ProviderAuthChoice[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ProviderAuthChoice[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const provider = item.provider;\n const method = item.method;\n const choiceId = item.choiceId;\n const choiceLabel = item.choiceLabel;\n if (\n typeof provider !== 'string' ||\n typeof choiceId !== 'string' ||\n typeof choiceLabel !== 'string' ||\n (method !== 'api-key' && method !== 'oauth' && method !== 'cli' && method !== 'env')\n ) {\n continue;\n }\n out.push({\n provider,\n method,\n choiceId,\n choiceLabel,\n choiceHint: typeof item.choiceHint === 'string' ? item.choiceHint : undefined,\n groupId: typeof item.groupId === 'string' ? item.groupId : undefined,\n groupLabel: typeof item.groupLabel === 'string' ? item.groupLabel : undefined,\n groupHint: typeof item.groupHint === 'string' ? item.groupHint : undefined,\n cliFlag: typeof item.cliFlag === 'string' ? item.cliFlag : undefined,\n cliOption: typeof item.cliOption === 'string' ? item.cliOption : undefined,\n cliDescription: typeof item.cliDescription === 'string' ? item.cliDescription : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeModelSupport(raw: unknown): ModelSupportDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const modelPrefixes = Array.isArray(raw.modelPrefixes)\n ? raw.modelPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const modelPatterns = Array.isArray(raw.modelPatterns)\n ? raw.modelPatterns.filter((x): x is string => typeof x === 'string')\n : undefined;\n if (!modelPrefixes?.length && !modelPatterns?.length) return undefined;\n return { modelPrefixes, modelPatterns };\n}\n\nfunction normalizeActivation(raw: unknown): ActivationDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const onProviders = Array.isArray(raw.onProviders)\n ? raw.onProviders.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onCommands = Array.isArray(raw.onCommands)\n ? raw.onCommands.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onChannels = Array.isArray(raw.onChannels)\n ? raw.onChannels.filter((x): x is string => typeof x === 'string')\n : undefined;\n const capRaw = raw.onCapabilities;\n const onCapabilities = Array.isArray(capRaw)\n ? capRaw.filter(\n (x): x is 'provider' | 'channel' | 'tool' | 'hook' =>\n x === 'provider' || x === 'channel' || x === 'tool' || x === 'hook',\n )\n : undefined;\n if (!onProviders?.length && !onCommands?.length && !onChannels?.length && !onCapabilities?.length) {\n return undefined;\n }\n return { onProviders, onCommands, onChannels, onCapabilities };\n}\n\nfunction normalizeContracts(raw: unknown): ContractDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const pick = (k: string) =>\n Array.isArray(raw[k]) ? raw[k].filter((x: unknown): x is string => typeof x === 'string') : undefined;\n const c: ContractDeclaration = {\n mediaUnderstandingProviders: pick('mediaUnderstandingProviders'),\n speechProviders: pick('speechProviders'),\n imageGenerationProviders: pick('imageGenerationProviders'),\n webSearchProviders: pick('webSearchProviders'),\n memoryProviders: pick('memoryProviders'),\n };\n if (\n !c.mediaUnderstandingProviders?.length &&\n !c.speechProviders?.length &&\n !c.imageGenerationProviders?.length &&\n !c.webSearchProviders?.length &&\n !c.memoryProviders?.length\n ) {\n return undefined;\n }\n return c;\n}\n\nfunction normalizeSetup(raw: unknown): SetupDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const requiresRuntime = typeof raw.requiresRuntime === 'boolean' ? raw.requiresRuntime : undefined;\n let providers: SetupDeclaration['providers'];\n if (Array.isArray(raw.providers)) {\n providers = [];\n for (const p of raw.providers) {\n if (!isRecord(p) || typeof p.id !== 'string') continue;\n providers.push({\n id: p.id,\n authMethods: Array.isArray(p.authMethods)\n ? p.authMethods.filter((x): x is string => typeof x === 'string')\n : undefined,\n envVars: Array.isArray(p.envVars)\n ? p.envVars.filter((x): x is string => typeof x === 'string')\n : undefined,\n });\n }\n if (providers.length === 0) providers = undefined;\n }\n if (!providers && requiresRuntime === undefined) return undefined;\n return { providers, requiresRuntime };\n}\n"],"mappings":"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"}
@@ -33,3 +33,5 @@ export { checkExtensionPathSafety, checkExtensionDirSafety, isExtensionAllowed,
33
33
  export { getExtensionCache, getExtensionDiagnostics, ExtensionLoaderCacheImpl, ExtensionDiagnostics, } from '../diagnostics.js';
34
34
  export type { Config } from '../../config/config-surface.js';
35
35
  export { lazyModule, lazyFunction } from './lazy.js';
36
+ export { createMockExtensionApi, createTestGateway } from './testing.js';
37
+ export type { MockExtensionApi, MockExtensionApiOptions, TestGateway, } from './testing.js';
@@ -9,9 +9,10 @@ import { ExtensionRegistryImpl } from "../loader.js";
9
9
  import { ExtensionHookRunner, createHookContext, isHookEvent } from "../hooks.js";
10
10
  import { registerExtensionCliProgram } from "./channel-helpers.js";
11
11
  import { lazyFunction, lazyModule } from "./lazy.js";
12
+ import { createMockExtensionApi, createTestGateway } from "./testing.js";
12
13
  //#region src/extensions/sdk/index.ts
13
14
  init_plugin_registry();
14
15
  //#endregion
15
- export { DEFAULT_SECURITY_CONFIG, ExtensionDiagnostics, ExtensionHookRunner, ExtensionLoaderCacheImpl, ExtensionRegistryImpl, HOOK_EXECUTION_MODES, ProviderPluginRegistry, SlotRegistry, TypedEventBus, checkExtensionDirSafety, checkExtensionPathSafety, createHookContext, defineChannelPluginEntry, getExtensionCache, getExtensionDiagnostics, getProviderRegistry, getSlotRegistry, isExtensionAllowed, isHookEvent, lazyFunction, lazyModule, logSecurityIssue, provenanceTracker, registerExtensionCliProgram, registerSlotType };
16
+ export { DEFAULT_SECURITY_CONFIG, ExtensionDiagnostics, ExtensionHookRunner, ExtensionLoaderCacheImpl, ExtensionRegistryImpl, HOOK_EXECUTION_MODES, ProviderPluginRegistry, SlotRegistry, TypedEventBus, checkExtensionDirSafety, checkExtensionPathSafety, createHookContext, createMockExtensionApi, createTestGateway, defineChannelPluginEntry, getExtensionCache, getExtensionDiagnostics, getProviderRegistry, getSlotRegistry, isExtensionAllowed, isHookEvent, lazyFunction, lazyModule, logSecurityIssue, provenanceTracker, registerExtensionCliProgram, registerSlotType };
16
17
 
17
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/extensions/sdk/index.ts"],"sourcesContent":["/**\n * xopc Extension SDK\n * \n * Official SDK for developing xopc extensions.\n * Import types and utilities from this module:\n * \n * @example\n * import type { ExtensionApi, ExtensionDefinition } from 'xopc/extension-sdk';\n */\n\n// ============================================================================\n// Core extension types\n// ============================================================================\n\nexport type {\n ExtensionDefinition,\n ExtensionModule,\n ExtensionKind,\n ExtensionApi,\n ExtensionLogger,\n ExtensionManifest,\n ExtensionRecord,\n ExtensionRegistry,\n ResolvedExtensionConfig,\n ExtensionRuntime,\n ExtensionCliRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Tools (re-exported from @mariozechner/pi-agent-core)\n// ============================================================================\n\nexport type {\n AgentTool,\n AgentToolResult,\n AgentToolUpdateCallback,\n ToolExecutionStartEvent,\n ToolExecutionUpdateEvent,\n ToolExecutionEndEvent,\n} from '../types/index.js';\n\n// ============================================================================\n// Hooks ( Strongly Typed)\n// ============================================================================\n\nexport type {\n ExtensionHookEvent,\n ExtensionHookHandler,\n HookOptions,\n HookAgentContext,\n AgentMessage,\n ContextEvent,\n ContextResult,\n InputEvent,\n InputResult,\n TurnEvent,\n TurnResult,\n // New hook types\n HookHandlerMap,\n HookExecutionMode,\n // Note: HOOK_EXECUTION_MODES is exported as value below\n // LLM observation hooks\n HookBeforeModelResolveEvent,\n HookBeforeModelResolveResult,\n HookBeforePromptBuildEvent,\n HookBeforePromptBuildResult,\n HookLlmInputEvent,\n HookLlmOutputEvent,\n // Inbound claim\n HookInboundClaimEvent,\n HookInboundClaimResult,\n // Reset hook\n HookBeforeResetEvent,\n HookBeforeResetResult,\n // Message write hook\n HookBeforeMessageWriteEvent,\n HookBeforeMessageWriteResult,\n // Turn hooks\n HookTurnStartEvent,\n HookTurnEndEvent,\n // Tool execution hooks\n HookToolExecutionStartEvent,\n HookToolExecutionUpdateEvent,\n HookToolExecutionEndEvent,\n // Existing context types\n HookContext,\n BeforeAgentStartContext,\n BeforeAgentStartResult,\n AgentEndContext,\n BeforeCompactionContext,\n AfterCompactionContext,\n MessageReceivedContext,\n MessageSendingContext,\n MessageSendingResult,\n MessageSentContext,\n BeforeToolCallContext,\n BeforeToolCallResult,\n AfterToolCallContext,\n SessionStartContext,\n SessionEndContext,\n GatewayStartContext,\n GatewayStopContext,\n} from '../types/index.js';\n\n// ============================================================================\n// Typed Event Bus\n// ============================================================================\n\nexport type {\n EventMap,\n RequestMap,\n EventHandler,\n EventHandlerMeta,\n RequestHandler,\n RequestHandlerMeta,\n WildcardEventHandler,\n WildcardHandlerMeta,\n TypedEventBusOptions,\n RequestOptions,\n} from '../types/index.js';\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\nexport type {\n ProviderPlugin,\n ProviderModelDefinition,\n ProviderCapabilities,\n ProviderStreamParams,\n ProviderStreamChunk,\n ProviderCompleteParams,\n ProviderResponse,\n ProviderRegistry,\n BUILTIN_PROVIDERS,\n BuiltinProviderId,\n} from '../types/index.js';\n\n// ============================================================================\n// Advanced Features\n// ============================================================================\n\nexport type {\n ProviderConfig,\n ModelConfig,\n OAuthConfig,\n OAuthCallbacks,\n OAuthCredentials,\n FlagConfig,\n FlagValue,\n ShortcutConfig,\n ShortcutHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Security Types\n// ============================================================================\n\nexport type {\n SafetyCheckResult,\n SecurityConfig,\n ExtensionSourceOrigin,\n ProvenanceInfo,\n} from '../security.js';\n\n// ============================================================================\n// Slot Types\n// ============================================================================\n\nexport type {\n SlotKey,\n SlotClaim,\n SlotConfig,\n} from '../slots.js';\n\n// ============================================================================\n// Diagnostics Types\n// ============================================================================\n\nexport type {\n DiagnosticLevel,\n ExtensionDiagnostic,\n ExtensionLoaderCache,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Channels (ChannelPlugin registry)\n// ============================================================================\n\nexport type {\n ChannelPlugin,\n ChannelPluginInitOptions,\n ChannelPluginStartOptions,\n} from '../../channels/plugin-types.js';\n\n// ============================================================================\n// HTTP\n// ============================================================================\n\nexport type {\n HttpRequestHandler,\n HttpRequest,\n HttpResponse,\n} from '../types/index.js';\n\n// ============================================================================\n// Commands\n// ============================================================================\n\nexport type {\n ExtensionCommand,\n ExtensionCommandHandler,\n ExtensionCommandContext,\n ExtensionCommandResult,\n ExtensionReloadHandler,\n ExtensionReloadResult,\n ExtensionReloadRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Services\n// ============================================================================\n\nexport type {\n ExtensionService,\n} from '../types/index.js';\n\n// ============================================================================\n// Gateway\n// ============================================================================\n\nexport type {\n GatewayMethodHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Export Classes\n// ============================================================================\n\nexport { TypedEventBus } from '../typed-event-bus.js';\nexport { ExtensionRegistryImpl } from '../loader.js';\nexport { ProviderPluginRegistry, getProviderRegistry } from '../../providers/plugin-registry.js';\nexport { SlotRegistry, getSlotRegistry, registerSlotType } from '../slots.js';\nexport { HOOK_EXECUTION_MODES } from '../types/hooks.js';\n\nexport { defineChannelPluginEntry } from './channel-entry.js';\nexport { registerExtensionCliProgram } from './channel-helpers.js';\n\n// ============================================================================\n// Export Hook Runner and Utilities\n// ============================================================================\n\nexport { \n ExtensionHookRunner, \n createHookContext, \n isHookEvent \n} from '../hooks.js';\n\n// ============================================================================\n// Security Utilities\n// ============================================================================\n\nexport {\n checkExtensionPathSafety,\n checkExtensionDirSafety,\n isExtensionAllowed,\n provenanceTracker,\n logSecurityIssue,\n DEFAULT_SECURITY_CONFIG,\n} from '../security.js';\n\n// ============================================================================\n// Diagnostics Utilities\n// ============================================================================\n\nexport {\n getExtensionCache,\n getExtensionDiagnostics,\n ExtensionLoaderCacheImpl,\n ExtensionDiagnostics,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Config\n// ============================================================================\n\nexport type { Config } from '../../config/config-surface.js';\n\n// Subpath barrels (also available as `xopc/extension-sdk/<name>`)\nexport { lazyModule, lazyFunction } from './lazy.js';\n"],"mappings":";;;;;;;;;;;;sBAiPiG"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/extensions/sdk/index.ts"],"sourcesContent":["/**\n * xopc Extension SDK\n * \n * Official SDK for developing xopc extensions.\n * Import types and utilities from this module:\n * \n * @example\n * import type { ExtensionApi, ExtensionDefinition } from 'xopc/extension-sdk';\n */\n\n// ============================================================================\n// Core extension types\n// ============================================================================\n\nexport type {\n ExtensionDefinition,\n ExtensionModule,\n ExtensionKind,\n ExtensionApi,\n ExtensionLogger,\n ExtensionManifest,\n ExtensionRecord,\n ExtensionRegistry,\n ResolvedExtensionConfig,\n ExtensionRuntime,\n ExtensionCliRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Tools (re-exported from @mariozechner/pi-agent-core)\n// ============================================================================\n\nexport type {\n AgentTool,\n AgentToolResult,\n AgentToolUpdateCallback,\n ToolExecutionStartEvent,\n ToolExecutionUpdateEvent,\n ToolExecutionEndEvent,\n} from '../types/index.js';\n\n// ============================================================================\n// Hooks ( Strongly Typed)\n// ============================================================================\n\nexport type {\n ExtensionHookEvent,\n ExtensionHookHandler,\n HookOptions,\n HookAgentContext,\n AgentMessage,\n ContextEvent,\n ContextResult,\n InputEvent,\n InputResult,\n TurnEvent,\n TurnResult,\n // New hook types\n HookHandlerMap,\n HookExecutionMode,\n // Note: HOOK_EXECUTION_MODES is exported as value below\n // LLM observation hooks\n HookBeforeModelResolveEvent,\n HookBeforeModelResolveResult,\n HookBeforePromptBuildEvent,\n HookBeforePromptBuildResult,\n HookLlmInputEvent,\n HookLlmOutputEvent,\n // Inbound claim\n HookInboundClaimEvent,\n HookInboundClaimResult,\n // Reset hook\n HookBeforeResetEvent,\n HookBeforeResetResult,\n // Message write hook\n HookBeforeMessageWriteEvent,\n HookBeforeMessageWriteResult,\n // Turn hooks\n HookTurnStartEvent,\n HookTurnEndEvent,\n // Tool execution hooks\n HookToolExecutionStartEvent,\n HookToolExecutionUpdateEvent,\n HookToolExecutionEndEvent,\n // Existing context types\n HookContext,\n BeforeAgentStartContext,\n BeforeAgentStartResult,\n AgentEndContext,\n BeforeCompactionContext,\n AfterCompactionContext,\n MessageReceivedContext,\n MessageSendingContext,\n MessageSendingResult,\n MessageSentContext,\n BeforeToolCallContext,\n BeforeToolCallResult,\n AfterToolCallContext,\n SessionStartContext,\n SessionEndContext,\n GatewayStartContext,\n GatewayStopContext,\n} from '../types/index.js';\n\n// ============================================================================\n// Typed Event Bus\n// ============================================================================\n\nexport type {\n EventMap,\n RequestMap,\n EventHandler,\n EventHandlerMeta,\n RequestHandler,\n RequestHandlerMeta,\n WildcardEventHandler,\n WildcardHandlerMeta,\n TypedEventBusOptions,\n RequestOptions,\n} from '../types/index.js';\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\nexport type {\n ProviderPlugin,\n ProviderModelDefinition,\n ProviderCapabilities,\n ProviderStreamParams,\n ProviderStreamChunk,\n ProviderCompleteParams,\n ProviderResponse,\n ProviderRegistry,\n BUILTIN_PROVIDERS,\n BuiltinProviderId,\n} from '../types/index.js';\n\n// ============================================================================\n// Advanced Features\n// ============================================================================\n\nexport type {\n ProviderConfig,\n ModelConfig,\n OAuthConfig,\n OAuthCallbacks,\n OAuthCredentials,\n FlagConfig,\n FlagValue,\n ShortcutConfig,\n ShortcutHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Security Types\n// ============================================================================\n\nexport type {\n SafetyCheckResult,\n SecurityConfig,\n ExtensionSourceOrigin,\n ProvenanceInfo,\n} from '../security.js';\n\n// ============================================================================\n// Slot Types\n// ============================================================================\n\nexport type {\n SlotKey,\n SlotClaim,\n SlotConfig,\n} from '../slots.js';\n\n// ============================================================================\n// Diagnostics Types\n// ============================================================================\n\nexport type {\n DiagnosticLevel,\n ExtensionDiagnostic,\n ExtensionLoaderCache,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Channels (ChannelPlugin registry)\n// ============================================================================\n\nexport type {\n ChannelPlugin,\n ChannelPluginInitOptions,\n ChannelPluginStartOptions,\n} from '../../channels/plugin-types.js';\n\n// ============================================================================\n// HTTP\n// ============================================================================\n\nexport type {\n HttpRequestHandler,\n HttpRequest,\n HttpResponse,\n} from '../types/index.js';\n\n// ============================================================================\n// Commands\n// ============================================================================\n\nexport type {\n ExtensionCommand,\n ExtensionCommandHandler,\n ExtensionCommandContext,\n ExtensionCommandResult,\n ExtensionReloadHandler,\n ExtensionReloadResult,\n ExtensionReloadRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Services\n// ============================================================================\n\nexport type {\n ExtensionService,\n} from '../types/index.js';\n\n// ============================================================================\n// Gateway\n// ============================================================================\n\nexport type {\n GatewayMethodHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Export Classes\n// ============================================================================\n\nexport { TypedEventBus } from '../typed-event-bus.js';\nexport { ExtensionRegistryImpl } from '../loader.js';\nexport { ProviderPluginRegistry, getProviderRegistry } from '../../providers/plugin-registry.js';\nexport { SlotRegistry, getSlotRegistry, registerSlotType } from '../slots.js';\nexport { HOOK_EXECUTION_MODES } from '../types/hooks.js';\n\nexport { defineChannelPluginEntry } from './channel-entry.js';\nexport { registerExtensionCliProgram } from './channel-helpers.js';\n\n// ============================================================================\n// Export Hook Runner and Utilities\n// ============================================================================\n\nexport { \n ExtensionHookRunner, \n createHookContext, \n isHookEvent \n} from '../hooks.js';\n\n// ============================================================================\n// Security Utilities\n// ============================================================================\n\nexport {\n checkExtensionPathSafety,\n checkExtensionDirSafety,\n isExtensionAllowed,\n provenanceTracker,\n logSecurityIssue,\n DEFAULT_SECURITY_CONFIG,\n} from '../security.js';\n\n// ============================================================================\n// Diagnostics Utilities\n// ============================================================================\n\nexport {\n getExtensionCache,\n getExtensionDiagnostics,\n ExtensionLoaderCacheImpl,\n ExtensionDiagnostics,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Config\n// ============================================================================\n\nexport type { Config } from '../../config/config-surface.js';\n\n// Subpath barrels (also available as `xopc/extension-sdk/<name>`)\nexport { lazyModule, lazyFunction } from './lazy.js';\n\nexport { createMockExtensionApi, createTestGateway } from './testing.js';\nexport type {\n MockExtensionApi,\n MockExtensionApiOptions,\n TestGateway,\n} from './testing.js';\n"],"mappings":";;;;;;;;;;;;;sBAiPiG"}
@@ -1,5 +1,51 @@
1
1
  /**
2
- * Lightweight test doubles no Vitest dependency.
2
+ * Extension testing helpers (Phase 2): mock API + minimal HTTP gateway fixture.
3
3
  */
4
- import type { ExtensionApi } from '../types/core.js';
5
- export declare function createMockExtensionApi(overrides?: Partial<ExtensionApi>): ExtensionApi;
4
+ import type { AgentTool } from '@mariozechner/pi-agent-core';
5
+ import type { ChannelPlugin } from '../../channels/plugin-types.js';
6
+ import type { Config } from '../../config/config-surface.js';
7
+ import type { ExtensionApi, ExtensionCommand, ExtensionCommandContext, ExtensionLogger, ExtensionReloadHandler, ExtensionService, GatewayMethodHandler, HttpRequestHandler } from '../types/core.js';
8
+ import type { ExtensionHookEvent } from '../types/hooks.js';
9
+ import type { CommandContribution } from '../types/manifest.js';
10
+ export interface MockExtensionApiOptions {
11
+ id?: string;
12
+ name?: string;
13
+ version?: string;
14
+ source?: string;
15
+ extensionConfig?: Record<string, unknown>;
16
+ config?: Partial<Config>;
17
+ logger?: ExtensionLogger;
18
+ /** Pretend manifest `ui.contributions.commands` for `onCommand` tests. */
19
+ manifestCommands?: CommandContribution[];
20
+ }
21
+ export interface MockExtensionApi extends ExtensionApi {
22
+ getRegisteredTools(): AgentTool[];
23
+ getRegisteredHooks(): Array<{
24
+ event: ExtensionHookEvent;
25
+ handler: unknown;
26
+ }>;
27
+ getRegisteredCommands(): ExtensionCommand[];
28
+ getRegisteredHttpRoutes(): Array<{
29
+ path: string;
30
+ handler: HttpRequestHandler;
31
+ }>;
32
+ getRegisteredServices(): ExtensionService[];
33
+ getRegisteredGatewayMethods(): Array<{
34
+ method: string;
35
+ handler: GatewayMethodHandler;
36
+ }>;
37
+ getRegisteredChannelPlugins(): ChannelPlugin[];
38
+ getRegisteredReloadHandlers(): ExtensionReloadHandler[];
39
+ getEmittedEvents(): Array<{
40
+ event: string;
41
+ data: unknown;
42
+ }>;
43
+ }
44
+ export declare function createMockExtensionApi(options?: MockExtensionApiOptions): MockExtensionApi;
45
+ export interface TestGateway {
46
+ baseUrl: string;
47
+ fetch: (path: string, init?: RequestInit) => Promise<Response>;
48
+ close: () => Promise<void>;
49
+ }
50
+ export declare function createTestGateway(): Promise<TestGateway>;
51
+ export type { ExtensionCommandContext };
@@ -1,12 +1,181 @@
1
+ import { TypedEventBus } from "../typed-event-bus.js";
2
+ import { serve } from "@hono/node-server";
3
+ import { Hono } from "hono";
4
+ import { EventEmitter, once } from "node:events";
1
5
  //#region src/extensions/sdk/testing.ts
2
- function createMockExtensionApi(overrides) {
6
+ const noopLogger = {
7
+ debug: () => {},
8
+ info: () => {},
9
+ warn: () => {},
10
+ error: () => {}
11
+ };
12
+ function createMockExtensionApi(options = {}) {
13
+ return new MockExtensionApiImpl(options);
14
+ }
15
+ var MockExtensionApiImpl = class {
16
+ id;
17
+ name;
18
+ version;
19
+ source;
20
+ config;
21
+ extensionConfig;
22
+ logger;
23
+ runtime;
24
+ events;
25
+ _tools = [];
26
+ _hooks = [];
27
+ _commands = [];
28
+ _http = [];
29
+ _services = [];
30
+ _gw = [];
31
+ _channels = [];
32
+ _reload = [];
33
+ _emitted = [];
34
+ _bus = new EventEmitter();
35
+ _manifestCommands = /* @__PURE__ */ new Map();
36
+ constructor(opts) {
37
+ this.id = opts.id ?? "test-extension";
38
+ this.name = opts.name ?? "Test Extension";
39
+ this.version = opts.version;
40
+ this.source = opts.source ?? "/test";
41
+ this.extensionConfig = opts.extensionConfig ?? {};
42
+ this.config = opts.config ?? {};
43
+ this.logger = opts.logger ?? noopLogger;
44
+ this.runtime = {
45
+ config: this.config,
46
+ log: this.logger
47
+ };
48
+ this.events = new TypedEventBus({ logger: this.logger });
49
+ if (opts.manifestCommands?.length) for (const c of opts.manifestCommands) this._manifestCommands.set(c.id, c);
50
+ }
51
+ _setManifestCommands(commands) {
52
+ this._manifestCommands.clear();
53
+ for (const c of commands) this._manifestCommands.set(c.id, c);
54
+ }
55
+ getRegisteredTools() {
56
+ return [...this._tools];
57
+ }
58
+ getRegisteredHooks() {
59
+ return [...this._hooks];
60
+ }
61
+ getRegisteredCommands() {
62
+ return [...this._commands];
63
+ }
64
+ getRegisteredHttpRoutes() {
65
+ return [...this._http];
66
+ }
67
+ getRegisteredServices() {
68
+ return [...this._services];
69
+ }
70
+ getRegisteredGatewayMethods() {
71
+ return [...this._gw];
72
+ }
73
+ getRegisteredChannelPlugins() {
74
+ return [...this._channels];
75
+ }
76
+ getRegisteredReloadHandlers() {
77
+ return [...this._reload];
78
+ }
79
+ getEmittedEvents() {
80
+ return [...this._emitted];
81
+ }
82
+ registerTool(tool) {
83
+ this._tools.push(tool);
84
+ }
85
+ registerHook(event, handler, _opts) {
86
+ this._hooks.push({
87
+ event,
88
+ handler
89
+ });
90
+ }
91
+ onHook(_hookName, _handler) {}
92
+ registerChannel(registration) {
93
+ this._channels.push(registration.plugin);
94
+ }
95
+ registerHttpRoute(path, handler) {
96
+ this._http.push({
97
+ path,
98
+ handler
99
+ });
100
+ }
101
+ registerCommand(command) {
102
+ this._commands.push(command);
103
+ }
104
+ onCommand(commandId, handler) {
105
+ const meta = this._manifestCommands.get(commandId);
106
+ if (!meta) {
107
+ const name = commandId.includes(".") ? (commandId.split(".").pop() ?? commandId).trim() : commandId;
108
+ this.registerCommand({
109
+ name: name || commandId,
110
+ description: commandId,
111
+ handler
112
+ });
113
+ return;
114
+ }
115
+ let name;
116
+ if (meta.chatAlias?.trim()) name = meta.chatAlias.trim().replace(/^\//, "");
117
+ else name = meta.id.includes(".") ? meta.id.split(".").pop() ?? meta.id : meta.id;
118
+ if (!name) name = meta.id;
119
+ this.registerCommand({
120
+ name,
121
+ description: meta.title,
122
+ handler
123
+ });
124
+ }
125
+ registerReload(handler) {
126
+ this._reload.push(handler);
127
+ }
128
+ registerService(service) {
129
+ this._services.push(service);
130
+ }
131
+ registerGatewayMethod(method, handler) {
132
+ this._gw.push({
133
+ method,
134
+ handler
135
+ });
136
+ }
137
+ registerCli(_factory, _opts) {}
138
+ resolvePath(input) {
139
+ return `${this.source.replace(/\/$/, "")}/${input.replace(/^\//, "")}`;
140
+ }
141
+ emit(event, data) {
142
+ this._emitted.push({
143
+ event,
144
+ data
145
+ });
146
+ this._bus.emit(event, data);
147
+ }
148
+ on(event, handler) {
149
+ this._bus.on(event, handler);
150
+ }
151
+ off(event, handler) {
152
+ this._bus.off(event, handler);
153
+ }
154
+ registerProvider(_plugin) {}
155
+ registerProviderPlugin(_plugin) {}
156
+ registerFlag(_name, _config) {}
157
+ getFlag(_name) {}
158
+ registerShortcut(_key, _config) {}
159
+ };
160
+ async function createTestGateway() {
161
+ const app = new Hono();
162
+ app.get("/health", (c) => c.json({ ok: true }));
163
+ const server = serve({
164
+ fetch: app.fetch,
165
+ port: 0,
166
+ hostname: "127.0.0.1"
167
+ });
168
+ if (!server.listening) await once(server, "listening");
169
+ const baseUrl = `http://127.0.0.1:${server.address().port}`;
3
170
  return {
4
- id: "mock",
5
- name: "mock",
6
- ...overrides
171
+ baseUrl,
172
+ fetch: (path, init) => fetch(`${baseUrl}${path.startsWith("/") ? path : `/${path}`}`, init),
173
+ close: () => new Promise((resolve, reject) => {
174
+ server.close((err) => err ? reject(err) : resolve());
175
+ })
7
176
  };
8
177
  }
9
178
  //#endregion
10
- export { createMockExtensionApi };
179
+ export { createMockExtensionApi, createTestGateway };
11
180
 
12
181
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../../../../src/extensions/sdk/testing.ts"],"sourcesContent":["/**\n * Lightweight test doubles — no Vitest dependency.\n */\n\nimport type { ExtensionApi } from '../types/core.js';\n\nexport function createMockExtensionApi(overrides?: Partial<ExtensionApi>): ExtensionApi {\n return {\n id: 'mock',\n name: 'mock',\n ...overrides,\n } as unknown as ExtensionApi;\n}\n"],"mappings":";AAMA,SAAgB,uBAAuB,WAAiD;AACtF,QAAO;EACL,IAAI;EACJ,MAAM;EACN,GAAG;EACJ"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../../../../src/extensions/sdk/testing.ts"],"sourcesContent":["/**\n * Extension testing helpers (Phase 2): mock API + minimal HTTP gateway fixture.\n */\n\nimport type { Command } from 'commander';\nimport { EventEmitter } from 'node:events';\nimport { once } from 'node:events';\nimport type { AddressInfo } from 'node:net';\n\nimport type { AgentTool } from '@mariozechner/pi-agent-core';\n\nimport { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport type { ServerType } from '@hono/node-server';\n\nimport type { ChannelPlugin } from '../../channels/plugin-types.js';\nimport type { Config } from '../../config/config-surface.js';\nimport type {\n ExtensionApi,\n ExtensionCommand,\n ExtensionCommandContext,\n ExtensionCommandHandler,\n ExtensionLogger,\n ExtensionReloadHandler,\n ExtensionRuntime,\n ExtensionService,\n GatewayMethodHandler,\n HttpRequestHandler,\n} from '../types/core.js';\nimport type { FlagConfig, FlagValue, ShortcutConfig } from '../types/phase4.js';\nimport type {\n ExtensionHookEvent,\n ExtensionHookHandler,\n HookHandlerMap,\n HookOptions,\n} from '../types/hooks.js';\nimport type { CommandContribution } from '../types/manifest.js';\nimport { TypedEventBus } from '../typed-event-bus.js';\n\nexport interface MockExtensionApiOptions {\n id?: string;\n name?: string;\n version?: string;\n source?: string;\n extensionConfig?: Record<string, unknown>;\n config?: Partial<Config>;\n logger?: ExtensionLogger;\n /** Pretend manifest `ui.contributions.commands` for `onCommand` tests. */\n manifestCommands?: CommandContribution[];\n}\n\nconst noopLogger: ExtensionLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nexport interface MockExtensionApi extends ExtensionApi {\n getRegisteredTools(): AgentTool[];\n getRegisteredHooks(): Array<{ event: ExtensionHookEvent; handler: unknown }>;\n getRegisteredCommands(): ExtensionCommand[];\n getRegisteredHttpRoutes(): Array<{ path: string; handler: HttpRequestHandler }>;\n getRegisteredServices(): ExtensionService[];\n getRegisteredGatewayMethods(): Array<{ method: string; handler: GatewayMethodHandler }>;\n getRegisteredChannelPlugins(): ChannelPlugin[];\n getRegisteredReloadHandlers(): ExtensionReloadHandler[];\n getEmittedEvents(): Array<{ event: string; data: unknown }>;\n}\n\nexport function createMockExtensionApi(options: MockExtensionApiOptions = {}): MockExtensionApi {\n return new MockExtensionApiImpl(options);\n}\n\nclass MockExtensionApiImpl implements MockExtensionApi {\n readonly id: string;\n readonly name: string;\n readonly version: string | undefined;\n readonly source: string;\n readonly config: Config;\n readonly extensionConfig: Record<string, unknown>;\n readonly logger: ExtensionLogger;\n readonly runtime: ExtensionRuntime;\n readonly events: TypedEventBus;\n\n private readonly _tools: AgentTool[] = [];\n private readonly _hooks: Array<{ event: ExtensionHookEvent; handler: unknown }> = [];\n private readonly _commands: ExtensionCommand[] = [];\n private readonly _http: Array<{ path: string; handler: HttpRequestHandler }> = [];\n private readonly _services: ExtensionService[] = [];\n private readonly _gw: Array<{ method: string; handler: GatewayMethodHandler }> = [];\n private readonly _channels: ChannelPlugin[] = [];\n private readonly _reload: ExtensionReloadHandler[] = [];\n private readonly _emitted: Array<{ event: string; data: unknown }> = [];\n private readonly _bus = new EventEmitter();\n private readonly _manifestCommands = new Map<string, CommandContribution>();\n\n constructor(opts: MockExtensionApiOptions) {\n this.id = opts.id ?? 'test-extension';\n this.name = opts.name ?? 'Test Extension';\n this.version = opts.version;\n this.source = opts.source ?? '/test';\n this.extensionConfig = opts.extensionConfig ?? {};\n this.config = (opts.config ?? {}) as Config;\n this.logger = opts.logger ?? noopLogger;\n this.runtime = { config: this.config, log: this.logger };\n this.events = new TypedEventBus({ logger: this.logger });\n if (opts.manifestCommands?.length) {\n for (const c of opts.manifestCommands) {\n this._manifestCommands.set(c.id, c);\n }\n }\n }\n\n _setManifestCommands(commands: CommandContribution[]): void {\n this._manifestCommands.clear();\n for (const c of commands) {\n this._manifestCommands.set(c.id, c);\n }\n }\n\n getRegisteredTools(): AgentTool[] {\n return [...this._tools];\n }\n getRegisteredHooks(): Array<{ event: ExtensionHookEvent; handler: unknown }> {\n return [...this._hooks];\n }\n getRegisteredCommands(): ExtensionCommand[] {\n return [...this._commands];\n }\n getRegisteredHttpRoutes(): Array<{ path: string; handler: HttpRequestHandler }> {\n return [...this._http];\n }\n getRegisteredServices(): ExtensionService[] {\n return [...this._services];\n }\n getRegisteredGatewayMethods(): Array<{ method: string; handler: GatewayMethodHandler }> {\n return [...this._gw];\n }\n getRegisteredChannelPlugins(): ChannelPlugin[] {\n return [...this._channels];\n }\n getRegisteredReloadHandlers(): ExtensionReloadHandler[] {\n return [...this._reload];\n }\n getEmittedEvents(): Array<{ event: string; data: unknown }> {\n return [...this._emitted];\n }\n\n registerTool(tool: AgentTool): void {\n this._tools.push(tool);\n }\n\n registerHook(\n event: ExtensionHookEvent,\n handler: ExtensionHookHandler,\n _opts?: HookOptions,\n ): void {\n this._hooks.push({ event, handler });\n }\n\n onHook<K extends ExtensionHookEvent>(_hookName: K, _handler: HookHandlerMap[K]): void {\n /* optional for tests */\n }\n\n registerChannel(registration: { plugin: ChannelPlugin }): void {\n this._channels.push(registration.plugin);\n }\n\n registerHttpRoute(path: string, handler: HttpRequestHandler): void {\n this._http.push({ path, handler });\n }\n\n registerCommand(command: ExtensionCommand): void {\n this._commands.push(command);\n }\n\n onCommand(commandId: string, handler: ExtensionCommandHandler): void {\n const meta = this._manifestCommands.get(commandId);\n if (!meta) {\n const name = commandId.includes('.')\n ? (commandId.split('.').pop() ?? commandId).trim()\n : commandId;\n this.registerCommand({\n name: name || commandId,\n description: commandId,\n handler,\n });\n return;\n }\n let name: string;\n if (meta.chatAlias?.trim()) {\n name = meta.chatAlias.trim().replace(/^\\//, '');\n } else {\n name = meta.id.includes('.') ? (meta.id.split('.').pop() ?? meta.id) : meta.id;\n }\n if (!name) name = meta.id;\n this.registerCommand({ name, description: meta.title, handler });\n }\n\n registerReload(handler: ExtensionReloadHandler): void {\n this._reload.push(handler);\n }\n\n registerService(service: ExtensionService): void {\n this._services.push(service);\n }\n\n registerGatewayMethod(method: string, handler: GatewayMethodHandler): void {\n this._gw.push({ method, handler });\n }\n\n registerCli(_factory: (ctx: { program: Command }) => void, _opts?: { commands: string[] }): void {\n /* noop */\n }\n\n resolvePath(input: string): string {\n const base = this.source.replace(/\\/$/, '');\n const p = input.replace(/^\\//, '');\n return `${base}/${p}`;\n }\n\n emit(event: string, data: unknown): void {\n this._emitted.push({ event, data });\n this._bus.emit(event, data);\n }\n\n on(event: string, handler: (data: unknown) => void): void {\n this._bus.on(event, handler);\n }\n\n off(event: string, handler: (data: unknown) => void): void {\n this._bus.off(event, handler);\n }\n\n registerProvider(_plugin: unknown): void {\n /* noop */\n }\n\n registerProviderPlugin(_plugin: unknown): void {\n /* noop */\n }\n\n registerFlag(_name: string, _config: FlagConfig): void {\n /* noop */\n }\n\n getFlag(_name: string): FlagValue {\n return undefined;\n }\n\n registerShortcut(_key: string, _config: ShortcutConfig): void {\n /* noop */\n }\n}\n\nexport interface TestGateway {\n baseUrl: string;\n fetch: (path: string, init?: RequestInit) => Promise<Response>;\n close: () => Promise<void>;\n}\n\nexport async function createTestGateway(): Promise<TestGateway> {\n const app = new Hono();\n app.get('/health', (c) => c.json({ ok: true }));\n\n const server: ServerType = serve({\n fetch: app.fetch,\n port: 0,\n hostname: '127.0.0.1',\n });\n\n if (!server.listening) {\n await once(server, 'listening');\n }\n const addr = server.address() as AddressInfo;\n const port = addr.port;\n const baseUrl = `http://127.0.0.1:${port}`;\n\n return {\n baseUrl,\n fetch: (path, init) =>\n fetch(`${baseUrl}${path.startsWith('/') ? path : `/${path}`}`, init),\n close: () =>\n new Promise((resolve, reject) => {\n server.close((err) => (err ? reject(err) : resolve()));\n }),\n };\n}\n\nexport type { ExtensionCommandContext };\n"],"mappings":"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"}
@@ -79,6 +79,11 @@ export interface ExtensionApi {
79
79
  }): void;
80
80
  registerHttpRoute(path: string, handler: HttpRequestHandler): void;
81
81
  registerCommand(command: ExtensionCommand): void;
82
+ /**
83
+ * Bind a handler to a manifest-declared command id (`ui.contributions.commands`).
84
+ * Metadata comes from the manifest; optional `chatAlias` becomes the slash command name.
85
+ */
86
+ onCommand(commandId: string, handler: ExtensionCommandHandler): void;
82
87
  /**
83
88
  * Register a reload handler when config paths matching this extension change during hot reload.
84
89
  */
@@ -3,6 +3,11 @@
3
3
  * New fields are optional for backward compatibility.
4
4
  */
5
5
  import type { ExtensionKind } from './core.js';
6
+ /** Declared in `engines` in the extension manifest (e.g. VSCode-style). */
7
+ export interface EnginesDeclaration {
8
+ /** Semver range string for the running xopc CLI / gateway, e.g. `">=0.0.20"`. */
9
+ xopc?: string;
10
+ }
6
11
  export interface ExtensionManifest {
7
12
  id: string;
8
13
  name: string;
@@ -29,6 +34,11 @@ export interface ExtensionManifest {
29
34
  configPrefixes?: string[];
30
35
  supportsHotReload?: boolean;
31
36
  };
37
+ /**
38
+ * Host / runtime requirements (e.g. compatible xopc semver range).
39
+ * Normalized from `xopc.extension.json` `engines`.
40
+ */
41
+ engines?: EnginesDeclaration;
32
42
  /** Chat commands metadata (runtime registration still required in `register()`). */
33
43
  commands?: ExtensionManifestCommand[];
34
44
  /** Frontend UI declaration — enables extensions to render custom UI in the Gateway Console. */
@@ -70,6 +80,8 @@ export interface SidebarPanelContribution {
70
80
  icon?: string;
71
81
  entrypoint: string;
72
82
  defaultVisible?: boolean;
83
+ /** When-expression for visibility (see Phase 2). */
84
+ when?: string;
73
85
  }
74
86
  /** A panel rendered inside the settings page. */
75
87
  export interface SettingsPanelContribution {
@@ -102,6 +114,7 @@ export interface PageContribution {
102
114
  showInNav?: boolean;
103
115
  /** Lucide icon name */
104
116
  navIcon?: string;
117
+ when?: string;
105
118
  }
106
119
  /** A command registered in the command palette. */
107
120
  export interface CommandContribution {
@@ -109,6 +122,9 @@ export interface CommandContribution {
109
122
  title: string;
110
123
  shortcut?: string;
111
124
  opensPanel?: string;
125
+ /** Optional chat slash name (e.g. `/hello`); bound via `api.onCommand`. */
126
+ chatAlias?: string;
127
+ when?: string;
112
128
  }
113
129
  /** A small widget rendered in the status bar. */
114
130
  export interface StatusBarItemContribution {
@@ -116,6 +132,7 @@ export interface StatusBarItemContribution {
116
132
  entrypoint: string;
117
133
  position?: 'left' | 'right';
118
134
  width?: number;
135
+ when?: string;
119
136
  }
120
137
  export interface ProviderAuthChoice {
121
138
  provider: string;
@@ -0,0 +1,6 @@
1
+ import type { Config as SurfaceConfig } from '../config/config-surface.js';
2
+ import type { ExtensionLoader } from './loader.js';
3
+ /**
4
+ * Flat payload for `GET /api/context` and client-side `when` evaluation.
5
+ */
6
+ export declare function buildWhenContextSnapshot(config: SurfaceConfig, loader: ExtensionLoader | null): Record<string, unknown>;