@xopcai/xopc 0.0.106 → 0.0.108
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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/dashscope/xopc.extension.json +7 -2
- package/dist/extensions/fal/xopc.extension.json +7 -2
- package/dist/extensions/feishu/src/adapters/gateway-setup.js +22 -26
- package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -1
- package/dist/extensions/feishu/xopc.extension.json +458 -26
- package/dist/extensions/google/xopc.extension.json +7 -2
- package/dist/extensions/minimax/xopc.extension.json +8 -2
- package/dist/extensions/openai/xopc.extension.json +7 -2
- package/dist/extensions/telegram/xopc.extension.json +10 -2
- package/dist/extensions/weixin/xopc.extension.json +57 -14
- package/dist/gateway/static/root/apple-touch-icon.png +0 -0
- package/dist/gateway/static/root/assets/agents-56kCGHdV.js +78 -0
- package/dist/gateway/static/root/assets/apps-page-Dd88J47r.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-Ckyvnvml.js +1 -0
- package/dist/gateway/static/root/assets/cron-page-DKo2ZdRA.js +1 -0
- package/dist/gateway/static/root/assets/{dist-OM9qGfm5.js → dist-dmxWdtPG.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-D-WHrr_w.js → extension-debug-page-iGpG-vpp.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CCgjSoKn.js → extension-page-I7-3uHiD.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BJH5a-Gn.js → extension-settings-page-BisnHG7r.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-CkvRO30i.js → fetch-CFdKBnE6.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BkKyRDrF.js → gateway-startup-retry-DdngdObI.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-CVyP6pFj.js → heartbeat-config-api-tbWAFPN8.js} +1 -1
- package/dist/gateway/static/root/assets/index-DI5_GsZt.css +1 -0
- package/dist/gateway/static/root/assets/index-slwUkhxH.js +4845 -0
- package/dist/gateway/static/root/assets/{logs-page-R6Vv_Ja6.js → logs-page-CCZiXrWu.js} +2 -2
- package/dist/gateway/static/root/assets/{note-detail-page-BUDarLhh.js → note-detail-page-BYbw2GLl.js} +4 -4
- package/dist/gateway/static/root/assets/{note-time-Cc2-T21g.js → note-time-Cya72Lte.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-DrAO7VRK.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-CrlOmEZt.js → schema-form-a6UJCK55.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-DNU3Ymvz.js +1 -0
- package/dist/gateway/static/root/assets/{settings-advanced-gate-BBAQxxew.js → settings-advanced-gate-CyEJYTbw.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-DjPD-ErC.js → settings-form-section-DpHo2ecA.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-YRwe4q56.js +3 -0
- package/dist/gateway/static/root/assets/{share-preview-page-BjvPht3V.js → share-preview-page-B7rf4QB4.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-we1NAt7u.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-DYgVdRB4.js → theme-store-BZozwAeK.js} +1 -1
- package/dist/gateway/static/root/assets/url-DQRqHuL-.js +3 -0
- package/dist/gateway/static/root/assets/voice-api-key-field-Btagks_B.js +1 -0
- package/dist/gateway/static/root/assets/{workflow-page.utils-D4sqR0yX.js → workflow-page.utils-DvzJKs6W.js} +1 -1
- package/dist/gateway/static/root/assets/workflows-page-BgOAgCOG.js +18 -0
- package/dist/gateway/static/root/favicon-16.png +0 -0
- package/dist/gateway/static/root/favicon-32.png +0 -0
- package/dist/gateway/static/root/favicon.ico +0 -0
- package/dist/gateway/static/root/favicon.svg +18 -0
- package/dist/gateway/static/root/index.html +11 -10
- package/dist/package.js +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +4 -0
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +4 -2
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
- package/dist/src/agent/starter-agents.d.ts +19 -0
- package/dist/src/agent/starter-agents.js +190 -0
- package/dist/src/agent/starter-agents.js.map +1 -0
- package/dist/src/agent/workflow/runtime.js +49 -15
- package/dist/src/agent/workflow/runtime.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +11 -0
- package/dist/src/channels/catalog/channel-catalog-service.js +13 -0
- package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -1
- package/dist/src/channels/plugins/types.adapters.d.ts +2 -0
- package/dist/src/cli/commands/extension-create.d.ts +2 -0
- package/dist/src/cli/commands/extension-create.js +165 -0
- package/dist/src/cli/commands/extension-create.js.map +1 -0
- package/dist/src/cli/commands/extension-dev.js +0 -2
- package/dist/src/cli/commands/extension-dev.js.map +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +104 -80
- package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
- package/dist/src/cli/commands/extension-pack.d.ts +13 -0
- package/dist/src/cli/commands/extension-pack.js +159 -91
- package/dist/src/cli/commands/extension-pack.js.map +1 -1
- package/dist/src/cli/commands/extension.d.ts +2 -0
- package/dist/src/cli/commands/extension.js +375 -3
- package/dist/src/cli/commands/extension.js.map +1 -1
- package/dist/src/cli/commands/gateway/run-foreground.js +1 -2
- package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
- package/dist/src/cli/commands/onboard.js +0 -2
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/setup.js +0 -2
- package/dist/src/cli/commands/setup.js.map +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +9 -6
- package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
- package/dist/src/config/paths.d.ts +2 -2
- package/dist/src/config/paths.js +10 -6
- package/dist/src/config/paths.js.map +1 -1
- package/dist/src/config/schema.d.ts +2 -0
- package/dist/src/config/schema.js +3 -1
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/extensions/api.d.ts +4 -2
- package/dist/src/extensions/api.js +31 -12
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -0
- package/dist/src/extensions/discover-extensions.js.map +1 -1
- package/dist/src/extensions/install.d.ts +1 -0
- package/dist/src/extensions/install.js +51 -8
- package/dist/src/extensions/install.js.map +1 -1
- package/dist/src/extensions/loader.d.ts +0 -4
- package/dist/src/extensions/loader.js +54 -87
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.d.ts +9 -1
- package/dist/src/extensions/lockfile.js.map +1 -1
- package/dist/src/extensions/normalize-manifest.js +20 -4
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/package-contract.d.ts +12 -0
- package/dist/src/extensions/package-contract.js +59 -0
- package/dist/src/extensions/package-contract.js.map +1 -0
- package/dist/src/extensions/sdk/core.d.ts +1 -1
- package/dist/src/extensions/sdk/index.d.ts +1 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/manifest.d.ts +15 -0
- package/dist/src/gateway/agents-admin.d.ts +0 -8
- package/dist/src/gateway/agents-admin.js +1 -26
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -55
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/channels.js +10 -1
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +130 -0
- package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +44 -0
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/notes/agent-context.d.ts +12 -4
- package/dist/src/notes/agent-context.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.js +0 -7
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.js +0 -7
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +0 -1
- package/dist/src/tui/tui-commands.js +1 -1
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-picker-overlay.js +1 -1
- package/dist/src/tui/tui-picker-overlay.js.map +1 -1
- package/dist/src/workflows/domain/definition-utils.d.ts +1 -0
- package/dist/src/workflows/domain/definition-utils.js +32 -2
- package/dist/src/workflows/domain/definition-utils.js.map +1 -1
- package/dist/src/workflows/domain/definition.d.ts +2 -0
- package/dist/src/workflows/domain/event.d.ts +2 -1
- package/dist/src/workflows/domain/index.d.ts +1 -0
- package/dist/src/workflows/domain/index.js +3 -2
- package/dist/src/workflows/domain/run.d.ts +27 -1
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/domain/schema-validation.d.ts +8 -0
- package/dist/src/workflows/domain/schema-validation.js +28 -0
- package/dist/src/workflows/domain/schema-validation.js.map +1 -0
- package/dist/src/workflows/draft/index.d.ts +3 -0
- package/dist/src/workflows/draft/index.js +3 -0
- package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +23 -0
- package/dist/src/workflows/draft/workflow-draft-prompt.js +98 -0
- package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -0
- package/dist/src/workflows/draft/workflow-draft-service.d.ts +12 -0
- package/dist/src/workflows/draft/workflow-draft-service.js +131 -0
- package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -0
- package/dist/src/workflows/draft/workflow-draft-validator.d.ts +4 -0
- package/dist/src/workflows/draft/workflow-draft-validator.js +133 -0
- package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -0
- package/dist/src/workflows/draft/workflow-draft.types.d.ts +44 -0
- package/dist/src/workflows/draft/workflow-draft.types.js +1 -0
- package/dist/src/workflows/engine/projector.js +1 -0
- package/dist/src/workflows/engine/projector.js.map +1 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +18 -0
- package/dist/src/workflows/engine/workflow-engine.js +320 -11
- package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
- package/dist/src/workflows/index.js +4 -3
- package/dist/src/workflows/service/workflow-run-service.d.ts +14 -3
- package/dist/src/workflows/service/workflow-run-service.js +227 -6
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +7 -2
- package/package.json +4 -2
- package/dist/gateway/static/root/assets/agents-3eP0vqFO.js +0 -396
- package/dist/gateway/static/root/assets/apps-page-CZ2ZKrko.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-BbETa93K.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-DCtUkHMu.js +0 -1
- package/dist/gateway/static/root/assets/index-BPYKW7FB.css +0 -1
- package/dist/gateway/static/root/assets/index-CEZxETzw.js +0 -4845
- package/dist/gateway/static/root/assets/notes-page-EAHl16bq.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-Ce_xuuSB.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-KhQ9QgH0.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-C0laq7l1.js +0 -2
- package/dist/gateway/static/root/assets/url-DPEStU4M.js +0 -3
- package/dist/gateway/static/root/assets/voice-api-key-field-DeGckWkl.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-DFjM95g5.js +0 -27
- package/dist/src/agent/builtin-agent-ids.d.ts +0 -2
- package/dist/src/agent/builtin-agent-ids.js +0 -17
- package/dist/src/agent/builtin-agent-ids.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-marketplace.js","names":["marketplace.findExtension","marketplace.listExtensions","marketplace.searchExtensions","marketplace.fetchRegistry","marketplace.getExtensionMarketplaceStoreBaseUrl"],"sources":["../../../../src/cli/commands/extension-marketplace.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync, statSync, rmSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nimport { Command } from 'commander';\nimport semver from 'semver';\n\nimport {\n downloadExtensionStoreZipBuffer,\n resolveExtensionZipDownloadUrl,\n resolveExtensionsStoreBaseUrl,\n} from '../../agent/skills/marketplace/adapters/store/store-api-client.js';\nimport { loadConfig } from '../../config/loader.js';\nimport { resolveExtensionsDir } from '../../config/paths.js';\nimport type { InstallResult } from '../../extensions/install.js';\nimport {\n installExtensionFromStoreZip,\n installFromLocal,\n installFromNpm,\n peekExtensionIdFromStoreZip,\n} 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 '../context.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\nfunction parseNameAtVersion(raw: string): { name: string; version?: string } {\n const t = raw.trim();\n const at = t.lastIndexOf('@');\n if (at <= 0 || at === t.length - 1) return { name: t };\n const maybeVer = t.slice(at + 1);\n const v = semver.valid(maybeVer);\n if (v) return { name: t.slice(0, at), version: v };\n return { name: t };\n}\n\nfunction looksLikeLocalPath(raw: string): boolean {\n const p = raw.trim();\n if (p.startsWith('./') || p.startsWith('../')) return true;\n if (p === '.' || p === '..') return true;\n try {\n const abs = resolve(process.cwd(), p);\n return existsSync(abs) && statSync(abs).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** xopc-store package names: lowercase letters, digits, hyphen (see xopc-store scan). */\nconst STORE_NAME_RE = /^[a-z0-9-]{1,64}$/;\n\nfunction looksLikeStorePackageRef(raw: string): boolean {\n const { name } = parseNameAtVersion(raw);\n return STORE_NAME_RE.test(name);\n}\n\nasync function upsertNpmExtensionLock(\n lock: ReturnType<typeof getExtensionLockfileManager>,\n targetDir: string,\n result: InstallResult,\n spec: string,\n): Promise<void> {\n if (!result.extensionId) return;\n const reg = await marketplace.findExtension(result.extensionId);\n const resolved = reg?.npmPackage ?? spec;\n let ver = reg?.version ?? '0.0.0';\n try {\n const raw = readFileSync(join(targetDir, result.extensionId, MANIFEST), 'utf-8');\n const m = JSON.parse(raw) as { version?: string };\n const mv = typeof m.version === 'string' ? semver.valid(m.version) : null;\n if (mv) ver = mv;\n } catch {\n /* keep registry / fallback version */\n }\n await lock.upsert(result.extensionId, {\n name: result.extensionId,\n version: ver,\n resolved,\n source: 'npm',\n });\n}\n\nasync function installExtensionFromStoreWithLock(params: {\n storeBase: string;\n packageName: string;\n version?: string;\n targetDir: string;\n lock: ReturnType<typeof getExtensionLockfileManager>;\n force?: boolean;\n}): Promise<{ ok: true; extensionId: string; version: string } | { ok: false; error: string }> {\n try {\n const { downloadUrl, version } = await resolveExtensionZipDownloadUrl(\n params.storeBase,\n params.packageName,\n params.version,\n );\n console.log(\n colors.cyan('📦'),\n `Downloading ${params.packageName}@${version} from xopc-store (${params.storeBase})…`,\n );\n const buf = await downloadExtensionStoreZipBuffer(params.storeBase, downloadUrl);\n if (params.force) {\n const id = peekExtensionIdFromStoreZip(buf);\n if (id && existsSync(join(params.targetDir, id))) {\n rmSync(join(params.targetDir, id), { recursive: true, force: true });\n }\n }\n const result = await installExtensionFromStoreZip(buf, params.targetDir);\n if (!result.ok || !result.extensionId) {\n return { ok: false, error: result.error ?? 'install failed' };\n }\n await params.lock.upsert(result.extensionId, {\n name: result.extensionId,\n version,\n resolved: params.packageName,\n source: 'store',\n });\n return { ok: true, extensionId: result.extensionId, version };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return { ok: false, error: msg };\n }\n}\n\nexport function createExtensionInstallCommand(): Command {\n return new Command('install')\n .description(\n 'Install extension from xopc-store (store.xopc.ai), npm, or a local directory into ~/.xopc/extensions',\n )\n .argument(\n '<target>',\n 'npm spec, path, store:id, or store-shaped id (npm is tried first; use --store / store: for store-only)',\n )\n .option('--store', 'Install from xopc-store only (fail if not an extension package)', false)\n .option('--npm', 'Install from npm only', false)\n .option(\n '-f, --force',\n 'Remove existing extension folder (manifest id) before store or local install',\n false,\n )\n .action(\n async (\n target: string,\n opts: { store: boolean; npm: boolean; force: boolean },\n ) => {\n const ctx = getContextWithOpts();\n const cfg = loadConfig(ctx.configPath);\n const targetDir = resolveExtensionsDir();\n const lock = getExtensionLockfileManager();\n\n let installTarget = target.trim();\n const storeExplicit = /^store:/i.test(installTarget);\n if (storeExplicit) {\n installTarget = installTarget.replace(/^store:/i, '').trim();\n }\n if (!installTarget) {\n console.error(colors.red('error:'), 'Missing target');\n process.exit(1);\n }\n\n if (opts.store && opts.npm) {\n console.error(colors.red('error:'), 'Use only one of --store and --npm');\n process.exit(1);\n }\n\n const storeOnly = opts.store || storeExplicit;\n if (storeExplicit && opts.npm) {\n console.error(colors.red('error:'), 'Cannot combine store: prefix with --npm');\n process.exit(1);\n }\n\n const storeBase = resolveExtensionsStoreBaseUrl(cfg);\n\n if (storeOnly) {\n const { name: pkgName, version: ver } = parseNameAtVersion(installTarget);\n if (!STORE_NAME_RE.test(pkgName)) {\n console.error(\n colors.red('error:'),\n 'Invalid store package name (lowercase letters, digits, hyphen only)',\n );\n process.exit(1);\n }\n const r = await installExtensionFromStoreWithLock({\n storeBase,\n packageName: pkgName,\n version: ver,\n targetDir,\n lock,\n force: opts.force,\n });\n if (r.ok === false) {\n console.error(colors.red('error:'), r.error);\n process.exit(1);\n }\n console.log(colors.green('✓'), `${r.extensionId}@${r.version} (store)`);\n return;\n }\n\n if (opts.npm) {\n const spec = installTarget;\n console.log(colors.cyan('📦'), `Installing from npm: ${spec}…`);\n const result = await installFromNpm(spec, targetDir);\n if (!result.ok) {\n console.error(colors.red('error:'), result.error ?? 'install failed');\n process.exit(1);\n }\n await upsertNpmExtensionLock(lock, targetDir, result, spec);\n console.log(colors.green('✓'), result.extensionId ?? 'ok', '(npm)');\n return;\n }\n\n if (looksLikeLocalPath(installTarget)) {\n const sourceDir = resolve(process.cwd(), installTarget);\n if (opts.force) {\n const manifestPath = join(sourceDir, MANIFEST);\n if (existsSync(manifestPath)) {\n try {\n const raw = readFileSync(manifestPath, 'utf-8');\n const m = JSON.parse(raw) as { id?: string };\n const extId =\n typeof m.id === 'string' &&\n m.id &&\n !m.id.includes('/') &&\n !m.id.includes('\\\\')\n ? m.id\n : undefined;\n if (extId && existsSync(join(targetDir, extId))) {\n rmSync(join(targetDir, extId), { recursive: true, force: true });\n }\n } catch {\n /* installFromLocal will surface manifest errors */\n }\n }\n }\n console.log(colors.cyan('📂'), 'Installing from local directory…');\n const result = await installFromLocal(sourceDir, targetDir);\n if (!result.ok) {\n console.error(colors.red('error:'), result.error ?? 'install failed');\n process.exit(1);\n }\n console.log(colors.green('✓'), result.extensionId ?? 'ok');\n return;\n }\n\n if (looksLikeStorePackageRef(installTarget)) {\n const spec = installTarget;\n console.log(colors.cyan('📦'), `Trying npm: ${spec}…`);\n const npmTry = await installFromNpm(spec, targetDir);\n if (npmTry.ok) {\n await upsertNpmExtensionLock(lock, targetDir, npmTry, spec);\n console.log(colors.green('✓'), npmTry.extensionId ?? 'ok', '(npm)');\n return;\n }\n console.log(colors.yellow('npm:'), npmTry.error ?? 'failed', '— trying xopc-store…');\n const { name: pkgName, version: ver } = parseNameAtVersion(installTarget);\n const r = await installExtensionFromStoreWithLock({\n storeBase,\n packageName: pkgName,\n version: ver,\n targetDir,\n lock,\n force: opts.force,\n });\n if (r.ok === false) {\n console.error(colors.red('error:'), r.error);\n process.exit(1);\n }\n console.log(colors.green('✓'), `${r.extensionId}@${r.version} (store)`);\n return;\n }\n\n const spec = installTarget;\n console.log(colors.cyan('📦'), `Installing from npm: ${spec}…`);\n const result = await installFromNpm(spec, targetDir);\n if (!result.ok) {\n console.error(colors.red('error:'), result.error ?? 'install failed');\n process.exit(1);\n }\n await upsertNpmExtensionLock(lock, targetDir, result, spec);\n console.log(colors.green('✓'), result.extensionId ?? 'ok', '(npm)');\n },\n );\n}\n\nexport function createExtensionSearchCommand(): Command {\n return new Command('search')\n .description('Search extensions listed on xopc-store')\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(`xopc-store: ${marketplace.getExtensionMarketplaceStoreBaseUrl()}`);\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('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('update')\n .description('Re-install extension(s) from the lockfile (npm or xopc-store) under ~/.xopc/extensions')\n .argument('[extensionId]', 'Specific extension id (default: all in lockfile)')\n .action(async (extensionId: string | undefined) => {\n const ctx = getContextWithOpts();\n const cfg = loadConfig(ctx.configPath);\n const targetDir = resolveExtensionsDir();\n const storeBase = resolveExtensionsStoreBaseUrl(cfg);\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 === 'store') {\n const pkgName = entry.resolved?.trim() || id;\n console.log(colors.cyan('Updating'), id, '←', `store:${pkgName}`);\n if (existsSync(join(targetDir, id))) {\n rmSync(join(targetDir, id), { recursive: true, force: true });\n }\n const r = await installExtensionFromStoreWithLock({\n storeBase,\n packageName: pkgName,\n targetDir,\n lock,\n });\n if (r.ok === false) {\n console.error(colors.red('error:'), r.error ?? id);\n process.exit(1);\n }\n console.log(colors.green('✓'), id);\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 if (existsSync(join(targetDir, id))) {\n rmSync(join(targetDir, id), { recursive: true, force: true });\n }\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 await lock.upsert(id, {\n name: id,\n version: entry.version,\n resolved: spec,\n source: 'npm',\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":"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"}
|
|
1
|
+
{"version":3,"file":"extension-marketplace.js","names":["marketplace.findExtension","marketplace.listExtensions","marketplace.searchExtensions","marketplace.fetchRegistry","marketplace.getExtensionMarketplaceStoreBaseUrl"],"sources":["../../../../src/cli/commands/extension-marketplace.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { execSync } from 'node:child_process';\nimport { existsSync, readFileSync, statSync, rmSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nimport { confirm } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport semver from 'semver';\n\nimport {\n downloadExtensionStoreZipBuffer,\n resolveExtensionZipDownloadUrl,\n resolveExtensionsStoreBaseUrl,\n} from '../../agent/skills/marketplace/adapters/store/store-api-client.js';\nimport { loadConfig } from '../../config/loader.js';\nimport { resolveExtensionsDir } from '../../config/paths.js';\nimport type { InstallResult } from '../../extensions/install.js';\nimport {\n installExtensionFromStoreZip,\n installFromLocal,\n installFromNpm,\n peekExtensionIdFromStoreZip,\n peekExtensionManifestFromStoreZip,\n} from '../../extensions/install.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport * as marketplace from '../../extensions/marketplace.js';\nimport { colors } from '../utils/colors.js';\nimport { getContextWithOpts } from '../context.js';\nimport { validateExtensionPackageDirectory } from './extension-pack.js';\n\nconst MANIFEST = 'xopc.extension.json';\n\nfunction readJsonObject(path: string): Record<string, unknown> | undefined {\n try {\n const raw = JSON.parse(readFileSync(path, 'utf-8')) as unknown;\n return typeof raw === 'object' && raw !== null && !Array.isArray(raw)\n ? (raw as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction readInstalledSnapshots(targetDir: string, extensionId: string): {\n manifest?: Record<string, unknown>;\n packageJson?: Record<string, unknown>;\n} {\n const root = join(targetDir, extensionId);\n return {\n manifest: readJsonObject(join(root, MANIFEST)),\n packageJson: readJsonObject(join(root, 'package.json')),\n };\n}\n\nfunction sha256Integrity(buffer: Buffer): string {\n return `sha256-${createHash('sha256').update(buffer).digest('base64')}`;\n}\n\nfunction normalizeIntegrity(raw: string | undefined): string | undefined {\n const value = raw?.trim();\n if (!value) return undefined;\n if (value.startsWith('sha256-')) return value;\n if (/^[a-f0-9]{64}$/i.test(value)) {\n return `sha256-${Buffer.from(value, 'hex').toString('base64')}`;\n }\n return value;\n}\n\nfunction printManifestSummary(params: {\n source: 'store' | 'npm' | 'local';\n packageName: string;\n version?: string;\n integrity?: string;\n manifest?: Record<string, unknown>;\n}): void {\n const manifest = params.manifest;\n console.log('');\n console.log(colors.cyan('Extension install review'));\n console.log(` Source: ${params.source}`);\n console.log(` Package: ${params.packageName}${params.version ? `@${params.version}` : ''}`);\n if (params.integrity) console.log(` Integrity: ${params.integrity}`);\n if (manifest) {\n console.log(` ID: ${String(manifest.id ?? '(unknown)')}`);\n console.log(` Name: ${String(manifest.name ?? manifest.id ?? '(unknown)')}`);\n const engines = manifest.engines as Record<string, unknown> | undefined;\n if (engines?.xopc) console.log(` engines.xopc: ${String(engines.xopc)}`);\n const permissions = manifest.permissions as Record<string, unknown> | undefined;\n if (permissions) {\n console.log(' Permissions:');\n for (const [key, value] of Object.entries(permissions)) {\n console.log(` ${key}: ${Array.isArray(value) ? value.join(', ') : String(value)}`);\n }\n }\n const contracts = manifest.contracts as Record<string, unknown> | undefined;\n if (contracts) {\n console.log(' Contracts:');\n for (const [key, value] of Object.entries(contracts)) {\n if (Array.isArray(value) && value.length > 0) console.log(` ${key}: ${value.join(', ')}`);\n }\n }\n }\n console.log('');\n}\n\nasync function confirmInstall(params: Parameters<typeof printManifestSummary>[0] & { yes?: boolean }): Promise<boolean> {\n printManifestSummary(params);\n if (params.yes || !process.stdin.isTTY) return true;\n return await confirm({ message: 'Install this extension?', default: false });\n}\n\nfunction parseNameAtVersion(raw: string): { name: string; version?: string } {\n const t = raw.trim();\n const at = t.lastIndexOf('@');\n if (at <= 0 || at === t.length - 1) return { name: t };\n const maybeVer = t.slice(at + 1);\n const v = semver.valid(maybeVer);\n if (v) return { name: t.slice(0, at), version: v };\n return { name: t };\n}\n\nfunction looksLikeLocalPath(raw: string): boolean {\n const p = raw.trim();\n if (p.startsWith('./') || p.startsWith('../')) return true;\n if (p === '.' || p === '..') return true;\n try {\n const abs = resolve(process.cwd(), p);\n return existsSync(abs) && statSync(abs).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** xopc-store package names: lowercase letters, digits, hyphen (see xopc-store scan). */\nconst STORE_NAME_RE = /^[a-z0-9-]{1,64}$/;\n\nasync function upsertNpmExtensionLock(\n lock: ReturnType<typeof getExtensionLockfileManager>,\n targetDir: string,\n result: InstallResult,\n spec: string,\n): Promise<void> {\n if (!result.extensionId) return;\n const reg = await marketplace.findExtension(result.extensionId);\n const resolved = reg?.npmPackage ?? spec;\n let ver = reg?.version ?? '0.0.0';\n try {\n const raw = readFileSync(join(targetDir, result.extensionId, MANIFEST), 'utf-8');\n const m = JSON.parse(raw) as { version?: string };\n const mv = typeof m.version === 'string' ? semver.valid(m.version) : null;\n if (mv) ver = mv;\n } catch {\n /* keep registry / fallback version */\n }\n await lock.upsert(result.extensionId, {\n name: result.extensionId,\n version: ver,\n resolved,\n source: 'npm',\n ...readInstalledSnapshots(targetDir, result.extensionId),\n });\n}\n\nasync function installExtensionFromStoreWithLock(params: {\n storeBase: string;\n packageName: string;\n version?: string;\n targetDir: string;\n lock: ReturnType<typeof getExtensionLockfileManager>;\n force?: boolean;\n yes?: boolean;\n}): Promise<{ ok: true; extensionId: string; version: string } | { ok: false; error: string }> {\n try {\n const { downloadUrl, version, integrity: expectedIntegrityRaw } = await resolveExtensionZipDownloadUrl(\n params.storeBase,\n params.packageName,\n params.version,\n );\n console.log(\n colors.cyan('📦'),\n `Downloading ${params.packageName}@${version} from xopc-store (${params.storeBase})…`,\n );\n const buf = await downloadExtensionStoreZipBuffer(params.storeBase, downloadUrl);\n const actualIntegrity = sha256Integrity(buf);\n const expectedIntegrity = normalizeIntegrity(expectedIntegrityRaw);\n if (expectedIntegrity && expectedIntegrity !== actualIntegrity) {\n return {\n ok: false,\n error: `Extension artifact checksum mismatch: expected ${expectedIntegrity}, got ${actualIntegrity}`,\n };\n }\n const manifest = peekExtensionManifestFromStoreZip(buf);\n const accepted = await confirmInstall({\n source: 'store',\n packageName: params.packageName,\n version,\n integrity: actualIntegrity,\n manifest,\n yes: params.yes,\n });\n if (!accepted) {\n return { ok: false, error: 'Install cancelled' };\n }\n if (params.force) {\n const id = peekExtensionIdFromStoreZip(buf);\n if (id && existsSync(join(params.targetDir, id))) {\n rmSync(join(params.targetDir, id), { recursive: true, force: true });\n }\n }\n const result = await installExtensionFromStoreZip(buf, params.targetDir);\n if (!result.ok || !result.extensionId) {\n return { ok: false, error: result.error ?? 'install failed' };\n }\n await params.lock.upsert(result.extensionId, {\n name: result.extensionId,\n version,\n resolved: params.packageName,\n source: 'store',\n artifactUrl: downloadUrl,\n integrity: actualIntegrity,\n ...readInstalledSnapshots(params.targetDir, result.extensionId),\n });\n return { ok: true, extensionId: result.extensionId, version };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return { ok: false, error: msg };\n }\n}\n\nexport function createExtensionInstallCommand(): Command {\n return new Command('install')\n .description(\n 'Install extension from xopc-store (store.xopc.ai), npm, or a local directory into ~/.xopc/extensions',\n )\n .argument(\n '<target>',\n 'Explicit source spec: store:<id>, npm:<package>, or a local extension directory',\n )\n .option(\n '-f, --force',\n 'Remove existing extension folder (manifest id) before store or local install',\n false,\n )\n .option('-y, --yes', 'Skip interactive install confirmation', false)\n .action(\n async (\n target: string,\n opts: { force: boolean; yes: boolean },\n ) => {\n const ctx = getContextWithOpts();\n const cfg = loadConfig(ctx.configPath);\n const targetDir = resolveExtensionsDir();\n const lock = getExtensionLockfileManager();\n\n let installTarget = target.trim();\n const storeExplicit = /^store:/i.test(installTarget);\n const npmExplicit = /^npm:/i.test(installTarget);\n if (storeExplicit) {\n installTarget = installTarget.replace(/^store:/i, '').trim();\n } else if (npmExplicit) {\n installTarget = installTarget.replace(/^npm:/i, '').trim();\n }\n if (!installTarget) {\n console.error(colors.red('error:'), 'Missing target');\n process.exit(1);\n }\n\n const storeBase = resolveExtensionsStoreBaseUrl(cfg);\n\n if (storeExplicit) {\n const { name: pkgName, version: ver } = parseNameAtVersion(installTarget);\n if (!STORE_NAME_RE.test(pkgName)) {\n console.error(\n colors.red('error:'),\n 'Invalid store package name (lowercase letters, digits, hyphen only)',\n );\n process.exit(1);\n }\n const r = await installExtensionFromStoreWithLock({\n storeBase,\n packageName: pkgName,\n version: ver,\n targetDir,\n lock,\n force: opts.force,\n yes: opts.yes,\n });\n if (r.ok === false) {\n console.error(colors.red('error:'), r.error);\n process.exit(1);\n }\n console.log(colors.green('✓'), `${r.extensionId}@${r.version} (store)`);\n return;\n }\n\n if (npmExplicit) {\n const spec = installTarget;\n console.log(colors.cyan('📦'), `Installing from npm: ${spec}…`);\n const result = await installFromNpm(spec, targetDir);\n if (!result.ok) {\n console.error(colors.red('error:'), result.error ?? 'install failed');\n process.exit(1);\n }\n await upsertNpmExtensionLock(lock, targetDir, result, spec);\n console.log(colors.green('✓'), result.extensionId ?? 'ok', '(npm)');\n return;\n }\n\n if (looksLikeLocalPath(installTarget)) {\n const sourceDir = resolve(process.cwd(), installTarget);\n if (opts.force) {\n const manifestPath = join(sourceDir, MANIFEST);\n if (existsSync(manifestPath)) {\n try {\n const raw = readFileSync(manifestPath, 'utf-8');\n const m = JSON.parse(raw) as { id?: string };\n const extId =\n typeof m.id === 'string' &&\n m.id &&\n !m.id.includes('/') &&\n !m.id.includes('\\\\')\n ? m.id\n : undefined;\n if (extId && existsSync(join(targetDir, extId))) {\n rmSync(join(targetDir, extId), { recursive: true, force: true });\n }\n } catch {\n /* installFromLocal will surface manifest errors */\n }\n }\n }\n console.log(colors.cyan('📂'), 'Installing from local directory…');\n const result = await installFromLocal(sourceDir, targetDir);\n if (!result.ok) {\n console.error(colors.red('error:'), result.error ?? 'install failed');\n process.exit(1);\n }\n console.log(colors.green('✓'), result.extensionId ?? 'ok');\n return;\n }\n\n console.error(\n colors.red('error:'),\n 'Extension installs require an explicit source: store:<id>, npm:<package>, or a local directory path.',\n );\n process.exit(1);\n },\n );\n}\n\nexport function createExtensionSearchCommand(): Command {\n return new Command('search')\n .description('Search extensions listed on xopc-store')\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(`xopc-store: ${marketplace.getExtensionMarketplaceStoreBaseUrl()}`);\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('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 const validation = validateExtensionPackageDirectory(root);\n for (const d of validation.diagnostics) {\n const label = d.level === 'error' ? colors.red('error') : d.level === 'warning' ? colors.yellow('warning') : colors.cyan('info');\n console.log(`${label}:`, d.message);\n }\n if (!validation.ok || !validation.manifest?.id) {\n console.error(colors.red('error:'), 'Package is not publishable as an independent extension.');\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('update')\n .description('Re-install extension(s) from the lockfile (npm or xopc-store) under ~/.xopc/extensions')\n .argument('[extensionId]', 'Specific extension id (default: all in lockfile)')\n .action(async (extensionId: string | undefined) => {\n const ctx = getContextWithOpts();\n const cfg = loadConfig(ctx.configPath);\n const targetDir = resolveExtensionsDir();\n const storeBase = resolveExtensionsStoreBaseUrl(cfg);\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 === 'store') {\n const pkgName = entry.resolved?.trim() || id;\n console.log(colors.cyan('Updating'), id, '←', `store:${pkgName}`);\n if (existsSync(join(targetDir, id))) {\n rmSync(join(targetDir, id), { recursive: true, force: true });\n }\n const r = await installExtensionFromStoreWithLock({\n storeBase,\n packageName: pkgName,\n targetDir,\n lock,\n yes: true,\n });\n if (r.ok === false) {\n console.error(colors.red('error:'), r.error ?? id);\n process.exit(1);\n }\n console.log(colors.green('✓'), id);\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 if (existsSync(join(targetDir, id))) {\n rmSync(join(targetDir, id), { recursive: true, force: true });\n }\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 await lock.upsert(id, {\n name: id,\n version: entry.version,\n resolved: spec,\n source: 'npm',\n ...readInstalledSnapshots(targetDir, id),\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":"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"}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import type { ExtensionManifest } from '../../extensions/types/index.js';
|
|
3
|
+
export interface PackDiagnostic {
|
|
4
|
+
level: 'error' | 'warning' | 'info';
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ExtensionPackageValidationResult {
|
|
8
|
+
extensionDir: string;
|
|
9
|
+
manifest: ExtensionManifest | null;
|
|
10
|
+
packageJson: Record<string, unknown> | null;
|
|
11
|
+
diagnostics: PackDiagnostic[];
|
|
12
|
+
ok: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function validateExtensionPackageDirectory(dir: string): ExtensionPackageValidationResult;
|
|
2
15
|
export declare function createExtensionPackCommand(): Command;
|
|
@@ -3,10 +3,13 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
3
3
|
import { init_logger } from "../../utils/logger.js";
|
|
4
4
|
import { init_normalize_manifest, normalizeExtensionManifest } from "../../extensions/normalize-manifest.js";
|
|
5
5
|
import { checkEngineCompatibility } from "../../extensions/engine-check.js";
|
|
6
|
+
import { collectExtensionPackageDependencyIssues } from "../../extensions/package-contract.js";
|
|
6
7
|
import { colors } from "../utils/colors.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { basename, join, relative, resolve } from "node:path";
|
|
9
11
|
import { execSync } from "node:child_process";
|
|
12
|
+
import AdmZip from "adm-zip";
|
|
10
13
|
import { Command } from "commander";
|
|
11
14
|
//#region src/cli/commands/extension-pack.ts
|
|
12
15
|
init_normalize_manifest();
|
|
@@ -62,18 +65,8 @@ function collectContributionPaths(manifest, extRoot) {
|
|
|
62
65
|
return out;
|
|
63
66
|
}
|
|
64
67
|
function resolveMainFile(root, main) {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
"index.ts",
|
|
68
|
-
"index.js",
|
|
69
|
-
"extension.ts",
|
|
70
|
-
"extension.js"
|
|
71
|
-
].filter((x) => typeof x === "string" && x.length > 0);
|
|
72
|
-
for (const c of cands) {
|
|
73
|
-
const p = join(root, c);
|
|
74
|
-
if (existsSync(p)) return p;
|
|
75
|
-
}
|
|
76
|
-
return null;
|
|
68
|
+
const p = join(root, main);
|
|
69
|
+
return existsSync(p) ? p : null;
|
|
77
70
|
}
|
|
78
71
|
function validateManifest(ctx) {
|
|
79
72
|
const { manifest, extensionDir, diagnostics } = ctx;
|
|
@@ -81,9 +74,13 @@ function validateManifest(ctx) {
|
|
|
81
74
|
level: "error",
|
|
82
75
|
message: "Manifest \"id\" is required"
|
|
83
76
|
});
|
|
84
|
-
if (!
|
|
77
|
+
if (!manifest.main) diagnostics.push({
|
|
78
|
+
level: "error",
|
|
79
|
+
message: "Manifest \"main\" is required and must point at built JavaScript"
|
|
80
|
+
});
|
|
81
|
+
if (!(manifest.main ? resolveMainFile(extensionDir, manifest.main) : null)) diagnostics.push({
|
|
85
82
|
level: "error",
|
|
86
|
-
message: `Main entry not found
|
|
83
|
+
message: `Main entry not found: ${manifest.main ?? "(missing)"}`
|
|
87
84
|
});
|
|
88
85
|
if (manifest.ui?.main) {
|
|
89
86
|
if (!existsSync(join(extensionDir, manifest.ui.main))) diagnostics.push({
|
|
@@ -95,32 +92,37 @@ function validateManifest(ctx) {
|
|
|
95
92
|
level: "error",
|
|
96
93
|
message: `UI contribution entry missing: ${p}`
|
|
97
94
|
});
|
|
98
|
-
if (manifest.
|
|
95
|
+
if (manifest.main && !/\.(mjs|cjs|js)$/i.test(manifest.main)) diagnostics.push({
|
|
96
|
+
level: "error",
|
|
97
|
+
message: `Strict package contract requires manifest.main to point at built JavaScript, got "${manifest.main}"`
|
|
98
|
+
});
|
|
99
|
+
if (!manifest.engines?.xopc) diagnostics.push({
|
|
100
|
+
level: "error",
|
|
101
|
+
message: "manifest engines.xopc is required for independent extension packages"
|
|
102
|
+
});
|
|
103
|
+
else {
|
|
99
104
|
const r = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);
|
|
100
105
|
if (r.parseWarning) diagnostics.push({
|
|
101
|
-
level: "
|
|
102
|
-
message: `engines.xopc parse issue — ${r.reason ?? "unknown"}
|
|
106
|
+
level: "error",
|
|
107
|
+
message: `engines.xopc parse issue — ${r.reason ?? "unknown"}`
|
|
103
108
|
});
|
|
104
109
|
else if (!r.compatible) diagnostics.push({
|
|
105
|
-
level: "
|
|
110
|
+
level: "error",
|
|
106
111
|
message: `engines.xopc not satisfied by current xopc ${PACKAGE_VERSION}: ${r.reason ?? manifest.engines.xopc}`
|
|
107
112
|
});
|
|
108
113
|
}
|
|
109
114
|
}
|
|
110
115
|
function validatePackageJson(ctx) {
|
|
111
116
|
const { packageJson, diagnostics, extensionDir } = ctx;
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
message: `dependency "${name}": ${v} — will be replaced when packing from a pnpm workspace`
|
|
117
|
-
});
|
|
118
|
-
}
|
|
117
|
+
for (const issue of collectExtensionPackageDependencyIssues(packageJson, { strictRuntimeSdkDeps: true })) diagnostics.push({
|
|
118
|
+
level: "error",
|
|
119
|
+
message: issue.message
|
|
120
|
+
});
|
|
119
121
|
const files = packageJson.files;
|
|
120
122
|
if (Array.isArray(files)) {
|
|
121
123
|
if (!files.some((f) => f === MANIFEST || f === "**/xopc.extension.json")) diagnostics.push({
|
|
122
|
-
level: "
|
|
123
|
-
message: `package.json "files"
|
|
124
|
+
level: "error",
|
|
125
|
+
message: `package.json "files" must include "${MANIFEST}" so the archive ships the manifest`
|
|
124
126
|
});
|
|
125
127
|
}
|
|
126
128
|
const keywords = packageJson.keywords;
|
|
@@ -137,14 +139,123 @@ function validatePackageJson(ctx) {
|
|
|
137
139
|
message: "package.json is missing"
|
|
138
140
|
});
|
|
139
141
|
}
|
|
140
|
-
|
|
142
|
+
const SECRET_FILE_RE = /(^|\/)(\.env(?:\..*)?|\.npmrc|\.yarnrc|id_rsa|id_ed25519|.*\.(?:pem|key|p12|pfx))$/i;
|
|
143
|
+
const SECRET_TEXT_RE = /(sk-[A-Za-z0-9_-]{20,}|xox[baprs]-[A-Za-z0-9-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN (?:RSA |OPENSSH |EC |DSA )?PRIVATE KEY-----)/;
|
|
144
|
+
function scanUnsafeFiles(root, diagnostics) {
|
|
145
|
+
const walk = (dir) => {
|
|
146
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
147
|
+
const full = join(dir, entry.name);
|
|
148
|
+
const rel = relative(root, full).replace(/\\/g, "/");
|
|
149
|
+
if (shouldExcludeFromArtifact(rel)) continue;
|
|
150
|
+
if (SECRET_FILE_RE.test(rel)) {
|
|
151
|
+
diagnostics.push({
|
|
152
|
+
level: "error",
|
|
153
|
+
message: `Unsafe secret-like file would be packaged: ${rel}`
|
|
154
|
+
});
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (entry.isDirectory()) walk(full);
|
|
158
|
+
else if (entry.isFile()) {
|
|
159
|
+
if (statSync(full).size <= 1024 * 1024 && /\.(?:js|mjs|cjs|json|html|css|md|txt|map)$/i.test(entry.name)) {
|
|
160
|
+
const text = readFileSync(full, "utf-8");
|
|
161
|
+
if (SECRET_TEXT_RE.test(text)) diagnostics.push({
|
|
162
|
+
level: "error",
|
|
163
|
+
message: `Potential secret token found in packaged file: ${rel}`
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
walk(root);
|
|
170
|
+
}
|
|
171
|
+
function validateExtensionPackageDirectory(dir) {
|
|
172
|
+
const extensionDir = resolve(dir || ".");
|
|
173
|
+
const diagnostics = [];
|
|
174
|
+
if (!existsSync(extensionDir) || !existsSync(join(extensionDir, "package.json"))) {
|
|
175
|
+
diagnostics.push({
|
|
176
|
+
level: "error",
|
|
177
|
+
message: `Not an extension project (no package.json): ${extensionDir}`
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
extensionDir,
|
|
181
|
+
manifest: null,
|
|
182
|
+
packageJson: null,
|
|
183
|
+
diagnostics,
|
|
184
|
+
ok: false
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const manifest = loadManifestAtRoot(extensionDir, diagnostics);
|
|
188
|
+
let packageJson = null;
|
|
141
189
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
} catch {
|
|
145
|
-
|
|
190
|
+
packageJson = loadJson(join(extensionDir, "package.json"));
|
|
191
|
+
if (!isRecord(packageJson)) throw new Error("package.json must be an object");
|
|
192
|
+
} catch (e) {
|
|
193
|
+
diagnostics.push({
|
|
194
|
+
level: "error",
|
|
195
|
+
message: e instanceof Error ? e.message : String(e)
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (manifest && packageJson) {
|
|
199
|
+
const ctx = {
|
|
200
|
+
extensionDir,
|
|
201
|
+
manifest,
|
|
202
|
+
packageJson,
|
|
203
|
+
diagnostics
|
|
204
|
+
};
|
|
205
|
+
validateManifest(ctx);
|
|
206
|
+
validatePackageJson(ctx);
|
|
207
|
+
scanUnsafeFiles(extensionDir, diagnostics);
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
extensionDir,
|
|
211
|
+
manifest,
|
|
212
|
+
packageJson,
|
|
213
|
+
diagnostics,
|
|
214
|
+
ok: !diagnostics.some((d) => d.level === "error")
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function shouldExcludeFromArtifact(rel) {
|
|
218
|
+
const parts = rel.split(/[\\/]+/);
|
|
219
|
+
if (parts.some((p) => p === "node_modules" || p === ".git" || p === ".turbo" || p === ".cache")) return true;
|
|
220
|
+
const name = parts.at(-1) ?? rel;
|
|
221
|
+
if (name === ".DS_Store") return true;
|
|
222
|
+
if (name.endsWith(".tgz") || name.endsWith(".zip") || name.endsWith(".sha256") || name.endsWith(".manifest.json")) return true;
|
|
223
|
+
if (name.endsWith(".tsbuildinfo")) return true;
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
function addDirectoryToZip(zip, root, dir) {
|
|
227
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
228
|
+
const full = join(dir, entry.name);
|
|
229
|
+
const rel = relative(root, full).replace(/\\/g, "/");
|
|
230
|
+
if (shouldExcludeFromArtifact(rel)) continue;
|
|
231
|
+
if (entry.isDirectory()) addDirectoryToZip(zip, root, full);
|
|
232
|
+
else if (entry.isFile()) zip.addFile(rel, readFileSync(full));
|
|
146
233
|
}
|
|
147
234
|
}
|
|
235
|
+
function writeStoreReadyArtifact(params) {
|
|
236
|
+
mkdirSync(params.outDir, { recursive: true });
|
|
237
|
+
const name = String(params.packageJson.name ?? params.manifest.id).replace(/^@/, "").replace(/[\\/]+/g, "-").replace(/[^A-Za-z0-9._-]+/g, "-");
|
|
238
|
+
const version = String(params.manifest.version ?? params.packageJson.version ?? "0.0.0");
|
|
239
|
+
const base = `${name}-${version}`;
|
|
240
|
+
const zipPath = join(params.outDir, `${base}.zip`);
|
|
241
|
+
const zip = new AdmZip();
|
|
242
|
+
addDirectoryToZip(zip, params.extensionDir, params.extensionDir);
|
|
243
|
+
zip.writeZip(zipPath);
|
|
244
|
+
const buffer = readFileSync(zipPath);
|
|
245
|
+
const sha256Hex = createHash("sha256").update(buffer).digest("hex");
|
|
246
|
+
const integrity = `sha256-${createHash("sha256").update(buffer).digest("base64")}`;
|
|
247
|
+
writeFileSync(join(params.outDir, `${base}.sha256`), `${sha256Hex} ${basename(zipPath)}\n`);
|
|
248
|
+
writeFileSync(join(params.outDir, `${base}.manifest.json`), JSON.stringify({
|
|
249
|
+
id: params.manifest.id,
|
|
250
|
+
name: params.manifest.name,
|
|
251
|
+
version,
|
|
252
|
+
artifact: basename(zipPath),
|
|
253
|
+
integrity,
|
|
254
|
+
manifest: params.manifest,
|
|
255
|
+
packageJson: params.packageJson
|
|
256
|
+
}, null, 2));
|
|
257
|
+
return zipPath;
|
|
258
|
+
}
|
|
148
259
|
function printDiagnostics(d) {
|
|
149
260
|
for (const x of d) if (x.level === "error") console.error(`${colors.red("error")}:`, x.message);
|
|
150
261
|
else if (x.level === "warning") console.log(`${colors.yellow("warning")}:`, x.message);
|
|
@@ -152,37 +263,11 @@ function printDiagnostics(d) {
|
|
|
152
263
|
}
|
|
153
264
|
function createExtensionPackCommand() {
|
|
154
265
|
return new Command("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) => {
|
|
155
|
-
const
|
|
266
|
+
const validation = validateExtensionPackageDirectory(dir || ".");
|
|
267
|
+
const { extensionDir, manifest, packageJson, diagnostics } = validation;
|
|
156
268
|
const outDir = opts.out && opts.out.length > 0 ? resolve(opts.out) : extensionDir;
|
|
157
|
-
const diagnostics = [];
|
|
158
|
-
if (!existsSync(extensionDir) || !existsSync(join(extensionDir, "package.json"))) {
|
|
159
|
-
console.error(colors.red("error:"), `Not an extension project (no package.json): ${extensionDir}`);
|
|
160
|
-
process.exit(1);
|
|
161
|
-
}
|
|
162
|
-
const manifest = loadManifestAtRoot(extensionDir, diagnostics);
|
|
163
|
-
if (!manifest) {
|
|
164
|
-
printDiagnostics(diagnostics);
|
|
165
|
-
process.exit(1);
|
|
166
|
-
}
|
|
167
|
-
let packageJson;
|
|
168
|
-
try {
|
|
169
|
-
packageJson = loadJson(join(extensionDir, "package.json"));
|
|
170
|
-
if (!isRecord(packageJson)) throw new Error("package.json must be an object");
|
|
171
|
-
} catch (e) {
|
|
172
|
-
log.error({ err: e }, "Failed to read package.json");
|
|
173
|
-
console.error(colors.red("error:"), e instanceof Error ? e.message : String(e));
|
|
174
|
-
process.exit(1);
|
|
175
|
-
}
|
|
176
|
-
const ctx = {
|
|
177
|
-
extensionDir,
|
|
178
|
-
manifest,
|
|
179
|
-
packageJson,
|
|
180
|
-
diagnostics
|
|
181
|
-
};
|
|
182
|
-
validateManifest(ctx);
|
|
183
|
-
validatePackageJson(ctx);
|
|
184
269
|
printDiagnostics(diagnostics);
|
|
185
|
-
if (
|
|
270
|
+
if (!validation.ok || !manifest || !packageJson) {
|
|
186
271
|
console.error(colors.red("Pack validation failed (fix errors above)."));
|
|
187
272
|
process.exit(1);
|
|
188
273
|
}
|
|
@@ -201,43 +286,26 @@ function createExtensionPackCommand() {
|
|
|
201
286
|
console.error(colors.red("error:"), `UI build failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
202
287
|
process.exit(1);
|
|
203
288
|
}
|
|
204
|
-
let
|
|
289
|
+
let artifactPath;
|
|
205
290
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
else tarball = "";
|
|
213
|
-
if (!tarball) {
|
|
214
|
-
const tgzs = readdirSync(extensionDir).filter((f) => f.endsWith(".tgz"));
|
|
215
|
-
tgzs.sort((a, b) => statSync(join(extensionDir, b)).mtimeMs - statSync(join(extensionDir, a)).mtimeMs);
|
|
216
|
-
const last = tgzs[0];
|
|
217
|
-
tarball = last ? join(extensionDir, last) : "";
|
|
218
|
-
}
|
|
219
|
-
if (!tarball || !existsSync(tarball)) throw new Error("Could not locate .tgz after pack; check pnpm/npm output");
|
|
291
|
+
artifactPath = writeStoreReadyArtifact({
|
|
292
|
+
extensionDir,
|
|
293
|
+
outDir,
|
|
294
|
+
manifest,
|
|
295
|
+
packageJson
|
|
296
|
+
});
|
|
220
297
|
} catch (e) {
|
|
221
298
|
log.error({ err: e }, "pack failed");
|
|
222
299
|
console.error(colors.red("error:"), e instanceof Error ? e.message : String(e));
|
|
223
300
|
process.exit(1);
|
|
224
301
|
}
|
|
225
|
-
if (outDir !== extensionDir) try {
|
|
226
|
-
mkdirSync(outDir, { recursive: true });
|
|
227
|
-
const dest = join(outDir, tarball.includes("/") ? tarball.slice(tarball.lastIndexOf("/") + 1) : tarball);
|
|
228
|
-
renameSync(tarball, dest);
|
|
229
|
-
tarball = dest;
|
|
230
|
-
} catch (e) {
|
|
231
|
-
console.error(colors.red("error:"), `Failed to move archive to --out: ${e instanceof Error ? e.message : String(e)}`);
|
|
232
|
-
process.exit(1);
|
|
233
|
-
}
|
|
234
|
-
const displayPath = tarball;
|
|
235
302
|
console.log("");
|
|
236
|
-
console.log(colors.green("Pack complete:"),
|
|
237
|
-
console.log(colors.cyan("
|
|
303
|
+
console.log(colors.green("Pack complete:"), artifactPath);
|
|
304
|
+
console.log(colors.cyan("Generated:"), ".zip artifact, .sha256 checksum, .manifest.json metadata");
|
|
305
|
+
console.log(colors.cyan("Next:"), "upload the generated artifact set to store.xopc.ai or install the zip via the store pipeline.");
|
|
238
306
|
});
|
|
239
307
|
}
|
|
240
308
|
//#endregion
|
|
241
|
-
export { createExtensionPackCommand };
|
|
309
|
+
export { createExtensionPackCommand, validateExtensionPackageDirectory };
|
|
242
310
|
|
|
243
311
|
//# sourceMappingURL=extension-pack.js.map
|
|
@@ -1 +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('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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"}
|
|
1
|
+
{"version":3,"file":"extension-pack.js","names":[],"sources":["../../../../src/cli/commands/extension-pack.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { execSync } from 'node:child_process';\nimport { existsSync, readFileSync, readdirSync, mkdirSync, statSync, writeFileSync } from 'node:fs';\nimport { basename, join, relative, resolve } from 'node:path';\n\nimport AdmZip from 'adm-zip';\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 { collectExtensionPackageDependencyIssues } from '../../extensions/package-contract.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\nexport interface PackDiagnostic {\n level: 'error' | 'warning' | 'info';\n message: string;\n}\n\nexport interface ExtensionPackageValidationResult {\n extensionDir: string;\n manifest: ExtensionManifest | null;\n packageJson: Record<string, unknown> | null;\n diagnostics: PackDiagnostic[];\n ok: boolean;\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 p = join(root, main);\n return existsSync(p) ? p : 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 if (!manifest.main) {\n diagnostics.push({ level: 'error', message: 'Manifest \"main\" is required and must point at built JavaScript' });\n }\n const mainFile = manifest.main ? resolveMainFile(extensionDir, manifest.main) : null;\n if (!mainFile) {\n diagnostics.push({\n level: 'error',\n message: `Main entry not found: ${manifest.main ?? '(missing)'}`,\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.main && !/\\.(mjs|cjs|js)$/i.test(manifest.main)) {\n diagnostics.push({\n level: 'error',\n message: `Strict package contract requires manifest.main to point at built JavaScript, got \"${manifest.main}\"`,\n });\n }\n\n if (!manifest.engines?.xopc) {\n diagnostics.push({\n level: 'error',\n message: 'manifest engines.xopc is required for independent extension packages',\n });\n } else {\n const r = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);\n if (r.parseWarning) {\n diagnostics.push({\n level: 'error',\n message: `engines.xopc parse issue — ${r.reason ?? 'unknown'}`,\n });\n } else if (!r.compatible) {\n diagnostics.push({\n level: 'error',\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 for (const issue of collectExtensionPackageDependencyIssues(packageJson, {\n strictRuntimeSdkDeps: true,\n })) {\n diagnostics.push({\n level: 'error',\n message: issue.message,\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: 'error',\n message: `package.json \"files\" must 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\nconst SECRET_FILE_RE = /(^|\\/)(\\.env(?:\\..*)?|\\.npmrc|\\.yarnrc|id_rsa|id_ed25519|.*\\.(?:pem|key|p12|pfx))$/i;\nconst SECRET_TEXT_RE = /(sk-[A-Za-z0-9_-]{20,}|xox[baprs]-[A-Za-z0-9-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN (?:RSA |OPENSSH |EC |DSA )?PRIVATE KEY-----)/;\n\nfunction scanUnsafeFiles(root: string, diagnostics: PackDiagnostic[]): void {\n const walk = (dir: string) => {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n const rel = relative(root, full).replace(/\\\\/g, '/');\n if (shouldExcludeFromArtifact(rel)) continue;\n if (SECRET_FILE_RE.test(rel)) {\n diagnostics.push({ level: 'error', message: `Unsafe secret-like file would be packaged: ${rel}` });\n continue;\n }\n if (entry.isDirectory()) {\n walk(full);\n } else if (entry.isFile()) {\n const size = statSync(full).size;\n if (size <= 1024 * 1024 && /\\.(?:js|mjs|cjs|json|html|css|md|txt|map)$/i.test(entry.name)) {\n const text = readFileSync(full, 'utf-8');\n if (SECRET_TEXT_RE.test(text)) {\n diagnostics.push({ level: 'error', message: `Potential secret token found in packaged file: ${rel}` });\n }\n }\n }\n }\n };\n walk(root);\n}\n\nexport function validateExtensionPackageDirectory(dir: string): ExtensionPackageValidationResult {\n const extensionDir = resolve(dir || '.');\n const diagnostics: PackDiagnostic[] = [];\n if (!existsSync(extensionDir) || !existsSync(join(extensionDir, 'package.json'))) {\n diagnostics.push({ level: 'error', message: `Not an extension project (no package.json): ${extensionDir}` });\n return { extensionDir, manifest: null, packageJson: null, diagnostics, ok: false };\n }\n const manifest = loadManifestAtRoot(extensionDir, diagnostics);\n let packageJson: Record<string, unknown> | null = null;\n try {\n packageJson = loadJson(join(extensionDir, 'package.json')) as Record<string, unknown>;\n if (!isRecord(packageJson)) throw new Error('package.json must be an object');\n } catch (e) {\n diagnostics.push({ level: 'error', message: e instanceof Error ? e.message : String(e) });\n }\n if (manifest && packageJson) {\n const ctx: PackContext = { extensionDir, manifest, packageJson, diagnostics };\n validateManifest(ctx);\n validatePackageJson(ctx);\n scanUnsafeFiles(extensionDir, diagnostics);\n }\n return {\n extensionDir,\n manifest,\n packageJson,\n diagnostics,\n ok: !diagnostics.some((d) => d.level === 'error'),\n };\n}\n\nfunction shouldExcludeFromArtifact(rel: string): boolean {\n const parts = rel.split(/[\\\\/]+/);\n if (parts.some((p) => p === 'node_modules' || p === '.git' || p === '.turbo' || p === '.cache')) return true;\n const name = parts.at(-1) ?? rel;\n if (name === '.DS_Store') return true;\n if (name.endsWith('.tgz') || name.endsWith('.zip') || name.endsWith('.sha256') || name.endsWith('.manifest.json')) return true;\n if (name.endsWith('.tsbuildinfo')) return true;\n return false;\n}\n\nfunction addDirectoryToZip(zip: AdmZip, root: string, dir: string): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n const rel = relative(root, full).replace(/\\\\/g, '/');\n if (shouldExcludeFromArtifact(rel)) continue;\n if (entry.isDirectory()) {\n addDirectoryToZip(zip, root, full);\n } else if (entry.isFile()) {\n zip.addFile(rel, readFileSync(full));\n }\n }\n}\n\nfunction writeStoreReadyArtifact(params: {\n extensionDir: string;\n outDir: string;\n manifest: ExtensionManifest;\n packageJson: Record<string, unknown>;\n}): string {\n mkdirSync(params.outDir, { recursive: true });\n const name = String(params.packageJson.name ?? params.manifest.id)\n .replace(/^@/, '')\n .replace(/[\\\\/]+/g, '-')\n .replace(/[^A-Za-z0-9._-]+/g, '-');\n const version = String(params.manifest.version ?? params.packageJson.version ?? '0.0.0');\n const base = `${name}-${version}`;\n const zipPath = join(params.outDir, `${base}.zip`);\n const zip = new AdmZip();\n addDirectoryToZip(zip, params.extensionDir, params.extensionDir);\n zip.writeZip(zipPath);\n\n const buffer = readFileSync(zipPath);\n const sha256Hex = createHash('sha256').update(buffer).digest('hex');\n const integrity = `sha256-${createHash('sha256').update(buffer).digest('base64')}`;\n writeFileSync(join(params.outDir, `${base}.sha256`), `${sha256Hex} ${basename(zipPath)}\\n`);\n writeFileSync(\n join(params.outDir, `${base}.manifest.json`),\n JSON.stringify(\n {\n id: params.manifest.id,\n name: params.manifest.name,\n version,\n artifact: basename(zipPath),\n integrity,\n manifest: params.manifest,\n packageJson: params.packageJson,\n },\n null,\n 2,\n ),\n );\n return zipPath;\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('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 validation = validateExtensionPackageDirectory(dir || '.');\n const { extensionDir, manifest, packageJson, diagnostics } = validation;\n const outDir = opts.out && opts.out.length > 0 ? resolve(opts.out) : extensionDir;\n printDiagnostics(diagnostics);\n\n if (!validation.ok || !manifest || !packageJson) {\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 artifactPath: string;\n try {\n artifactPath = writeStoreReadyArtifact({ extensionDir, outDir, manifest, packageJson });\n } catch (e) {\n log.error({ err: e }, 'pack failed');\n console.error(colors.red('error:'), e instanceof Error ? e.message : String(e));\n process.exit(1);\n }\n\n console.log('');\n console.log(colors.green('Pack complete:'), artifactPath);\n console.log(colors.cyan('Generated:'), '.zip artifact, .sha256 checksum, .manifest.json metadata');\n console.log(colors.cyan('Next:'), 'upload the generated artifact set to store.xopc.ai or install the zip via the store pipeline.');\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
export declare function createExtensionListCommand(): Command;
|
|
3
|
+
export declare function createExtensionInspectCommand(): Command;
|
|
3
4
|
export declare function createExtensionFreezeCommand(): Command;
|
|
4
5
|
export declare function createExtensionHealthCommand(): Command;
|
|
5
6
|
export declare function createExtensionVerifyCommand(): Command;
|
|
7
|
+
export declare function createExtensionDoctorCommand(): Command;
|
|
6
8
|
export declare function createExtensionAuditCommand(): Command;
|
|
7
9
|
export declare function registerExtensionCommands(program: Command): void;
|