@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-dev.js","names":[],"sources":["../../../../src/cli/commands/extension-dev.ts"],"sourcesContent":["import {\n existsSync,\n mkdirSync,\n readFileSync,\n symlinkSync,\n unlinkSync,\n watch,\n type FSWatcher,\n} from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nimport { Command } from 'commander';\n\nimport { resolveDefaultAgentId } from '../../agent/agent-scope.js';\nimport { loadConfig } from '../../config/loader.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { resolveWorkspaceExtensionsDir } from '../../config/paths.js';\nimport { checkEngineCompatibility } from '../../extensions/engine-check.js';\nimport type { ExtensionManifest } from '../../extensions/types/index.js';\nimport { normalizeExtensionManifest } from '../../extensions/normalize-manifest.js';\nimport { GatewayServer } from '../../gateway/index.js';\nimport { runGatewayLoop } from '../../gateway/run-loop.js';\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { colors } from '../utils/colors.js';\nimport { getContextWithOpts } from '../index.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { seedMainAgentBootstrap } from '../../agent/context/workspace-seed.js';\n\nconst log = createLogger('ExtensionDev');\nconst MANIFEST = 'xopc.extension.json';\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nasync function ensureGatewayReady(\n configPath: string,\n workspacePath: string,\n gatewayHost: string,\n gatewayPort: number,\n): Promise<void> {\n const result = await initWorkspace({\n configPath,\n workspacePath,\n gatewayHost,\n gatewayPort,\n });\n\n if (result.configCreated || result.workspaceCreated) {\n console.log('');\n console.log('👋 First-time setup before starting the gateway...');\n console.log('');\n console.log('✅ Setup complete.');\n console.log(` Config: ${configPath}`);\n console.log(` Workspace: ${workspacePath}`);\n console.log('');\n seedMainAgentBootstrap(result.config);\n }\n}\n\nfunction loadAndValidateManifest(extensionDir: string): ExtensionManifest | null {\n const manifestPath = join(extensionDir, MANIFEST);\n if (!existsSync(manifestPath)) {\n console.error(colors.red('error:'), `Missing ${MANIFEST} in ${extensionDir}`);\n return null;\n }\n try {\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8') as string) as unknown;\n if (!isRecord(raw)) {\n console.error(colors.red('error:'), 'Manifest must be a JSON object');\n return null;\n }\n const manifest = normalizeExtensionManifest(raw);\n if (!manifest.id?.trim()) {\n console.error(colors.red('error:'), 'Manifest \"id\" is required');\n return null;\n }\n if (manifest.engines?.xopc) {\n const r = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);\n if (r.parseWarning) {\n console.log(\n colors.yellow('warning:'),\n r.reason ?? 'engines.xopc could not be fully parsed — continuing',\n );\n } else if (!r.compatible) {\n console.log(\n colors.yellow('warning:'),\n r.reason ?? `engines.xopc may not match xopc ${PACKAGE_VERSION} — continuing`,\n );\n }\n }\n return manifest;\n } catch (e) {\n log.error({ err: e }, 'Failed to read manifest');\n console.error(\n colors.red('error:'),\n e instanceof Error ? e.message : String(e),\n );\n return null;\n }\n}\n\nfunction setupDevSymlink(extensionDir: string, extensionsDir: string, extensionId: string): string {\n mkdirSync(extensionsDir, { recursive: true });\n const symlinkPath = join(extensionsDir, extensionId);\n if (existsSync(symlinkPath)) {\n unlinkSync(symlinkPath);\n }\n symlinkSync(extensionDir, symlinkPath, 'dir');\n return symlinkPath;\n}\n\nfunction cleanupSymlink(symlinkPath: string | null): void {\n if (!symlinkPath) return;\n try {\n if (existsSync(symlinkPath)) {\n unlinkSync(symlinkPath);\n }\n } catch (e) {\n log.warn({ err: e, symlinkPath }, 'Failed to remove dev symlink');\n }\n}\n\nfunction shouldIgnorePath(relativePath: string): boolean {\n const parts = relativePath.split(/[/\\\\]/);\n if (parts.some((p) => p === 'node_modules')) return true;\n if (parts.some((p) => p.startsWith('.'))) return true;\n return false;\n}\n\nexport function createExtensionDevCommand(): Command {\n return new Command('extension:dev')\n .alias('ext:dev')\n .description('Symlink an extension into the workspace for live development (optional file watch + gateway)')\n .argument('[dir]', 'Extension directory (default: current working directory)', '.')\n .option('--port <number>', 'Gateway port', '18790')\n .option('--host <address>', 'Gateway host', '127.0.0.1')\n .option('--no-gateway', 'Do not start the gateway (symlink only)')\n .option('--no-watch', 'Do not watch files for changes')\n .action(\n async (\n dir: string,\n options: { port: string; host: string; gateway: boolean; watch: boolean },\n ) => {\n const extensionDir = resolve(dir || '.');\n const manifest = loadAndValidateManifest(extensionDir);\n if (!manifest) {\n process.exit(1);\n }\n\n const ctx = getContextWithOpts();\n const config = loadConfig(ctx.configPath);\n const agentId = resolveDefaultAgentId(config);\n const extensionsDir = resolveWorkspaceExtensionsDir(config, agentId);\n const symlinkPath = setupDevSymlink(extensionDir, extensionsDir, manifest.id);\n\n console.log(\n colors.green('✓'),\n `Dev symlink: ${symlinkPath} → ${extensionDir}`,\n );\n console.log(\n colors.cyan('Note:'),\n 'restart the gateway or trigger config hot-reload so the extension reload picks up changes.',\n );\n\n let debounce: ReturnType<typeof setTimeout> | null = null;\n let watcher: FSWatcher | null = null;\n\n if (options.watch) {\n try {\n watcher = watch(\n extensionDir,\n { recursive: true },\n (_event, filename) => {\n const rel = filename ? String(filename) : '';\n if (rel && shouldIgnorePath(rel)) return;\n if (debounce) clearTimeout(debounce);\n debounce = setTimeout(() => {\n const label = rel || '(unknown)';\n if (/(^|[\\\\/])xopc\\.extension\\.json$/.test(rel) || rel === MANIFEST) {\n console.log(colors.cyan('[watch]'), `manifest: ${label}`);\n } else if (/\\.(html?|css|mjs|js|tsx?|jsx|json)$/i.test(label)) {\n if (/^ui[\\\\/]/.test(rel) || /[\\\\/]ui[\\\\/]/.test(label)) {\n console.log(colors.cyan('[watch]'), `ui: ${label}`);\n } else {\n console.log(colors.cyan('[watch]'), `source: ${label}`);\n }\n } else {\n console.log(colors.cyan('[watch]'), `changed: ${label}`);\n }\n }, 300);\n },\n );\n } catch (e) {\n log.warn({ err: e }, 'fs.watch failed; continuing without watch');\n }\n }\n\n let cleaned = false;\n const cleanup = () => {\n if (cleaned) return;\n cleaned = true;\n if (debounce) clearTimeout(debounce);\n if (watcher) {\n try {\n watcher.close();\n } catch (e) {\n log.warn({ err: e }, 'watcher close failed');\n }\n }\n cleanupSymlink(symlinkPath);\n };\n\n for (const sig of ['SIGINT', 'SIGTERM'] as const) {\n process.on(sig, () => {\n cleanup();\n process.exit(0);\n });\n }\n\n if (!options.gateway) {\n if (options.watch) {\n console.log(colors.cyan('Watching…'), 'Ctrl+C to stop and remove symlink');\n } else {\n console.log(\n colors.cyan('Holding process…'),\n 'Ctrl+C to stop and remove symlink (no file watch)',\n );\n }\n await new Promise(() => {\n /* until SIGINT / SIGTERM */\n });\n return;\n }\n\n const port = parseInt(options.port, 10);\n const host = options.host;\n await ensureGatewayReady(ctx.configPath, ctx.workspacePath, host, port);\n const cfg = loadConfig(ctx.configPath);\n\n if (Number.isNaN(port)) {\n console.error(colors.red('error:'), 'Invalid --port');\n cleanup();\n process.exit(1);\n }\n\n console.log('');\n console.log('🚀 Starting gateway (extension dev)…');\n console.log(` Host: ${host}`);\n console.log(` Port: ${port}`);\n console.log('');\n\n try {\n await runGatewayLoop({\n configPath: ctx.configPath || resolveConfigPath(),\n port,\n start: async () => {\n const server = new GatewayServer({\n host,\n port,\n token: cfg?.gateway?.auth?.token,\n verbose: ctx.isVerbose,\n configPath: ctx.configPath,\n enableHotReload: true,\n });\n await server.start();\n const displayHost = host === '0.0.0.0' ? 'localhost' : host;\n const token = cfg?.gateway?.auth?.token;\n console.log('✅ Gateway started');\n console.log(` URL: http://${displayHost}:${port}`);\n if (token) {\n console.log(\n ` Token: ${String(token).slice(0, 8)}...${String(token).slice(-8)}`,\n );\n }\n console.log('');\n return server;\n },\n });\n } finally {\n cleanup();\n }\n },\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Command } from 'commander';
2
+ export declare function createExtensionSearchCommand(): Command;
3
+ export declare function createExtensionPublishCommand(): Command;
4
+ export declare function createExtensionUpdateCommand(): Command;
@@ -0,0 +1,145 @@
1
+ import { init_agent_scope, resolveDefaultAgentId } from "../../agent/agent-scope.js";
2
+ import { init_paths, resolveWorkspaceExtensionsDir } from "../../config/paths.js";
3
+ import { init_loader, loadConfig } from "../../config/loader.js";
4
+ import { normalizeExtensionManifest } from "../../extensions/normalize-manifest.js";
5
+ import { colors } from "../utils/colors.js";
6
+ import { fetchRegistry, findExtension, getRegistryUrl, listExtensions, searchExtensions } from "../../extensions/marketplace.js";
7
+ import { getExtensionLockfileManager } from "../../extensions/lockfile.js";
8
+ import { installFromNpm, resolveExtensionsDir } from "../../extensions/install.js";
9
+ import { getContextWithOpts } from "../index.js";
10
+ import { join, resolve } from "node:path";
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import { Command } from "commander";
13
+ import { execSync } from "node:child_process";
14
+ //#region src/cli/commands/extension-marketplace.ts
15
+ init_agent_scope();
16
+ init_loader();
17
+ init_paths();
18
+ const MANIFEST = "xopc.extension.json";
19
+ function isRecord(x) {
20
+ return typeof x === "object" && x !== null && !Array.isArray(x);
21
+ }
22
+ function hasWorkspaceDeps(pkg) {
23
+ const deps = pkg.dependencies;
24
+ const dev = pkg.devDependencies;
25
+ const check = (d) => {
26
+ if (!isRecord(d)) return false;
27
+ return Object.values(d).some((v) => typeof v === "string" && v.startsWith("workspace:"));
28
+ };
29
+ return check(deps) || check(dev);
30
+ }
31
+ function createExtensionSearchCommand() {
32
+ return new Command("extension:search").alias("ext:search").description("Search the curated extension registry").argument("[keyword]", "Search text (omit to list all)", "").option("--category <cat>", "Filter by category").option("--json", "JSON output").action(async (keyword, opts) => {
33
+ try {
34
+ let rows;
35
+ if (opts.category?.trim()) {
36
+ rows = await listExtensions(opts.category.trim());
37
+ if (keyword.trim()) {
38
+ const k = keyword.trim().toLowerCase();
39
+ rows = rows.filter((e) => e.id.toLowerCase().includes(k) || e.name.toLowerCase().includes(k) || (e.description ?? "").toLowerCase().includes(k));
40
+ }
41
+ } else if (keyword.trim()) rows = await searchExtensions(keyword.trim());
42
+ else rows = (await fetchRegistry()).extensions;
43
+ if (opts.json) {
44
+ console.log(JSON.stringify(rows, null, 2));
45
+ return;
46
+ }
47
+ if (rows.length === 0) {
48
+ console.log("No extensions found.");
49
+ return;
50
+ }
51
+ console.log(`Registry: ${getRegistryUrl()}`);
52
+ console.log("");
53
+ for (const e of rows) {
54
+ const badge = e.verified ? ` ${colors.green("✓")}` : "";
55
+ console.log(`${colors.cyan(e.name)}${badge} ${colors.gray(e.version ?? "")}`);
56
+ console.log(` id: ${e.id} npm: ${e.npmPackage}`);
57
+ if (e.description) console.log(` ${e.description}`);
58
+ if (e.categories?.length) console.log(` categories: ${e.categories.join(", ")}`);
59
+ console.log("");
60
+ }
61
+ } catch (err) {
62
+ console.error(colors.red("Error:"), err instanceof Error ? err.message : String(err));
63
+ process.exit(1);
64
+ }
65
+ });
66
+ }
67
+ function createExtensionPublishCommand() {
68
+ return new Command("extension:publish").alias("ext:publish").description("Publish extension to npm (public)").argument("[directory]", "Extension root", ".").option("--dry-run", "npm publish --dry-run", false).option("--access <level>", "npm access", "public").action((dir, opts) => {
69
+ const root = resolve(dir || ".");
70
+ const manifestPath = join(root, MANIFEST);
71
+ const pkgPath = join(root, "package.json");
72
+ if (!existsSync(manifestPath) || !existsSync(pkgPath)) {
73
+ console.error(colors.red("error:"), `Need ${MANIFEST} and package.json in ${root}`);
74
+ process.exit(1);
75
+ }
76
+ try {
77
+ if (hasWorkspaceDeps(JSON.parse(readFileSync(pkgPath, "utf-8")))) {
78
+ console.error(colors.red("error:"), "Remove workspace:* dependencies before publishing.");
79
+ process.exit(1);
80
+ }
81
+ if (!normalizeExtensionManifest(JSON.parse(readFileSync(manifestPath, "utf-8"))).id) {
82
+ console.error(colors.red("error:"), "Invalid manifest id");
83
+ process.exit(1);
84
+ }
85
+ } catch (e) {
86
+ console.error(colors.red("error:"), e instanceof Error ? e.message : String(e));
87
+ process.exit(1);
88
+ }
89
+ const args = ["publish", `--access=${opts.access}`];
90
+ if (opts.dryRun) args.push("--dry-run");
91
+ console.log(colors.cyan("Running:"), `npm ${args.join(" ")}`);
92
+ try {
93
+ execSync(`npm ${args.join(" ")}`, {
94
+ cwd: root,
95
+ stdio: "inherit"
96
+ });
97
+ } catch {
98
+ process.exit(1);
99
+ }
100
+ });
101
+ }
102
+ function createExtensionUpdateCommand() {
103
+ return new Command("extension:update").alias("ext:update").description("Re-install extension(s) from npm using the lockfile / registry").argument("[extensionId]", "Specific extension id (default: all in lockfile)").option("--global", "Use global extensions directory", false).action(async (extensionId, opts) => {
104
+ const ctx = getContextWithOpts();
105
+ const cfg = loadConfig(ctx.configPath);
106
+ const agentId = resolveDefaultAgentId(cfg);
107
+ const targetDir = opts.global ? resolveExtensionsDir(ctx.workspacePath, true) : resolveWorkspaceExtensionsDir(cfg, agentId);
108
+ const data = await getExtensionLockfileManager().load();
109
+ const ids = extensionId?.trim() ? [extensionId.trim()] : Object.keys(data.extensions);
110
+ if (ids.length === 0) {
111
+ console.log("No extensions in lockfile.");
112
+ return;
113
+ }
114
+ for (const id of ids) {
115
+ const entry = data.extensions[id];
116
+ if (!entry) {
117
+ console.log(colors.yellow("skip"), id, "(not in lockfile)");
118
+ continue;
119
+ }
120
+ if (entry.source !== "npm") {
121
+ console.log(colors.yellow("skip"), id, `(source ${entry.source})`);
122
+ continue;
123
+ }
124
+ const spec = entry.resolved?.trim() || await npmPackageForId(id);
125
+ if (!spec) {
126
+ console.log(colors.yellow("skip"), id, "(could not resolve npm package)");
127
+ continue;
128
+ }
129
+ console.log(colors.cyan("Updating"), id, "←", spec);
130
+ const result = await installFromNpm(spec, targetDir);
131
+ if (!result.ok) {
132
+ console.error(colors.red("error:"), result.error ?? id);
133
+ process.exit(1);
134
+ }
135
+ console.log(colors.green("✓"), id);
136
+ }
137
+ });
138
+ }
139
+ async function npmPackageForId(id) {
140
+ return (await findExtension(id))?.npmPackage;
141
+ }
142
+ //#endregion
143
+ export { createExtensionPublishCommand, createExtensionSearchCommand, createExtensionUpdateCommand };
144
+
145
+ //# sourceMappingURL=extension-marketplace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-marketplace.js","names":["marketplace.listExtensions","marketplace.searchExtensions","marketplace.fetchRegistry","marketplace.getRegistryUrl","marketplace.findExtension"],"sources":["../../../../src/cli/commands/extension-marketplace.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nimport { Command } from 'commander';\n\nimport { resolveDefaultAgentId } from '../../agent/agent-scope.js';\nimport { loadConfig } from '../../config/loader.js';\nimport { resolveWorkspaceExtensionsDir } from '../../config/paths.js';\nimport { installFromNpm, resolveExtensionsDir } from '../../extensions/install.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport * as marketplace from '../../extensions/marketplace.js';\nimport { normalizeExtensionManifest } from '../../extensions/normalize-manifest.js';\nimport { colors } from '../utils/colors.js';\nimport { getContextWithOpts } from '../index.js';\n\nconst MANIFEST = 'xopc.extension.json';\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction hasWorkspaceDeps(pkg: Record<string, unknown>): boolean {\n const deps = pkg.dependencies;\n const dev = pkg.devDependencies;\n const check = (d: unknown) => {\n if (!isRecord(d)) return false;\n return Object.values(d).some((v) => typeof v === 'string' && v.startsWith('workspace:'));\n };\n return check(deps) || check(dev);\n}\n\nexport function createExtensionSearchCommand(): Command {\n return new Command('extension:search')\n .alias('ext:search')\n .description('Search the curated extension registry')\n .argument('[keyword]', 'Search text (omit to list all)', '')\n .option('--category <cat>', 'Filter by category')\n .option('--json', 'JSON output')\n .action(async (keyword: string, opts: { category?: string; json?: boolean }) => {\n try {\n let rows;\n if (opts.category?.trim()) {\n rows = await marketplace.listExtensions(opts.category.trim());\n if (keyword.trim()) {\n const k = keyword.trim().toLowerCase();\n rows = rows.filter(\n (e) =>\n e.id.toLowerCase().includes(k) ||\n e.name.toLowerCase().includes(k) ||\n (e.description ?? '').toLowerCase().includes(k),\n );\n }\n } else if (keyword.trim()) {\n rows = await marketplace.searchExtensions(keyword.trim());\n } else {\n const reg = await marketplace.fetchRegistry();\n rows = reg.extensions;\n }\n\n if (opts.json) {\n console.log(JSON.stringify(rows, null, 2));\n return;\n }\n\n if (rows.length === 0) {\n console.log('No extensions found.');\n return;\n }\n\n console.log(`Registry: ${marketplace.getRegistryUrl()}`);\n console.log('');\n for (const e of rows) {\n const badge = e.verified ? ` ${colors.green('✓')}` : '';\n console.log(`${colors.cyan(e.name)}${badge} ${colors.gray(e.version ?? '')}`);\n console.log(` id: ${e.id} npm: ${e.npmPackage}`);\n if (e.description) console.log(` ${e.description}`);\n if (e.categories?.length) console.log(` categories: ${e.categories.join(', ')}`);\n console.log('');\n }\n } catch (err) {\n console.error(colors.red('Error:'), err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n });\n}\n\nexport function createExtensionPublishCommand(): Command {\n return new Command('extension:publish')\n .alias('ext:publish')\n .description('Publish extension to npm (public)')\n .argument('[directory]', 'Extension root', '.')\n .option('--dry-run', 'npm publish --dry-run', false)\n .option('--access <level>', 'npm access', 'public')\n .action((dir: string, opts: { dryRun: boolean; access: string }) => {\n const root = resolve(dir || '.');\n const manifestPath = join(root, MANIFEST);\n const pkgPath = join(root, 'package.json');\n if (!existsSync(manifestPath) || !existsSync(pkgPath)) {\n console.error(colors.red('error:'), `Need ${MANIFEST} and package.json in ${root}`);\n process.exit(1);\n }\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as Record<string, unknown>;\n if (hasWorkspaceDeps(pkg)) {\n console.error(\n colors.red('error:'),\n 'Remove workspace:* dependencies before publishing.',\n );\n process.exit(1);\n }\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as Record<string, unknown>;\n const manifest = normalizeExtensionManifest(raw);\n if (!manifest.id) {\n console.error(colors.red('error:'), 'Invalid manifest id');\n process.exit(1);\n }\n } catch (e) {\n console.error(colors.red('error:'), e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n\n const args = ['publish', `--access=${opts.access}`];\n if (opts.dryRun) args.push('--dry-run');\n console.log(colors.cyan('Running:'), `npm ${args.join(' ')}`);\n try {\n execSync(`npm ${args.join(' ')}`, { cwd: root, stdio: 'inherit' });\n } catch {\n process.exit(1);\n }\n });\n}\n\nexport function createExtensionUpdateCommand(): Command {\n return new Command('extension:update')\n .alias('ext:update')\n .description('Re-install extension(s) from npm using the lockfile / registry')\n .argument('[extensionId]', 'Specific extension id (default: all in lockfile)')\n .option('--global', 'Use global extensions directory', false)\n .action(async (extensionId: string | undefined, opts: { global: boolean }) => {\n const ctx = getContextWithOpts();\n const cfg = loadConfig(ctx.configPath);\n const agentId = resolveDefaultAgentId(cfg);\n const targetDir = opts.global\n ? resolveExtensionsDir(ctx.workspacePath, true)\n : resolveWorkspaceExtensionsDir(cfg, agentId);\n\n const lock = getExtensionLockfileManager();\n const data = await lock.load();\n const ids = extensionId?.trim()\n ? [extensionId.trim()]\n : Object.keys(data.extensions);\n\n if (ids.length === 0) {\n console.log('No extensions in lockfile.');\n return;\n }\n\n for (const id of ids) {\n const entry = data.extensions[id];\n if (!entry) {\n console.log(colors.yellow('skip'), id, '(not in lockfile)');\n continue;\n }\n if (entry.source !== 'npm') {\n console.log(colors.yellow('skip'), id, `(source ${entry.source})`);\n continue;\n }\n const spec = entry.resolved?.trim() || (await npmPackageForId(id));\n if (!spec) {\n console.log(colors.yellow('skip'), id, '(could not resolve npm package)');\n continue;\n }\n console.log(colors.cyan('Updating'), id, '←', spec);\n const result = await installFromNpm(spec, targetDir);\n if (!result.ok) {\n console.error(colors.red('error:'), result.error ?? id);\n process.exit(1);\n }\n console.log(colors.green('✓'), id);\n }\n });\n}\n\nasync function npmPackageForId(id: string): Promise<string | undefined> {\n const found = await marketplace.findExtension(id);\n return found?.npmPackage;\n}\n"],"mappings":";;;;;;;;;;;;;;kBAMmE;aACf;YACkB;AAQtE,MAAM,WAAW;AAEjB,SAAS,SAAS,GAA0C;AAC1D,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,EAAE;;AAGjE,SAAS,iBAAiB,KAAuC;CAC/D,MAAM,OAAO,IAAI;CACjB,MAAM,MAAM,IAAI;CAChB,MAAM,SAAS,MAAe;AAC5B,MAAI,CAAC,SAAS,EAAE,CAAE,QAAO;AACzB,SAAO,OAAO,OAAO,EAAE,CAAC,MAAM,MAAM,OAAO,MAAM,YAAY,EAAE,WAAW,aAAa,CAAC;;AAE1F,QAAO,MAAM,KAAK,IAAI,MAAM,IAAI;;AAGlC,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,wCAAwC,CACpD,SAAS,aAAa,kCAAkC,GAAG,CAC3D,OAAO,oBAAoB,qBAAqB,CAChD,OAAO,UAAU,cAAc,CAC/B,OAAO,OAAO,SAAiB,SAAgD;AAC9E,MAAI;GACF,IAAI;AACJ,OAAI,KAAK,UAAU,MAAM,EAAE;AACzB,WAAO,MAAMA,eAA2B,KAAK,SAAS,MAAM,CAAC;AAC7D,QAAI,QAAQ,MAAM,EAAE;KAClB,MAAM,IAAI,QAAQ,MAAM,CAAC,aAAa;AACtC,YAAO,KAAK,QACT,MACC,EAAE,GAAG,aAAa,CAAC,SAAS,EAAE,IAC9B,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,KAC/B,EAAE,eAAe,IAAI,aAAa,CAAC,SAAS,EAAE,CAClD;;cAEM,QAAQ,MAAM,CACvB,QAAO,MAAMC,iBAA6B,QAAQ,MAAM,CAAC;OAGzD,SAAO,MADWC,eAA2B,EAClC;AAGb,OAAI,KAAK,MAAM;AACb,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C;;AAGF,OAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,IAAI,uBAAuB;AACnC;;AAGF,WAAQ,IAAI,aAAaC,gBAA4B,GAAG;AACxD,WAAQ,IAAI,GAAG;AACf,QAAK,MAAM,KAAK,MAAM;IACpB,MAAM,QAAQ,EAAE,WAAW,IAAI,OAAO,MAAM,IAAI,KAAK;AACrD,YAAQ,IAAI,GAAG,OAAO,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,KAAK,EAAE,WAAW,GAAG,GAAG;AAC7E,YAAQ,IAAI,SAAS,EAAE,GAAG,SAAS,EAAE,aAAa;AAClD,QAAI,EAAE,YAAa,SAAQ,IAAI,KAAK,EAAE,cAAc;AACpD,QAAI,EAAE,YAAY,OAAQ,SAAQ,IAAI,iBAAiB,EAAE,WAAW,KAAK,KAAK,GAAG;AACjF,YAAQ,IAAI,GAAG;;WAEV,KAAK;AACZ,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC;AACrF,WAAQ,KAAK,EAAE;;GAEjB;;AAGN,SAAgB,gCAAyC;AACvD,QAAO,IAAI,QAAQ,oBAAoB,CACpC,MAAM,cAAc,CACpB,YAAY,oCAAoC,CAChD,SAAS,eAAe,kBAAkB,IAAI,CAC9C,OAAO,aAAa,yBAAyB,MAAM,CACnD,OAAO,oBAAoB,cAAc,SAAS,CAClD,QAAQ,KAAa,SAA8C;EAClE,MAAM,OAAO,QAAQ,OAAO,IAAI;EAChC,MAAM,eAAe,KAAK,MAAM,SAAS;EACzC,MAAM,UAAU,KAAK,MAAM,eAAe;AAC1C,MAAI,CAAC,WAAW,aAAa,IAAI,CAAC,WAAW,QAAQ,EAAE;AACrD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,QAAQ,SAAS,uBAAuB,OAAO;AACnF,WAAQ,KAAK,EAAE;;AAEjB,MAAI;AAEF,OAAI,iBADQ,KAAK,MAAM,aAAa,SAAS,QAAQ,CAC7B,CAAC,EAAE;AACzB,YAAQ,MACN,OAAO,IAAI,SAAS,EACpB,qDACD;AACD,YAAQ,KAAK,EAAE;;AAIjB,OAAI,CADa,2BADL,KAAK,MAAM,aAAa,cAAc,QAAQ,CACX,CAClC,CAAC,IAAI;AAChB,YAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,sBAAsB;AAC1D,YAAQ,KAAK,EAAE;;WAEV,GAAG;AACV,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE,CAAC;AAC/E,WAAQ,KAAK,EAAE;;EAGjB,MAAM,OAAO,CAAC,WAAW,YAAY,KAAK,SAAS;AACnD,MAAI,KAAK,OAAQ,MAAK,KAAK,YAAY;AACvC,UAAQ,IAAI,OAAO,KAAK,WAAW,EAAE,OAAO,KAAK,KAAK,IAAI,GAAG;AAC7D,MAAI;AACF,YAAS,OAAO,KAAK,KAAK,IAAI,IAAI;IAAE,KAAK;IAAM,OAAO;IAAW,CAAC;UAC5D;AACN,WAAQ,KAAK,EAAE;;GAEjB;;AAGN,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,iEAAiE,CAC7E,SAAS,iBAAiB,mDAAmD,CAC7E,OAAO,YAAY,mCAAmC,MAAM,CAC5D,OAAO,OAAO,aAAiC,SAA8B;EAC5E,MAAM,MAAM,oBAAoB;EAChC,MAAM,MAAM,WAAW,IAAI,WAAW;EACtC,MAAM,UAAU,sBAAsB,IAAI;EAC1C,MAAM,YAAY,KAAK,SACnB,qBAAqB,IAAI,eAAe,KAAK,GAC7C,8BAA8B,KAAK,QAAQ;EAG/C,MAAM,OAAO,MADA,6BACU,CAAC,MAAM;EAC9B,MAAM,MAAM,aAAa,MAAM,GAC3B,CAAC,YAAY,MAAM,CAAC,GACpB,OAAO,KAAK,KAAK,WAAW;AAEhC,MAAI,IAAI,WAAW,GAAG;AACpB,WAAQ,IAAI,6BAA6B;AACzC;;AAGF,OAAK,MAAM,MAAM,KAAK;GACpB,MAAM,QAAQ,KAAK,WAAW;AAC9B,OAAI,CAAC,OAAO;AACV,YAAQ,IAAI,OAAO,OAAO,OAAO,EAAE,IAAI,oBAAoB;AAC3D;;AAEF,OAAI,MAAM,WAAW,OAAO;AAC1B,YAAQ,IAAI,OAAO,OAAO,OAAO,EAAE,IAAI,WAAW,MAAM,OAAO,GAAG;AAClE;;GAEF,MAAM,OAAO,MAAM,UAAU,MAAM,IAAK,MAAM,gBAAgB,GAAG;AACjE,OAAI,CAAC,MAAM;AACT,YAAQ,IAAI,OAAO,OAAO,OAAO,EAAE,IAAI,kCAAkC;AACzE;;AAEF,WAAQ,IAAI,OAAO,KAAK,WAAW,EAAE,IAAI,KAAK,KAAK;GACnD,MAAM,SAAS,MAAM,eAAe,MAAM,UAAU;AACpD,OAAI,CAAC,OAAO,IAAI;AACd,YAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,OAAO,SAAS,GAAG;AACvD,YAAQ,KAAK,EAAE;;AAEjB,WAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,GAAG;;GAEpC;;AAGN,eAAe,gBAAgB,IAAyC;AAEtE,SAAO,MADaC,cAA0B,GAAG,GACnC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createExtensionPackCommand(): Command;
@@ -0,0 +1,242 @@
1
+ import { PACKAGE_VERSION, init_package_version } from "../../package-version.js";
2
+ import { createLogger } from "../../utils/logger/index.js";
3
+ import { init_logger } from "../../utils/logger.js";
4
+ import { normalizeExtensionManifest } from "../../extensions/normalize-manifest.js";
5
+ import { checkEngineCompatibility } from "../../extensions/engine-check.js";
6
+ import { colors } from "../utils/colors.js";
7
+ import { isAbsolute, join, resolve } from "node:path";
8
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
9
+ import { Command } from "commander";
10
+ import { execSync } from "node:child_process";
11
+ //#region src/cli/commands/extension-pack.ts
12
+ init_package_version();
13
+ init_logger();
14
+ const log = createLogger("ExtensionPack");
15
+ const MANIFEST = "xopc.extension.json";
16
+ function isRecord(x) {
17
+ return typeof x === "object" && x !== null && !Array.isArray(x);
18
+ }
19
+ function loadJson(path) {
20
+ return JSON.parse(readFileSync(path, "utf-8"));
21
+ }
22
+ function loadManifestAtRoot(root, diagnostics) {
23
+ const manifestPath = join(root, MANIFEST);
24
+ if (!existsSync(manifestPath)) {
25
+ diagnostics.push({
26
+ level: "error",
27
+ message: `Missing ${MANIFEST} in ${root}`
28
+ });
29
+ return null;
30
+ }
31
+ try {
32
+ const raw = loadJson(manifestPath);
33
+ if (!isRecord(raw)) {
34
+ diagnostics.push({
35
+ level: "error",
36
+ message: `${MANIFEST} must be a JSON object`
37
+ });
38
+ return null;
39
+ }
40
+ return normalizeExtensionManifest(raw);
41
+ } catch (e) {
42
+ diagnostics.push({
43
+ level: "error",
44
+ message: `Failed to parse ${MANIFEST}: ${e instanceof Error ? e.message : String(e)}`
45
+ });
46
+ return null;
47
+ }
48
+ }
49
+ function collectContributionPaths(manifest, extRoot) {
50
+ const out = [];
51
+ const ui = manifest.ui;
52
+ if (ui?.main) out.push(join(extRoot, ui.main));
53
+ if (ui?.icon) out.push(join(extRoot, ui.icon));
54
+ const c = ui?.contributions;
55
+ if (!c) return out;
56
+ for (const p of c.sidebarPanels ?? []) if (p.entrypoint) out.push(join(extRoot, p.entrypoint));
57
+ for (const p of c.settingsPanels ?? []) if (p.entrypoint) out.push(join(extRoot, p.entrypoint));
58
+ for (const p of c.chatWidgets ?? []) if (p.entrypoint) out.push(join(extRoot, p.entrypoint));
59
+ for (const p of c.pages ?? []) if (p.entrypoint) out.push(join(extRoot, p.entrypoint));
60
+ for (const p of c.statusBarItems ?? []) if (p.entrypoint) out.push(join(extRoot, p.entrypoint));
61
+ return out;
62
+ }
63
+ function resolveMainFile(root, main) {
64
+ const cands = [
65
+ main,
66
+ "index.ts",
67
+ "index.js",
68
+ "extension.ts",
69
+ "extension.js"
70
+ ].filter((x) => typeof x === "string" && x.length > 0);
71
+ for (const c of cands) {
72
+ const p = join(root, c);
73
+ if (existsSync(p)) return p;
74
+ }
75
+ return null;
76
+ }
77
+ function validateManifest(ctx) {
78
+ const { manifest, extensionDir, diagnostics } = ctx;
79
+ if (!manifest.id || !String(manifest.id).trim()) diagnostics.push({
80
+ level: "error",
81
+ message: "Manifest \"id\" is required"
82
+ });
83
+ if (!resolveMainFile(extensionDir, manifest.main)) diagnostics.push({
84
+ level: "error",
85
+ message: `Main entry not found (expected main, index.ts, index.js, etc. in ${extensionDir})`
86
+ });
87
+ if (manifest.ui?.main) {
88
+ if (!existsSync(join(extensionDir, manifest.ui.main))) diagnostics.push({
89
+ level: "error",
90
+ message: `ui.main missing: ${manifest.ui.main}`
91
+ });
92
+ }
93
+ for (const p of collectContributionPaths(manifest, extensionDir)) if (!existsSync(p)) diagnostics.push({
94
+ level: "error",
95
+ message: `UI contribution entry missing: ${p}`
96
+ });
97
+ if (manifest.engines?.xopc) {
98
+ const r = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);
99
+ if (r.parseWarning) diagnostics.push({
100
+ level: "warning",
101
+ message: `engines.xopc parse issue — ${r.reason ?? "unknown"} (continuing)`
102
+ });
103
+ else if (!r.compatible) diagnostics.push({
104
+ level: "warning",
105
+ message: `engines.xopc not satisfied by current xopc ${PACKAGE_VERSION}: ${r.reason ?? manifest.engines.xopc}`
106
+ });
107
+ }
108
+ }
109
+ function validatePackageJson(ctx) {
110
+ const { packageJson, diagnostics, extensionDir } = ctx;
111
+ const deps = packageJson.dependencies;
112
+ if (isRecord(deps)) {
113
+ for (const [name, v] of Object.entries(deps)) if (typeof v === "string" && v.startsWith("workspace:")) diagnostics.push({
114
+ level: "warning",
115
+ message: `dependency "${name}": ${v} — will be replaced when packing from a pnpm workspace`
116
+ });
117
+ }
118
+ const files = packageJson.files;
119
+ if (Array.isArray(files)) {
120
+ if (!files.some((f) => f === MANIFEST || f === "**/xopc.extension.json")) diagnostics.push({
121
+ level: "warning",
122
+ message: `package.json "files" should include "${MANIFEST}" so the archive ships the manifest`
123
+ });
124
+ }
125
+ const keywords = packageJson.keywords;
126
+ if (Array.isArray(keywords) && !keywords.includes("xopc-extension")) diagnostics.push({
127
+ level: "info",
128
+ message: "Consider adding \"xopc-extension\" to package.json keywords for discoverability"
129
+ });
130
+ else if (!Array.isArray(keywords)) diagnostics.push({
131
+ level: "info",
132
+ message: "Consider adding keywords: [\"xopc-extension\", ...]"
133
+ });
134
+ if (!existsSync(join(extensionDir, "package.json"))) diagnostics.push({
135
+ level: "error",
136
+ message: "package.json is missing"
137
+ });
138
+ }
139
+ function pnpmAvailable() {
140
+ try {
141
+ execSync("pnpm --version", { stdio: "pipe" });
142
+ return true;
143
+ } catch {
144
+ return false;
145
+ }
146
+ }
147
+ function printDiagnostics(d) {
148
+ for (const x of d) if (x.level === "error") console.error(`${colors.red("error")}:`, x.message);
149
+ else if (x.level === "warning") console.log(`${colors.yellow("warning")}:`, x.message);
150
+ else console.log(`${colors.cyan("info")}:`, x.message);
151
+ }
152
+ function createExtensionPackCommand() {
153
+ return new Command("extension:pack").alias("ext:pack").description("Package an extension as a .tgz archive for distribution").argument("[dir]", "Extension directory (default: current working directory)", ".").option("--out <dir>", "Output directory for the .tgz (default: extension directory)", "").option("--no-build-ui", "Skip automatic \"npm run build:ui\" when defined").option("--dry-run", "Validate only; do not create an archive", false).action((dir, opts) => {
154
+ const extensionDir = resolve(dir || ".");
155
+ const outDir = opts.out && opts.out.length > 0 ? resolve(opts.out) : extensionDir;
156
+ const diagnostics = [];
157
+ if (!existsSync(extensionDir) || !existsSync(join(extensionDir, "package.json"))) {
158
+ console.error(colors.red("error:"), `Not an extension project (no package.json): ${extensionDir}`);
159
+ process.exit(1);
160
+ }
161
+ const manifest = loadManifestAtRoot(extensionDir, diagnostics);
162
+ if (!manifest) {
163
+ printDiagnostics(diagnostics);
164
+ process.exit(1);
165
+ }
166
+ let packageJson;
167
+ try {
168
+ packageJson = loadJson(join(extensionDir, "package.json"));
169
+ if (!isRecord(packageJson)) throw new Error("package.json must be an object");
170
+ } catch (e) {
171
+ log.error({ err: e }, "Failed to read package.json");
172
+ console.error(colors.red("error:"), e instanceof Error ? e.message : String(e));
173
+ process.exit(1);
174
+ }
175
+ const ctx = {
176
+ extensionDir,
177
+ manifest,
178
+ packageJson,
179
+ diagnostics
180
+ };
181
+ validateManifest(ctx);
182
+ validatePackageJson(ctx);
183
+ printDiagnostics(diagnostics);
184
+ if (diagnostics.some((d) => d.level === "error")) {
185
+ console.error(colors.red("Pack validation failed (fix errors above)."));
186
+ process.exit(1);
187
+ }
188
+ if (opts.dryRun) {
189
+ console.log(colors.green("OK"), " — dry run; no archive created");
190
+ return;
191
+ }
192
+ const scripts = isRecord(packageJson.scripts) ? packageJson.scripts : null;
193
+ if (opts.buildUi && scripts && typeof scripts["build:ui"] === "string") try {
194
+ console.log(colors.cyan("Running"), "npm run build:ui …");
195
+ execSync("npm run build:ui", {
196
+ cwd: extensionDir,
197
+ stdio: "inherit"
198
+ });
199
+ } catch (e) {
200
+ console.error(colors.red("error:"), `UI build failed: ${e instanceof Error ? e.message : String(e)}`);
201
+ process.exit(1);
202
+ }
203
+ let tarball;
204
+ try {
205
+ const lines = execSync(pnpmAvailable() ? "pnpm pack" : "npm pack", {
206
+ cwd: extensionDir,
207
+ encoding: "utf-8"
208
+ }).split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
209
+ const line = lines.slice().reverse().find((l) => l.endsWith(".tgz") && !l.startsWith("WARN")) ?? lines.at(-1) ?? "";
210
+ if (line.endsWith(".tgz")) tarball = isAbsolute(line) || line.startsWith("file:") ? resolve(line.replace(/^file:/, "")) : join(extensionDir, line);
211
+ else tarball = "";
212
+ if (!tarball) {
213
+ const tgzs = readdirSync(extensionDir).filter((f) => f.endsWith(".tgz"));
214
+ tgzs.sort((a, b) => statSync(join(extensionDir, b)).mtimeMs - statSync(join(extensionDir, a)).mtimeMs);
215
+ const last = tgzs[0];
216
+ tarball = last ? join(extensionDir, last) : "";
217
+ }
218
+ if (!tarball || !existsSync(tarball)) throw new Error("Could not locate .tgz after pack; check pnpm/npm output");
219
+ } catch (e) {
220
+ log.error({ err: e }, "pack failed");
221
+ console.error(colors.red("error:"), e instanceof Error ? e.message : String(e));
222
+ process.exit(1);
223
+ }
224
+ if (outDir !== extensionDir) try {
225
+ mkdirSync(outDir, { recursive: true });
226
+ const dest = join(outDir, tarball.includes("/") ? tarball.slice(tarball.lastIndexOf("/") + 1) : tarball);
227
+ renameSync(tarball, dest);
228
+ tarball = dest;
229
+ } catch (e) {
230
+ console.error(colors.red("error:"), `Failed to move archive to --out: ${e instanceof Error ? e.message : String(e)}`);
231
+ process.exit(1);
232
+ }
233
+ const displayPath = tarball;
234
+ console.log("");
235
+ console.log(colors.green("Pack complete:"), displayPath);
236
+ console.log(colors.cyan("Next:"), "install the .tgz with your extension workflow, or extract into the global / workspace extensions directory.");
237
+ });
238
+ }
239
+ //#endregion
240
+ export { createExtensionPackCommand };
241
+
242
+ //# sourceMappingURL=extension-pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-pack.js","names":[],"sources":["../../../../src/cli/commands/extension-pack.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync, readdirSync, renameSync, mkdirSync, statSync } from 'node:fs';\nimport { isAbsolute, join, resolve } from 'node:path';\n\nimport { Command } from 'commander';\n\nimport { checkEngineCompatibility } from '../../extensions/engine-check.js';\nimport type { ExtensionManifest } from '../../extensions/types/index.js';\nimport { normalizeExtensionManifest } from '../../extensions/normalize-manifest.js';\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { colors } from '../utils/colors.js';\n\nconst log = createLogger('ExtensionPack');\nconst MANIFEST = 'xopc.extension.json';\n\ninterface PackContext {\n extensionDir: string;\n manifest: ExtensionManifest;\n packageJson: Record<string, unknown>;\n diagnostics: PackDiagnostic[];\n}\n\ninterface PackDiagnostic {\n level: 'error' | 'warning' | 'info';\n message: string;\n}\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction loadJson(path: string): unknown {\n return JSON.parse(readFileSync(path, 'utf-8') as string) as unknown;\n}\n\nfunction loadManifestAtRoot(\n root: string,\n diagnostics: PackDiagnostic[],\n): ExtensionManifest | null {\n const manifestPath = join(root, MANIFEST);\n if (!existsSync(manifestPath)) {\n diagnostics.push({ level: 'error', message: `Missing ${MANIFEST} in ${root}` });\n return null;\n }\n try {\n const raw = loadJson(manifestPath);\n if (!isRecord(raw)) {\n diagnostics.push({ level: 'error', message: `${MANIFEST} must be a JSON object` });\n return null;\n }\n return normalizeExtensionManifest(raw);\n } catch (e) {\n diagnostics.push({\n level: 'error',\n message: `Failed to parse ${MANIFEST}: ${e instanceof Error ? e.message : String(e)}`,\n });\n return null;\n }\n}\n\nfunction collectContributionPaths(manifest: ExtensionManifest, extRoot: string): string[] {\n const out: string[] = [];\n const ui = manifest.ui;\n if (ui?.main) out.push(join(extRoot, ui.main));\n if (ui?.icon) out.push(join(extRoot, ui.icon));\n const c = ui?.contributions;\n if (!c) return out;\n for (const p of c.sidebarPanels ?? []) {\n if (p.entrypoint) out.push(join(extRoot, p.entrypoint));\n }\n for (const p of c.settingsPanels ?? []) {\n if (p.entrypoint) out.push(join(extRoot, p.entrypoint));\n }\n for (const p of c.chatWidgets ?? []) {\n if (p.entrypoint) out.push(join(extRoot, p.entrypoint));\n }\n for (const p of c.pages ?? []) {\n if (p.entrypoint) out.push(join(extRoot, p.entrypoint));\n }\n for (const p of c.statusBarItems ?? []) {\n if (p.entrypoint) out.push(join(extRoot, p.entrypoint));\n }\n return out;\n}\n\nfunction resolveMainFile(root: string, main?: string): string | null {\n const cands = [main, 'index.ts', 'index.js', 'extension.ts', 'extension.js'].filter(\n (x): x is string => typeof x === 'string' && x.length > 0,\n );\n for (const c of cands) {\n const p = join(root, c);\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nfunction validateManifest(ctx: PackContext): void {\n const { manifest, extensionDir, diagnostics } = ctx;\n if (!manifest.id || !String(manifest.id).trim()) {\n diagnostics.push({ level: 'error', message: 'Manifest \"id\" is required' });\n }\n const mainFile = resolveMainFile(extensionDir, manifest.main);\n if (!mainFile) {\n diagnostics.push({\n level: 'error',\n message: `Main entry not found (expected main, index.ts, index.js, etc. in ${extensionDir})`,\n });\n }\n\n if (manifest.ui?.main) {\n const p = join(extensionDir, manifest.ui.main);\n if (!existsSync(p)) {\n diagnostics.push({ level: 'error', message: `ui.main missing: ${manifest.ui.main}` });\n }\n }\n\n for (const p of collectContributionPaths(manifest, extensionDir)) {\n if (!existsSync(p)) {\n diagnostics.push({ level: 'error', message: `UI contribution entry missing: ${p}` });\n }\n }\n\n if (manifest.engines?.xopc) {\n const r = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);\n if (r.parseWarning) {\n diagnostics.push({\n level: 'warning',\n message: `engines.xopc parse issue — ${r.reason ?? 'unknown'} (continuing)`,\n });\n } else if (!r.compatible) {\n diagnostics.push({\n level: 'warning',\n message: `engines.xopc not satisfied by current xopc ${PACKAGE_VERSION}: ${r.reason ?? manifest.engines.xopc}`,\n });\n }\n }\n}\n\nfunction validatePackageJson(ctx: PackContext): void {\n const { packageJson, diagnostics, extensionDir } = ctx;\n const deps = packageJson.dependencies;\n if (isRecord(deps)) {\n for (const [name, v] of Object.entries(deps)) {\n if (typeof v === 'string' && v.startsWith('workspace:')) {\n diagnostics.push({\n level: 'warning',\n message: `dependency \"${name}\": ${v} — will be replaced when packing from a pnpm workspace`,\n });\n }\n }\n }\n\n const files = packageJson.files;\n if (Array.isArray(files)) {\n if (!files.some((f) => f === MANIFEST || f === '**/xopc.extension.json')) {\n diagnostics.push({\n level: 'warning',\n message: `package.json \"files\" should include \"${MANIFEST}\" so the archive ships the manifest`,\n });\n }\n }\n\n const keywords = packageJson.keywords;\n if (Array.isArray(keywords) && !keywords.includes('xopc-extension')) {\n diagnostics.push({\n level: 'info',\n message: 'Consider adding \"xopc-extension\" to package.json keywords for discoverability',\n });\n } else if (!Array.isArray(keywords)) {\n diagnostics.push({ level: 'info', message: 'Consider adding keywords: [\"xopc-extension\", ...]' });\n }\n\n if (!existsSync(join(extensionDir, 'package.json'))) {\n diagnostics.push({ level: 'error', message: 'package.json is missing' });\n }\n}\n\nfunction pnpmAvailable(): boolean {\n try {\n execSync('pnpm --version', { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction printDiagnostics(d: PackDiagnostic[]): void {\n for (const x of d) {\n if (x.level === 'error') {\n console.error(`${colors.red('error')}:`, x.message);\n } else if (x.level === 'warning') {\n console.log(`${colors.yellow('warning')}:`, x.message);\n } else {\n console.log(`${colors.cyan('info')}:`, x.message);\n }\n }\n}\n\nexport function createExtensionPackCommand(): Command {\n return new Command('extension:pack')\n .alias('ext:pack')\n .description('Package an extension as a .tgz archive for distribution')\n .argument('[dir]', 'Extension directory (default: current working directory)', '.')\n .option('--out <dir>', 'Output directory for the .tgz (default: extension directory)', '')\n .option('--no-build-ui', 'Skip automatic \"npm run build:ui\" when defined')\n .option('--dry-run', 'Validate only; do not create an archive', false)\n .action((dir: string, opts: { out?: string; buildUi: boolean; dryRun: boolean }) => {\n const extensionDir = resolve(dir || '.');\n const outDir = opts.out && opts.out.length > 0 ? resolve(opts.out) : extensionDir;\n const diagnostics: PackDiagnostic[] = [];\n if (!existsSync(extensionDir) || !existsSync(join(extensionDir, 'package.json'))) {\n console.error(\n colors.red('error:'),\n `Not an extension project (no package.json): ${extensionDir}`,\n );\n process.exit(1);\n }\n const manifest = loadManifestAtRoot(extensionDir, diagnostics);\n if (!manifest) {\n printDiagnostics(diagnostics);\n process.exit(1);\n }\n\n let packageJson: Record<string, unknown>;\n try {\n packageJson = loadJson(join(extensionDir, 'package.json')) as Record<string, unknown>;\n if (!isRecord(packageJson)) {\n throw new Error('package.json must be an object');\n }\n } catch (e) {\n log.error({ err: e }, 'Failed to read package.json');\n console.error(\n colors.red('error:'),\n e instanceof Error ? e.message : String(e),\n );\n process.exit(1);\n }\n\n const ctx: PackContext = { extensionDir, manifest, packageJson, diagnostics };\n validateManifest(ctx);\n validatePackageJson(ctx);\n\n printDiagnostics(diagnostics);\n\n const hasError = diagnostics.some((d) => d.level === 'error');\n if (hasError) {\n console.error(colors.red('Pack validation failed (fix errors above).'));\n process.exit(1);\n }\n\n if (opts.dryRun) {\n console.log(colors.green('OK'), ' — dry run; no archive created');\n return;\n }\n\n const scripts = isRecord(packageJson.scripts) ? (packageJson.scripts as Record<string, unknown>) : null;\n if (opts.buildUi && scripts && typeof scripts['build:ui'] === 'string') {\n try {\n console.log(colors.cyan('Running'), 'npm run build:ui …');\n execSync('npm run build:ui', { cwd: extensionDir, stdio: 'inherit' });\n } catch (e) {\n console.error(\n colors.red('error:'),\n `UI build failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n process.exit(1);\n }\n }\n\n let tarball: string;\n try {\n const cmd = pnpmAvailable() ? 'pnpm pack' : 'npm pack';\n const out = execSync(cmd, { cwd: extensionDir, encoding: 'utf-8' });\n const lines = out\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean);\n const line = lines\n .slice()\n .reverse()\n .find((l) => l.endsWith('.tgz') && !l.startsWith('WARN')) ?? lines.at(-1) ?? '';\n if (line.endsWith('.tgz')) {\n tarball = isAbsolute(line) || line.startsWith('file:') ? resolve(line.replace(/^file:/, '')) : join(extensionDir, line);\n } else {\n tarball = '';\n }\n if (!tarball) {\n const tgzs = readdirSync(extensionDir).filter((f) => f.endsWith('.tgz'));\n tgzs.sort(\n (a, b) => statSync(join(extensionDir, b)).mtimeMs - statSync(join(extensionDir, a)).mtimeMs,\n );\n const last = tgzs[0];\n tarball = last ? join(extensionDir, last) : '';\n }\n if (!tarball || !existsSync(tarball)) {\n throw new Error('Could not locate .tgz after pack; check pnpm/npm output');\n }\n } catch (e) {\n log.error({ err: e }, 'pack failed');\n console.error(\n colors.red('error:'),\n e instanceof Error ? e.message : String(e),\n );\n process.exit(1);\n }\n\n if (outDir !== extensionDir) {\n try {\n mkdirSync(outDir, { recursive: true });\n const base = tarball.includes('/') ? tarball.slice(tarball.lastIndexOf('/') + 1) : tarball;\n const dest = join(outDir, base);\n renameSync(tarball, dest);\n tarball = dest;\n } catch (e) {\n console.error(\n colors.red('error:'),\n `Failed to move archive to --out: ${e instanceof Error ? e.message : String(e)}`,\n );\n process.exit(1);\n }\n }\n\n const displayPath = tarball;\n console.log('');\n console.log(colors.green('Pack complete:'), displayPath);\n console.log(\n colors.cyan('Next:'),\n 'install the .tgz with your extension workflow, or extract into the global / workspace extensions directory.',\n );\n });\n}\n"],"mappings":"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"}
@@ -3,6 +3,9 @@ import { init_logger } from "../../utils/logger.js";
3
3
  import { colors } from "../utils/colors.js";
4
4
  import { getExtensionLockfileManager } from "../../extensions/lockfile.js";
5
5
  import { checkAllExtensionsHealth, getExtensionHealthChecker } from "../../extensions/health.js";
6
+ import { createExtensionPackCommand } from "./extension-pack.js";
7
+ import { createExtensionDevCommand } from "./extension-dev.js";
8
+ import { createExtensionPublishCommand, createExtensionSearchCommand, createExtensionUpdateCommand } from "./extension-marketplace.js";
6
9
  import { Command } from "commander";
7
10
  //#region src/cli/commands/extension.ts
8
11
  init_logger();
@@ -125,6 +128,11 @@ Related commands:
125
128
  xopc extension:health Health check (alias: ext:health)
126
129
  xopc extension:verify Verify integrity (alias: ext:verify)
127
130
  xopc extension:audit Security audit (alias: ext:audit)
131
+ xopc extension:pack Package extension .tgz (alias: ext:pack)
132
+ xopc extension:dev Dev mode (symlink + optional gateway) (alias: ext:dev)
133
+ xopc extension:search Search extension registry (alias: ext:search)
134
+ xopc extension:publish Publish extension to npm (alias: ext:publish)
135
+ xopc extension:update Update installed extensions (alias: ext:update)
128
136
  `).action((_opts, cmd) => {
129
137
  cmd.help();
130
138
  }));
@@ -133,6 +141,11 @@ Related commands:
133
141
  program.addCommand(createExtensionHealthCommand());
134
142
  program.addCommand(createExtensionVerifyCommand());
135
143
  program.addCommand(createExtensionAuditCommand());
144
+ program.addCommand(createExtensionPackCommand());
145
+ program.addCommand(createExtensionDevCommand());
146
+ program.addCommand(createExtensionSearchCommand());
147
+ program.addCommand(createExtensionPublishCommand());
148
+ program.addCommand(createExtensionUpdateCommand());
136
149
  }
137
150
  //#endregion
138
151
  export { createExtensionAuditCommand, createExtensionFreezeCommand, createExtensionHealthCommand, createExtensionListCommand, createExtensionVerifyCommand, registerExtensionCommands };
@@ -1 +1 @@
1
- {"version":3,"file":"extension.js","names":[],"sources":["../../../../src/cli/commands/extension.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport {\n getExtensionHealthChecker,\n checkAllExtensionsHealth,\n} from '../../extensions/health.js';\nimport { colors } from '../utils/colors.js';\n\nconst log = createLogger('ExtensionCommands');\n\n// ============================================\n// Extension List Command\n// ============================================\n\nexport function createExtensionListCommand(): Command {\n return new Command('extension:list')\n .alias('ext:list')\n .description('List installed extensions')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n const extensions = await lockfileManager.list();\n\n if (options.json) {\n console.log(JSON.stringify(extensions, null, 2));\n return;\n }\n\n if (extensions.length === 0) {\n console.log('No extensions installed.');\n return;\n }\n\n console.log(`Installed extensions (${extensions.length}):`);\n console.log();\n\n for (const ext of extensions) {\n console.log(`${colors.cyan(ext.name)}@${ext.version}`);\n console.log(` Source: ${ext.source}`);\n console.log(` Resolved: ${ext.resolved}`);\n console.log(` Installed: ${new Date(ext.installedAt).toLocaleString()}`);\n console.log();\n }\n } catch (error) {\n log.error({ error }, 'Failed to list extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Freeze Command\n// ============================================\n\nexport function createExtensionFreezeCommand(): Command {\n return new Command('extension:freeze')\n .alias('ext:freeze')\n .description('Lock current extension versions')\n .action(async () => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n await lockfileManager.freeze();\n\n console.log(colors.green('✓'), 'Extension versions locked');\n } catch (error) {\n log.error({ error }, 'Failed to freeze extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Health Command\n// ============================================\n\nexport function createExtensionHealthCommand(): Command {\n return new Command('extension:health')\n .alias('ext:health')\n .description('Check extension health')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const checker = getExtensionHealthChecker();\n const report = await checkAllExtensionsHealth();\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n return;\n }\n\n console.log(checker.formatReport(report));\n\n // Exit with error code if there are errors\n if (report.summary.error > 0) {\n process.exit(1);\n }\n } catch (error) {\n log.error({ error }, 'Failed to check extension health');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Verify Command\n// ============================================\n\nexport function createExtensionVerifyCommand(): Command {\n return new Command('extension:verify')\n .alias('ext:verify')\n .description('Verify extension integrity')\n .argument('[extension]', 'Specific extension to verify (default: all)')\n .action(async (extensionId) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n\n if (extensionId) {\n const result = await lockfileManager.verify(extensionId);\n\n if (result.valid) {\n console.log(colors.green('✓'), `Extension \"${extensionId}\" is valid`);\n } else {\n console.log(colors.red('✗'), `Extension \"${extensionId}\" is invalid: ${result.reason}`);\n process.exit(1);\n }\n } else {\n const results = await lockfileManager.verifyAll();\n let hasErrors = false;\n\n for (const result of results) {\n if (result.valid) {\n console.log(colors.green('✓'), result.extensionId);\n } else {\n console.log(colors.red('✗'), `${result.extensionId}: ${result.reason}`);\n hasErrors = true;\n }\n }\n\n if (hasErrors) {\n process.exit(1);\n }\n }\n } catch (error) {\n log.error({ error }, 'Failed to verify extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Audit Command\n// ============================================\n\nexport function createExtensionAuditCommand(): Command {\n return new Command('extension:audit')\n .alias('ext:audit')\n .description('Audit extensions for security issues')\n .action(async () => {\n try {\n const checker = getExtensionHealthChecker();\n\n // Check for orphaned extensions\n const orphaned = await checker.findOrphaned();\n\n if (orphaned.length > 0) {\n console.log(colors.yellow('⚠'), 'Orphaned extensions found:');\n for (const ext of orphaned) {\n console.log(` - ${ext}`);\n }\n console.log();\n console.log('These extensions are installed but not in the lockfile.');\n console.log('Run `xopc extension:freeze` to add them.');\n } else {\n console.log(colors.green('✓'), 'No orphaned extensions found');\n }\n\n // Run health check\n const report = await checkAllExtensionsHealth();\n\n if (report.summary.error > 0 || report.summary.warning > 0) {\n console.log();\n console.log(checker.formatReport(report));\n } else {\n console.log(colors.green('✓'), 'All extensions are healthy');\n }\n } catch (error) {\n log.error({ error }, 'Failed to audit extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Register All Commands\n// ============================================\n\nexport function registerExtensionCommands(program: Command): void {\n program.addCommand(\n new Command('extension')\n .description('Extension lockfile and health tools')\n .addHelpText(\n 'after',\n `\nRelated commands:\n xopc extension:list List installed extensions (alias: ext:list)\n xopc extension:freeze Lock extension versions (alias: ext:freeze)\n xopc extension:health Health check (alias: ext:health)\n xopc extension:verify Verify integrity (alias: ext:verify)\n xopc extension:audit Security audit (alias: ext:audit)\n`\n )\n .action((_opts, cmd) => {\n cmd.help();\n })\n );\n program.addCommand(createExtensionListCommand());\n program.addCommand(createExtensionFreezeCommand());\n program.addCommand(createExtensionHealthCommand());\n program.addCommand(createExtensionVerifyCommand());\n program.addCommand(createExtensionAuditCommand());\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"extension.js","names":[],"sources":["../../../../src/cli/commands/extension.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport {\n getExtensionHealthChecker,\n checkAllExtensionsHealth,\n} from '../../extensions/health.js';\nimport { colors } from '../utils/colors.js';\nimport { createExtensionPackCommand } from './extension-pack.js';\nimport { createExtensionDevCommand } from './extension-dev.js';\nimport {\n createExtensionPublishCommand,\n createExtensionSearchCommand,\n createExtensionUpdateCommand,\n} from './extension-marketplace.js';\n\nconst log = createLogger('ExtensionCommands');\n\n// ============================================\n// Extension List Command\n// ============================================\n\nexport function createExtensionListCommand(): Command {\n return new Command('extension:list')\n .alias('ext:list')\n .description('List installed extensions')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n const extensions = await lockfileManager.list();\n\n if (options.json) {\n console.log(JSON.stringify(extensions, null, 2));\n return;\n }\n\n if (extensions.length === 0) {\n console.log('No extensions installed.');\n return;\n }\n\n console.log(`Installed extensions (${extensions.length}):`);\n console.log();\n\n for (const ext of extensions) {\n console.log(`${colors.cyan(ext.name)}@${ext.version}`);\n console.log(` Source: ${ext.source}`);\n console.log(` Resolved: ${ext.resolved}`);\n console.log(` Installed: ${new Date(ext.installedAt).toLocaleString()}`);\n console.log();\n }\n } catch (error) {\n log.error({ error }, 'Failed to list extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Freeze Command\n// ============================================\n\nexport function createExtensionFreezeCommand(): Command {\n return new Command('extension:freeze')\n .alias('ext:freeze')\n .description('Lock current extension versions')\n .action(async () => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n await lockfileManager.freeze();\n\n console.log(colors.green('✓'), 'Extension versions locked');\n } catch (error) {\n log.error({ error }, 'Failed to freeze extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Health Command\n// ============================================\n\nexport function createExtensionHealthCommand(): Command {\n return new Command('extension:health')\n .alias('ext:health')\n .description('Check extension health')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const checker = getExtensionHealthChecker();\n const report = await checkAllExtensionsHealth();\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n return;\n }\n\n console.log(checker.formatReport(report));\n\n // Exit with error code if there are errors\n if (report.summary.error > 0) {\n process.exit(1);\n }\n } catch (error) {\n log.error({ error }, 'Failed to check extension health');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Verify Command\n// ============================================\n\nexport function createExtensionVerifyCommand(): Command {\n return new Command('extension:verify')\n .alias('ext:verify')\n .description('Verify extension integrity')\n .argument('[extension]', 'Specific extension to verify (default: all)')\n .action(async (extensionId) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n\n if (extensionId) {\n const result = await lockfileManager.verify(extensionId);\n\n if (result.valid) {\n console.log(colors.green('✓'), `Extension \"${extensionId}\" is valid`);\n } else {\n console.log(colors.red('✗'), `Extension \"${extensionId}\" is invalid: ${result.reason}`);\n process.exit(1);\n }\n } else {\n const results = await lockfileManager.verifyAll();\n let hasErrors = false;\n\n for (const result of results) {\n if (result.valid) {\n console.log(colors.green('✓'), result.extensionId);\n } else {\n console.log(colors.red('✗'), `${result.extensionId}: ${result.reason}`);\n hasErrors = true;\n }\n }\n\n if (hasErrors) {\n process.exit(1);\n }\n }\n } catch (error) {\n log.error({ error }, 'Failed to verify extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Audit Command\n// ============================================\n\nexport function createExtensionAuditCommand(): Command {\n return new Command('extension:audit')\n .alias('ext:audit')\n .description('Audit extensions for security issues')\n .action(async () => {\n try {\n const checker = getExtensionHealthChecker();\n\n // Check for orphaned extensions\n const orphaned = await checker.findOrphaned();\n\n if (orphaned.length > 0) {\n console.log(colors.yellow('⚠'), 'Orphaned extensions found:');\n for (const ext of orphaned) {\n console.log(` - ${ext}`);\n }\n console.log();\n console.log('These extensions are installed but not in the lockfile.');\n console.log('Run `xopc extension:freeze` to add them.');\n } else {\n console.log(colors.green('✓'), 'No orphaned extensions found');\n }\n\n // Run health check\n const report = await checkAllExtensionsHealth();\n\n if (report.summary.error > 0 || report.summary.warning > 0) {\n console.log();\n console.log(checker.formatReport(report));\n } else {\n console.log(colors.green('✓'), 'All extensions are healthy');\n }\n } catch (error) {\n log.error({ error }, 'Failed to audit extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Register All Commands\n// ============================================\n\nexport function registerExtensionCommands(program: Command): void {\n program.addCommand(\n new Command('extension')\n .description('Extension lockfile and health tools')\n .addHelpText(\n 'after',\n `\nRelated commands:\n xopc extension:list List installed extensions (alias: ext:list)\n xopc extension:freeze Lock extension versions (alias: ext:freeze)\n xopc extension:health Health check (alias: ext:health)\n xopc extension:verify Verify integrity (alias: ext:verify)\n xopc extension:audit Security audit (alias: ext:audit)\n xopc extension:pack Package extension .tgz (alias: ext:pack)\n xopc extension:dev Dev mode (symlink + optional gateway) (alias: ext:dev)\n xopc extension:search Search extension registry (alias: ext:search)\n xopc extension:publish Publish extension to npm (alias: ext:publish)\n xopc extension:update Update installed extensions (alias: ext:update)\n`\n )\n .action((_opts, cmd) => {\n cmd.help();\n })\n );\n program.addCommand(createExtensionListCommand());\n program.addCommand(createExtensionFreezeCommand());\n program.addCommand(createExtensionHealthCommand());\n program.addCommand(createExtensionVerifyCommand());\n program.addCommand(createExtensionAuditCommand());\n program.addCommand(createExtensionPackCommand());\n program.addCommand(createExtensionDevCommand());\n program.addCommand(createExtensionSearchCommand());\n program.addCommand(createExtensionPublishCommand());\n program.addCommand(createExtensionUpdateCommand());\n}\n"],"mappings":";;;;;;;;;;aACqD;AAerD,MAAM,MAAM,aAAa,oBAAoB;AAM7C,SAAgB,6BAAsC;AACpD,QAAO,IAAI,QAAQ,iBAAiB,CACjC,MAAM,WAAW,CACjB,YAAY,4BAA4B,CACxC,OAAO,UAAU,iBAAiB,CAClC,OAAO,OAAO,YAAY;AACzB,MAAI;GAEF,MAAM,aAAa,MADK,6BACgB,CAAC,MAAM;AAE/C,OAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;AAChD;;AAGF,OAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAI,2BAA2B;AACvC;;AAGF,WAAQ,IAAI,yBAAyB,WAAW,OAAO,IAAI;AAC3D,WAAQ,KAAK;AAEb,QAAK,MAAM,OAAO,YAAY;AAC5B,YAAQ,IAAI,GAAG,OAAO,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU;AACtD,YAAQ,IAAI,aAAa,IAAI,SAAS;AACtC,YAAQ,IAAI,eAAe,IAAI,WAAW;AAC1C,YAAQ,IAAI,gBAAgB,IAAI,KAAK,IAAI,YAAY,CAAC,gBAAgB,GAAG;AACzE,YAAQ,KAAK;;WAER,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,4BAA4B;AACjD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,kCAAkC,CAC9C,OAAO,YAAY;AAClB,MAAI;AAEF,SADwB,6BACH,CAAC,QAAQ;AAE9B,WAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,4BAA4B;WACpD,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,8BAA8B;AACnD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,yBAAyB,CACrC,OAAO,UAAU,iBAAiB,CAClC,OAAO,OAAO,YAAY;AACzB,MAAI;GACF,MAAM,UAAU,2BAA2B;GAC3C,MAAM,SAAS,MAAM,0BAA0B;AAE/C,OAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGF,WAAQ,IAAI,QAAQ,aAAa,OAAO,CAAC;AAGzC,OAAI,OAAO,QAAQ,QAAQ,EACzB,SAAQ,KAAK,EAAE;WAEV,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,mCAAmC;AACxD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,6BAA6B,CACzC,SAAS,eAAe,8CAA8C,CACtE,OAAO,OAAO,gBAAgB;AAC7B,MAAI;GACF,MAAM,kBAAkB,6BAA6B;AAErD,OAAI,aAAa;IACf,MAAM,SAAS,MAAM,gBAAgB,OAAO,YAAY;AAExD,QAAI,OAAO,MACT,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,cAAc,YAAY,YAAY;SAChE;AACL,aAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,cAAc,YAAY,gBAAgB,OAAO,SAAS;AACvF,aAAQ,KAAK,EAAE;;UAEZ;IACL,MAAM,UAAU,MAAM,gBAAgB,WAAW;IACjD,IAAI,YAAY;AAEhB,SAAK,MAAM,UAAU,QACnB,KAAI,OAAO,MACT,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,OAAO,YAAY;SAC7C;AACL,aAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,GAAG,OAAO,YAAY,IAAI,OAAO,SAAS;AACvE,iBAAY;;AAIhB,QAAI,UACF,SAAQ,KAAK,EAAE;;WAGZ,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,8BAA8B;AACnD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,8BAAuC;AACrD,QAAO,IAAI,QAAQ,kBAAkB,CAClC,MAAM,YAAY,CAClB,YAAY,uCAAuC,CACnD,OAAO,YAAY;AAClB,MAAI;GACF,MAAM,UAAU,2BAA2B;GAG3C,MAAM,WAAW,MAAM,QAAQ,cAAc;AAE7C,OAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,IAAI,OAAO,OAAO,IAAI,EAAE,6BAA6B;AAC7D,SAAK,MAAM,OAAO,SAChB,SAAQ,IAAI,OAAO,MAAM;AAE3B,YAAQ,KAAK;AACb,YAAQ,IAAI,0DAA0D;AACtE,YAAQ,IAAI,2CAA2C;SAEvD,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,+BAA+B;GAIhE,MAAM,SAAS,MAAM,0BAA0B;AAE/C,OAAI,OAAO,QAAQ,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,YAAQ,KAAK;AACb,YAAQ,IAAI,QAAQ,aAAa,OAAO,CAAC;SAEzC,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,6BAA6B;WAEvD,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,6BAA6B;AAClD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,0BAA0B,SAAwB;AAChE,SAAQ,WACN,IAAI,QAAQ,YAAY,CACrB,YAAY,sCAAsC,CAClD,YACC,SACA;;;;;;;;;;;;EAaD,CACA,QAAQ,OAAO,QAAQ;AACtB,MAAI,MAAM;GACV,CACL;AACD,SAAQ,WAAW,4BAA4B,CAAC;AAChD,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,6BAA6B,CAAC;AACjD,SAAQ,WAAW,4BAA4B,CAAC;AAChD,SAAQ,WAAW,2BAA2B,CAAC;AAC/C,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,+BAA+B,CAAC;AACnD,SAAQ,WAAW,8BAA8B,CAAC"}
@@ -28,7 +28,11 @@ let parsedOpts = {};
28
28
  function getContextWithOpts(argv = process.argv) {
29
29
  return createDefaultContext(argv, parsedOpts);
30
30
  }
31
- const LONG_RUNNING_COMMANDS = new Set(["gateway", "agent"]);
31
+ const LONG_RUNNING_COMMANDS = new Set([
32
+ "gateway",
33
+ "agent",
34
+ "extension:dev"
35
+ ]);
32
36
  const program = new Command().name("xopc").description("Ultra-Lightweight Personal AI Assistant").version(version).option("--verbose", "Enable verbose logging", false).option("--config <path>", "Config file path").option("--workspace <path>", "Workspace directory");
33
37
  program.hook("preAction", (thisCommand) => {
34
38
  parsedOpts = thisCommand.opts();