@ai-agent-forge/agent-forge 0.85.8 → 0.85.10
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/CHANGELOG.md +12 -0
- package/dist/bundle/.build-manifest.json +7 -7
- package/dist/bundle/chunks/{chunk-BTBDSCF4.js → chunk-UO4LZHZN.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/plugin-command.d.ts +3 -1
- package/dist/cli/plugin-command.d.ts.map +1 -1
- package/dist/cli/plugin-command.js +14 -2
- package/dist/cli/plugin-command.js.map +1 -1
- package/dist/plugins/ecosystem/bootstrap-factory-manifest.d.ts.map +1 -1
- package/dist/plugins/ecosystem/bootstrap-factory-manifest.js +6 -0
- package/dist/plugins/ecosystem/bootstrap-factory-manifest.js.map +1 -1
- package/dist/profile/plugin-profiles.d.ts +1 -1
- package/dist/profile/plugin-profiles.d.ts.map +1 -1
- package/dist/profile/plugin-profiles.js +1 -0
- package/dist/profile/plugin-profiles.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-command.d.ts","sourceRoot":"","sources":["../../src/cli/plugin-command.ts"],"names":[],"mappings":"AAOA,OAAO,EAIN,KAAK,oBAAoB,EAGzB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAGhF,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE;QACf,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACjF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;KACzC,CAAC;IACF,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,CAAC,EAAE,oBAAoB,CAAC;IAC7C,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC,qFAAqF;IACrF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACjD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAiDD;;;;GAIG;AACH,wBAAsB,sCAAsC,CAAC,OAAO,EAAE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;CACrC,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAWnG;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CACjD,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,sBAA2B,GAClC,OAAO,CAAC,OAAO,CAAC,CAyBlB","sourcesContent":["import { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { defaultPluginHostFactsV1, projectPluginScopeRefV1 } from \"../plugins/ecosystem/default-active-bindings.ts\";\nimport {\n\tcreateDefaultPluginMarketWiringV1,\n\ttype DefaultPluginMarketWiringV1,\n} from \"../plugins/ecosystem/default-plugin-market.ts\";\nimport {\n\tcreatePluginEcosystemCliV1,\n\tcreatePluginSelectionStoreV1,\n\tcreatePluginStateStoreV1,\n\ttype PluginDistributionV1,\n\ttype PluginEcosystemCliResponseV1,\n\ttype PluginEcosystemCliV1,\n\ttype PluginEcosystemRegistryV1,\n\ttype PluginInstallerV1,\n\ttype PluginSelectionStoreV1,\n\ttype PluginStateStoreV1,\n} from \"../plugins/ecosystem/index.ts\";\nimport { listBuiltinPluginManifestsV1 } from \"../profile/plugin-profiles.ts\";\nimport type { PluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\nimport { createPluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\n\nexport interface PluginCommandOptionsV1 {\n\treadonly agentDir?: string;\n\t/** Working directory used for the project-local selection store. */\n\treadonly cwd?: string;\n\treadonly host?: {\n\t\treadonly os: string;\n\t\treadonly arch: string;\n\t\treadonly runtime: readonly { readonly name: string; readonly version: string }[];\n\t\treadonly apiVersion: string;\n\t\treadonly hostFeatures: readonly string[];\n\t};\n\t/** Optional host-owned boundaries used by install/update/remove commands. */\n\treadonly registry?: PluginEcosystemRegistryV1;\n\treadonly installer?: PluginInstallerV1;\n\t/** Optional host-owned package download boundary used by install/update. */\n\treadonly distribution?: PluginDistributionV1;\n\t/** Override persistence in tests or an embedding host; defaults remain agentDir files. */\n\treadonly stateStore?: PluginStateStoreV1;\n\t/** Override the project-local persistence boundary in tests or an embedding host. */\n\treadonly projectStateStore?: PluginStateStoreV1;\n\treadonly selectionStore?: PluginSelectionStoreV1;\n\treadonly projectSelectionStore?: PluginSelectionStoreV1;\n\treadonly write?: (line: string) => void;\n}\n\nfunction printResponse(response: PluginEcosystemCliResponseV1, write: (line: string) => void): void {\n\twrite(response.text);\n\tif (response.status !== \"succeeded\") process.exitCode = 1;\n}\n\ninterface MarketCliOptionsV1 {\n\treadonly agentDir: string;\n\treadonly cwd: string;\n\treadonly market?: DefaultPluginMarketWiringV1;\n\treadonly overrides?: PluginCommandOptionsV1;\n}\n\nfunction buildMarketCli(options: MarketCliOptionsV1): PluginEcosystemCliV1 {\n\tconst { market, overrides } = options;\n\treturn createPluginEcosystemCliV1({\n\t\thost: overrides?.host ?? defaultPluginHostFactsV1(),\n\t\tmanifests: listBuiltinPluginManifestsV1(),\n\t\tregistry: overrides?.registry ?? market?.cliRegistry,\n\t\t// Multi-source acquisition (`plugin install <ref>`) rides along with the\n\t\t// default market wiring; a fully host-injected stack replaces it wholesale.\n\t\t...(market?.acquisition === undefined ? {} : { acquisition: market.acquisition }),\n\t\tinstaller: overrides?.installer ?? market?.installer,\n\t\t...(overrides?.distribution !== undefined || market?.distribution !== undefined\n\t\t\t? { distribution: overrides?.distribution ?? market!.distribution }\n\t\t\t: {}),\n\t\tstateStore:\n\t\t\toverrides?.stateStore ??\n\t\t\tmarket?.stateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.agentDir, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectStateStore:\n\t\t\toverrides?.projectStateStore ??\n\t\t\tmarket?.projectStateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.cwd, CONFIG_DIR_NAME, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectScopeRef: projectPluginScopeRefV1(options.cwd),\n\t\tselectionStore:\n\t\t\toverrides?.selectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.agentDir, \".plugin-selection.json\") }),\n\t\tprojectSelectionStore:\n\t\t\toverrides?.projectSelectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.cwd, CONFIG_DIR_NAME, \".plugin-selection.json\") }),\n\t});\n}\n\n/**\n * Default TUI manager controller over the default marketplace wiring. The\n * controller reads the global or project state store per scope; callers must\n * invoke `close` after the config screen closes.\n */\nexport async function createDefaultPluginManagerControllerV1(options: {\n\treadonly agentDir?: string;\n\treadonly cwd?: string;\n\treadonly scope: \"global\" | \"project\";\n}): Promise<{ readonly controller: PluginManagerControllerV1; readonly close: () => Promise<void> }> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market = await createDefaultPluginMarketWiringV1({ agentDir, cwd });\n\tconst cli = buildMarketCli({ agentDir, cwd, market });\n\tconst controller = createPluginManagerControllerV1({\n\t\tregistry: market.registry,\n\t\tstateStore: options.scope === \"project\" ? market.projectStateStore : market.stateStore,\n\t\tcli,\n\t});\n\treturn { controller, close: market.close };\n}\n\n/**\n * Handle the independent ecosystem command namespace before legacy package\n * commands. Install/update/remove default to the disk install store plus an\n * optional configured marketplace origin; host injection of registry and\n * installer still wins entirely.\n */\nexport async function handlePluginEcosystemCommand(\n\targs: readonly string[],\n\toptions: PluginCommandOptionsV1 = {},\n): Promise<boolean> {\n\tif (args[0] !== \"plugin\") return false;\n\tconst write = options.write ?? ((line: string) => console.log(line));\n\t// Batch update convenience (0.85.7 user seat finding: a factory range bump\n\t// left seven plugins outdated and the per-plugin hint meant seven manual\n\t// commands). The ecosystem CLI protocol is unchanged — this outer layer\n\t// composes `state list` + one `update` per active plugin.\n\tif (args[1] === \"update\" && args[2] === \"--all\") {\n\t\tawait runBatchUpdate(args.slice(3), options, write);\n\t\treturn true;\n\t}\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst response = await cli.execute({ argv: args.slice(1) });\n\t\tprintResponse(response, write);\n\t\treturn true;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n\ninterface BatchUpdateEntry {\n\treadonly pluginId: string;\n\treadonly scope: string;\n\treadonly lifecycle: string;\n}\n\nasync function runBatchUpdate(\n\trestArgs: readonly string[],\n\toptions: PluginCommandOptionsV1,\n\twrite: (line: string) => void,\n): Promise<void> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst scopeIndex = restArgs.indexOf(\"--scope\");\n\tconst scope = scopeIndex !== -1 && restArgs[scopeIndex + 1] === \"project\" ? \"project\" : \"global\";\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst listResponse = await cli.execute({ argv: [\"state\", \"list\", \"--scope\", scope] });\n\t\tif (listResponse.status !== \"succeeded\") {\n\t\t\tprintResponse(listResponse, write);\n\t\t\treturn;\n\t\t}\n\t\tconst entries = ((listResponse.data?.entries ?? []) as readonly BatchUpdateEntry[]).filter(\n\t\t\t(entry) => entry.lifecycle === \"active\" && entry.scope === scope,\n\t\t);\n\t\tif (entries.length === 0) {\n\t\t\twrite(\"No active plugins to update.\");\n\t\t\treturn;\n\t\t}\n\t\tconst updated: string[] = [];\n\t\tconst current: string[] = [];\n\t\tconst failed: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\tconst response = await cli.execute({ argv: [\"update\", entry.pluginId, \"--scope\", scope] });\n\t\t\tif (response.status === \"succeeded\") {\n\t\t\t\tupdated.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t} else if (response.error?.code === \"already_installed\") {\n\t\t\t\tcurrent.push(entry.pluginId);\n\t\t\t} else {\n\t\t\t\tfailed.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t}\n\t\t}\n\t\tconst summary = [\n\t\t\t`updated ${updated.length}${updated.length > 0 ? ` (${updated.join(\", \")})` : \"\"}`,\n\t\t\t`already up to date ${current.length}${current.length > 0 ? ` (${current.join(\", \")})` : \"\"}`,\n\t\t\t`failed ${failed.length}${failed.length > 0 ? ` (${failed.join(\", \")})` : \"\"}`,\n\t\t].join(\"; \");\n\t\twrite(`plugin update --all [${scope}]: ${summary}`);\n\t\tif (failed.length > 0) process.exitCode = 1;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plugin-command.d.ts","sourceRoot":"","sources":["../../src/cli/plugin-command.ts"],"names":[],"mappings":"AAQA,OAAO,EAIN,KAAK,oBAAoB,EACzB,KAAK,+BAA+B,EAGpC,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAGhF,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE;QACf,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACjF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;KACzC,CAAC;IACF,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IACvC,kFAAkF;IAClF,QAAQ,CAAC,WAAW,CAAC,EAAE,+BAA+B,CAAC;IACvD,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,CAAC,EAAE,oBAAoB,CAAC;IAC7C,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC,qFAAqF;IACrF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACjD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAmDD;;;;GAIG;AACH,wBAAsB,sCAAsC,CAAC,OAAO,EAAE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;CACrC,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAWnG;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CACjD,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,sBAA2B,GAClC,OAAO,CAAC,OAAO,CAAC,CAyBlB","sourcesContent":["import { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1 } from \"../plugins/ecosystem/bootstrap-factory-manifest.ts\";\nimport { defaultPluginHostFactsV1, projectPluginScopeRefV1 } from \"../plugins/ecosystem/default-active-bindings.ts\";\nimport {\n\tcreateDefaultPluginMarketWiringV1,\n\ttype DefaultPluginMarketWiringV1,\n} from \"../plugins/ecosystem/default-plugin-market.ts\";\nimport {\n\tcreatePluginEcosystemCliV1,\n\tcreatePluginSelectionStoreV1,\n\tcreatePluginStateStoreV1,\n\ttype PluginDistributionV1,\n\ttype PluginEcosystemCliAcquisitionV1,\n\ttype PluginEcosystemCliResponseV1,\n\ttype PluginEcosystemCliV1,\n\ttype PluginEcosystemRegistryV1,\n\ttype PluginInstallerV1,\n\ttype PluginSelectionStoreV1,\n\ttype PluginStateStoreV1,\n} from \"../plugins/ecosystem/index.ts\";\nimport { listBuiltinPluginManifestsV1 } from \"../profile/plugin-profiles.ts\";\nimport type { PluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\nimport { createPluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\n\nexport interface PluginCommandOptionsV1 {\n\treadonly agentDir?: string;\n\t/** Working directory used for the project-local selection store. */\n\treadonly cwd?: string;\n\treadonly host?: {\n\t\treadonly os: string;\n\t\treadonly arch: string;\n\t\treadonly runtime: readonly { readonly name: string; readonly version: string }[];\n\t\treadonly apiVersion: string;\n\t\treadonly hostFeatures: readonly string[];\n\t};\n\t/** Optional host-owned boundaries used by install/update/remove commands. */\n\treadonly registry?: PluginEcosystemRegistryV1;\n\treadonly installer?: PluginInstallerV1;\n\t/** Optional host-owned multi-source package resolution used by install/update. */\n\treadonly acquisition?: PluginEcosystemCliAcquisitionV1;\n\t/** Optional host-owned package download boundary used by install/update. */\n\treadonly distribution?: PluginDistributionV1;\n\t/** Override persistence in tests or an embedding host; defaults remain agentDir files. */\n\treadonly stateStore?: PluginStateStoreV1;\n\t/** Override the project-local persistence boundary in tests or an embedding host. */\n\treadonly projectStateStore?: PluginStateStoreV1;\n\treadonly selectionStore?: PluginSelectionStoreV1;\n\treadonly projectSelectionStore?: PluginSelectionStoreV1;\n\treadonly write?: (line: string) => void;\n}\n\nfunction printResponse(response: PluginEcosystemCliResponseV1, write: (line: string) => void): void {\n\twrite(response.text);\n\tif (response.status !== \"succeeded\") process.exitCode = 1;\n}\n\ninterface MarketCliOptionsV1 {\n\treadonly agentDir: string;\n\treadonly cwd: string;\n\treadonly market?: DefaultPluginMarketWiringV1;\n\treadonly overrides?: PluginCommandOptionsV1;\n}\n\nfunction buildMarketCli(options: MarketCliOptionsV1): PluginEcosystemCliV1 {\n\tconst { market, overrides } = options;\n\treturn createPluginEcosystemCliV1({\n\t\thost: overrides?.host ?? defaultPluginHostFactsV1(),\n\t\tmanifests: listBuiltinPluginManifestsV1(),\n\t\tregistry: overrides?.registry ?? market?.cliRegistry,\n\t\t// Multi-source acquisition (`plugin install <ref>`) rides along with the\n\t\t// default market wiring; a fully host-injected stack replaces it wholesale.\n\t\t...(overrides?.acquisition === undefined && market?.acquisition === undefined\n\t\t\t? {}\n\t\t\t: { acquisition: overrides?.acquisition ?? market?.acquisition }),\n\t\tinstaller: overrides?.installer ?? market?.installer,\n\t\t...(overrides?.distribution !== undefined || market?.distribution !== undefined\n\t\t\t? { distribution: overrides?.distribution ?? market!.distribution }\n\t\t\t: {}),\n\t\tstateStore:\n\t\t\toverrides?.stateStore ??\n\t\t\tmarket?.stateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.agentDir, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectStateStore:\n\t\t\toverrides?.projectStateStore ??\n\t\t\tmarket?.projectStateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.cwd, CONFIG_DIR_NAME, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectScopeRef: projectPluginScopeRefV1(options.cwd),\n\t\tselectionStore:\n\t\t\toverrides?.selectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.agentDir, \".plugin-selection.json\") }),\n\t\tprojectSelectionStore:\n\t\t\toverrides?.projectSelectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.cwd, CONFIG_DIR_NAME, \".plugin-selection.json\") }),\n\t});\n}\n\n/**\n * Default TUI manager controller over the default marketplace wiring. The\n * controller reads the global or project state store per scope; callers must\n * invoke `close` after the config screen closes.\n */\nexport async function createDefaultPluginManagerControllerV1(options: {\n\treadonly agentDir?: string;\n\treadonly cwd?: string;\n\treadonly scope: \"global\" | \"project\";\n}): Promise<{ readonly controller: PluginManagerControllerV1; readonly close: () => Promise<void> }> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market = await createDefaultPluginMarketWiringV1({ agentDir, cwd });\n\tconst cli = buildMarketCli({ agentDir, cwd, market });\n\tconst controller = createPluginManagerControllerV1({\n\t\tregistry: market.registry,\n\t\tstateStore: options.scope === \"project\" ? market.projectStateStore : market.stateStore,\n\t\tcli,\n\t});\n\treturn { controller, close: market.close };\n}\n\n/**\n * Handle the independent ecosystem command namespace before legacy package\n * commands. Install/update/remove default to the disk install store plus an\n * optional configured marketplace origin; host injection of registry and\n * installer still wins entirely.\n */\nexport async function handlePluginEcosystemCommand(\n\targs: readonly string[],\n\toptions: PluginCommandOptionsV1 = {},\n): Promise<boolean> {\n\tif (args[0] !== \"plugin\") return false;\n\tconst write = options.write ?? ((line: string) => console.log(line));\n\t// Batch update convenience (0.85.7 user seat finding: a factory range bump\n\t// left seven plugins outdated and the per-plugin hint meant seven manual\n\t// commands). The ecosystem CLI protocol is unchanged — this outer layer\n\t// composes `state list` + one `update` per active plugin.\n\tif (args[1] === \"update\" && args[2] === \"--all\") {\n\t\tawait runBatchUpdate(args.slice(3), options, write);\n\t\treturn true;\n\t}\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst response = await cli.execute({ argv: args.slice(1) });\n\t\tprintResponse(response, write);\n\t\treturn true;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n\ninterface BatchUpdateEntry {\n\treadonly pluginId: string;\n\treadonly scope: string;\n\treadonly lifecycle: string;\n}\n\nasync function runBatchUpdate(\n\trestArgs: readonly string[],\n\toptions: PluginCommandOptionsV1,\n\twrite: (line: string) => void,\n): Promise<void> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst scopeIndex = restArgs.indexOf(\"--scope\");\n\tconst scope = scopeIndex !== -1 && restArgs[scopeIndex + 1] === \"project\" ? \"project\" : \"global\";\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst listResponse = await cli.execute({ argv: [\"state\", \"list\", \"--scope\", scope] });\n\t\tif (listResponse.status !== \"succeeded\") {\n\t\t\tprintResponse(listResponse, write);\n\t\t\treturn;\n\t\t}\n\t\tconst entries = ((listResponse.data?.entries ?? []) as readonly BatchUpdateEntry[]).filter(\n\t\t\t(entry) => entry.lifecycle === \"active\" && entry.scope === scope,\n\t\t);\n\t\tif (entries.length === 0) {\n\t\t\twrite(\"No active plugins to update.\");\n\t\t\treturn;\n\t\t}\n\t\tconst updated: string[] = [];\n\t\tconst current: string[] = [];\n\t\tconst failed: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\t// Factory-listed first-party plugins upgrade through the npm range the\n\t\t\t// bootstrap warnings name (`install <npmName>@^range`): the default disk\n\t\t\t// registry only resolves already-installed versions, so a bare `update`\n\t\t\t// there re-resolves the current version and reports nothing to do.\n\t\t\t// Non-factory plugins keep the bare `update` registry semantics.\n\t\t\tconst factoryEntry = BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1.find((item) => item.pluginId === entry.pluginId);\n\t\t\tconst argv = factoryEntry\n\t\t\t\t? [\"install\", `${factoryEntry.npmName}@${factoryEntry.range ?? \"latest\"}`, \"--scope\", scope]\n\t\t\t\t: [\"update\", entry.pluginId, \"--scope\", scope];\n\t\t\tconst response = await cli.execute({ argv });\n\t\t\tif (response.status === \"succeeded\") {\n\t\t\t\tupdated.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t} else if (response.error?.code === \"already_installed\") {\n\t\t\t\tcurrent.push(entry.pluginId);\n\t\t\t} else {\n\t\t\t\tfailed.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t}\n\t\t}\n\t\tconst summary = [\n\t\t\t`updated ${updated.length}${updated.length > 0 ? ` (${updated.join(\", \")})` : \"\"}`,\n\t\t\t`already up to date ${current.length}${current.length > 0 ? ` (${current.join(\", \")})` : \"\"}`,\n\t\t\t`failed ${failed.length}${failed.length > 0 ? ` (${failed.join(\", \")})` : \"\"}`,\n\t\t].join(\"; \");\n\t\twrite(`plugin update --all [${scope}]: ${summary}`);\n\t\tif (failed.length > 0) process.exitCode = 1;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { CONFIG_DIR_NAME, getAgentDir } from "../config.js";
|
|
3
|
+
import { BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1 } from "../plugins/ecosystem/bootstrap-factory-manifest.js";
|
|
3
4
|
import { defaultPluginHostFactsV1, projectPluginScopeRefV1 } from "../plugins/ecosystem/default-active-bindings.js";
|
|
4
5
|
import { createDefaultPluginMarketWiringV1, } from "../plugins/ecosystem/default-plugin-market.js";
|
|
5
6
|
import { createPluginEcosystemCliV1, createPluginSelectionStoreV1, createPluginStateStoreV1, } from "../plugins/ecosystem/index.js";
|
|
@@ -18,7 +19,9 @@ function buildMarketCli(options) {
|
|
|
18
19
|
registry: overrides?.registry ?? market?.cliRegistry,
|
|
19
20
|
// Multi-source acquisition (`plugin install <ref>`) rides along with the
|
|
20
21
|
// default market wiring; a fully host-injected stack replaces it wholesale.
|
|
21
|
-
...(
|
|
22
|
+
...(overrides?.acquisition === undefined && market?.acquisition === undefined
|
|
23
|
+
? {}
|
|
24
|
+
: { acquisition: overrides?.acquisition ?? market?.acquisition }),
|
|
22
25
|
installer: overrides?.installer ?? market?.installer,
|
|
23
26
|
...(overrides?.distribution !== undefined || market?.distribution !== undefined
|
|
24
27
|
? { distribution: overrides?.distribution ?? market.distribution }
|
|
@@ -114,7 +117,16 @@ async function runBatchUpdate(restArgs, options, write) {
|
|
|
114
117
|
const current = [];
|
|
115
118
|
const failed = [];
|
|
116
119
|
for (const entry of entries) {
|
|
117
|
-
|
|
120
|
+
// Factory-listed first-party plugins upgrade through the npm range the
|
|
121
|
+
// bootstrap warnings name (`install <npmName>@^range`): the default disk
|
|
122
|
+
// registry only resolves already-installed versions, so a bare `update`
|
|
123
|
+
// there re-resolves the current version and reports nothing to do.
|
|
124
|
+
// Non-factory plugins keep the bare `update` registry semantics.
|
|
125
|
+
const factoryEntry = BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1.find((item) => item.pluginId === entry.pluginId);
|
|
126
|
+
const argv = factoryEntry
|
|
127
|
+
? ["install", `${factoryEntry.npmName}@${factoryEntry.range ?? "latest"}`, "--scope", scope]
|
|
128
|
+
: ["update", entry.pluginId, "--scope", scope];
|
|
129
|
+
const response = await cli.execute({ argv });
|
|
118
130
|
if (response.status === "succeeded") {
|
|
119
131
|
updated.push(entry.pluginId);
|
|
120
132
|
write(response.text);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-command.js","sourceRoot":"","sources":["../../src/cli/plugin-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { defaultPluginHostFactsV1, projectPluginScopeRefV1 } from \"../plugins/ecosystem/default-active-bindings.ts\";\nimport {\n\tcreateDefaultPluginMarketWiringV1,\n\ttype DefaultPluginMarketWiringV1,\n} from \"../plugins/ecosystem/default-plugin-market.ts\";\nimport {\n\tcreatePluginEcosystemCliV1,\n\tcreatePluginSelectionStoreV1,\n\tcreatePluginStateStoreV1,\n\ttype PluginDistributionV1,\n\ttype PluginEcosystemCliResponseV1,\n\ttype PluginEcosystemCliV1,\n\ttype PluginEcosystemRegistryV1,\n\ttype PluginInstallerV1,\n\ttype PluginSelectionStoreV1,\n\ttype PluginStateStoreV1,\n} from \"../plugins/ecosystem/index.ts\";\nimport { listBuiltinPluginManifestsV1 } from \"../profile/plugin-profiles.ts\";\nimport type { PluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\nimport { createPluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\n\nexport interface PluginCommandOptionsV1 {\n\treadonly agentDir?: string;\n\t/** Working directory used for the project-local selection store. */\n\treadonly cwd?: string;\n\treadonly host?: {\n\t\treadonly os: string;\n\t\treadonly arch: string;\n\t\treadonly runtime: readonly { readonly name: string; readonly version: string }[];\n\t\treadonly apiVersion: string;\n\t\treadonly hostFeatures: readonly string[];\n\t};\n\t/** Optional host-owned boundaries used by install/update/remove commands. */\n\treadonly registry?: PluginEcosystemRegistryV1;\n\treadonly installer?: PluginInstallerV1;\n\t/** Optional host-owned package download boundary used by install/update. */\n\treadonly distribution?: PluginDistributionV1;\n\t/** Override persistence in tests or an embedding host; defaults remain agentDir files. */\n\treadonly stateStore?: PluginStateStoreV1;\n\t/** Override the project-local persistence boundary in tests or an embedding host. */\n\treadonly projectStateStore?: PluginStateStoreV1;\n\treadonly selectionStore?: PluginSelectionStoreV1;\n\treadonly projectSelectionStore?: PluginSelectionStoreV1;\n\treadonly write?: (line: string) => void;\n}\n\nfunction printResponse(response: PluginEcosystemCliResponseV1, write: (line: string) => void): void {\n\twrite(response.text);\n\tif (response.status !== \"succeeded\") process.exitCode = 1;\n}\n\ninterface MarketCliOptionsV1 {\n\treadonly agentDir: string;\n\treadonly cwd: string;\n\treadonly market?: DefaultPluginMarketWiringV1;\n\treadonly overrides?: PluginCommandOptionsV1;\n}\n\nfunction buildMarketCli(options: MarketCliOptionsV1): PluginEcosystemCliV1 {\n\tconst { market, overrides } = options;\n\treturn createPluginEcosystemCliV1({\n\t\thost: overrides?.host ?? defaultPluginHostFactsV1(),\n\t\tmanifests: listBuiltinPluginManifestsV1(),\n\t\tregistry: overrides?.registry ?? market?.cliRegistry,\n\t\t// Multi-source acquisition (`plugin install <ref>`) rides along with the\n\t\t// default market wiring; a fully host-injected stack replaces it wholesale.\n\t\t...(market?.acquisition === undefined ? {} : { acquisition: market.acquisition }),\n\t\tinstaller: overrides?.installer ?? market?.installer,\n\t\t...(overrides?.distribution !== undefined || market?.distribution !== undefined\n\t\t\t? { distribution: overrides?.distribution ?? market!.distribution }\n\t\t\t: {}),\n\t\tstateStore:\n\t\t\toverrides?.stateStore ??\n\t\t\tmarket?.stateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.agentDir, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectStateStore:\n\t\t\toverrides?.projectStateStore ??\n\t\t\tmarket?.projectStateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.cwd, CONFIG_DIR_NAME, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectScopeRef: projectPluginScopeRefV1(options.cwd),\n\t\tselectionStore:\n\t\t\toverrides?.selectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.agentDir, \".plugin-selection.json\") }),\n\t\tprojectSelectionStore:\n\t\t\toverrides?.projectSelectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.cwd, CONFIG_DIR_NAME, \".plugin-selection.json\") }),\n\t});\n}\n\n/**\n * Default TUI manager controller over the default marketplace wiring. The\n * controller reads the global or project state store per scope; callers must\n * invoke `close` after the config screen closes.\n */\nexport async function createDefaultPluginManagerControllerV1(options: {\n\treadonly agentDir?: string;\n\treadonly cwd?: string;\n\treadonly scope: \"global\" | \"project\";\n}): Promise<{ readonly controller: PluginManagerControllerV1; readonly close: () => Promise<void> }> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market = await createDefaultPluginMarketWiringV1({ agentDir, cwd });\n\tconst cli = buildMarketCli({ agentDir, cwd, market });\n\tconst controller = createPluginManagerControllerV1({\n\t\tregistry: market.registry,\n\t\tstateStore: options.scope === \"project\" ? market.projectStateStore : market.stateStore,\n\t\tcli,\n\t});\n\treturn { controller, close: market.close };\n}\n\n/**\n * Handle the independent ecosystem command namespace before legacy package\n * commands. Install/update/remove default to the disk install store plus an\n * optional configured marketplace origin; host injection of registry and\n * installer still wins entirely.\n */\nexport async function handlePluginEcosystemCommand(\n\targs: readonly string[],\n\toptions: PluginCommandOptionsV1 = {},\n): Promise<boolean> {\n\tif (args[0] !== \"plugin\") return false;\n\tconst write = options.write ?? ((line: string) => console.log(line));\n\t// Batch update convenience (0.85.7 user seat finding: a factory range bump\n\t// left seven plugins outdated and the per-plugin hint meant seven manual\n\t// commands). The ecosystem CLI protocol is unchanged — this outer layer\n\t// composes `state list` + one `update` per active plugin.\n\tif (args[1] === \"update\" && args[2] === \"--all\") {\n\t\tawait runBatchUpdate(args.slice(3), options, write);\n\t\treturn true;\n\t}\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst response = await cli.execute({ argv: args.slice(1) });\n\t\tprintResponse(response, write);\n\t\treturn true;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n\ninterface BatchUpdateEntry {\n\treadonly pluginId: string;\n\treadonly scope: string;\n\treadonly lifecycle: string;\n}\n\nasync function runBatchUpdate(\n\trestArgs: readonly string[],\n\toptions: PluginCommandOptionsV1,\n\twrite: (line: string) => void,\n): Promise<void> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst scopeIndex = restArgs.indexOf(\"--scope\");\n\tconst scope = scopeIndex !== -1 && restArgs[scopeIndex + 1] === \"project\" ? \"project\" : \"global\";\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst listResponse = await cli.execute({ argv: [\"state\", \"list\", \"--scope\", scope] });\n\t\tif (listResponse.status !== \"succeeded\") {\n\t\t\tprintResponse(listResponse, write);\n\t\t\treturn;\n\t\t}\n\t\tconst entries = ((listResponse.data?.entries ?? []) as readonly BatchUpdateEntry[]).filter(\n\t\t\t(entry) => entry.lifecycle === \"active\" && entry.scope === scope,\n\t\t);\n\t\tif (entries.length === 0) {\n\t\t\twrite(\"No active plugins to update.\");\n\t\t\treturn;\n\t\t}\n\t\tconst updated: string[] = [];\n\t\tconst current: string[] = [];\n\t\tconst failed: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\tconst response = await cli.execute({ argv: [\"update\", entry.pluginId, \"--scope\", scope] });\n\t\t\tif (response.status === \"succeeded\") {\n\t\t\t\tupdated.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t} else if (response.error?.code === \"already_installed\") {\n\t\t\t\tcurrent.push(entry.pluginId);\n\t\t\t} else {\n\t\t\t\tfailed.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t}\n\t\t}\n\t\tconst summary = [\n\t\t\t`updated ${updated.length}${updated.length > 0 ? ` (${updated.join(\", \")})` : \"\"}`,\n\t\t\t`already up to date ${current.length}${current.length > 0 ? ` (${current.join(\", \")})` : \"\"}`,\n\t\t\t`failed ${failed.length}${failed.length > 0 ? ` (${failed.join(\", \")})` : \"\"}`,\n\t\t].join(\"; \");\n\t\twrite(`plugin update --all [${scope}]: ${summary}`);\n\t\tif (failed.length > 0) process.exitCode = 1;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plugin-command.js","sourceRoot":"","sources":["../../src/cli/plugin-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1 } from \"../plugins/ecosystem/bootstrap-factory-manifest.ts\";\nimport { defaultPluginHostFactsV1, projectPluginScopeRefV1 } from \"../plugins/ecosystem/default-active-bindings.ts\";\nimport {\n\tcreateDefaultPluginMarketWiringV1,\n\ttype DefaultPluginMarketWiringV1,\n} from \"../plugins/ecosystem/default-plugin-market.ts\";\nimport {\n\tcreatePluginEcosystemCliV1,\n\tcreatePluginSelectionStoreV1,\n\tcreatePluginStateStoreV1,\n\ttype PluginDistributionV1,\n\ttype PluginEcosystemCliAcquisitionV1,\n\ttype PluginEcosystemCliResponseV1,\n\ttype PluginEcosystemCliV1,\n\ttype PluginEcosystemRegistryV1,\n\ttype PluginInstallerV1,\n\ttype PluginSelectionStoreV1,\n\ttype PluginStateStoreV1,\n} from \"../plugins/ecosystem/index.ts\";\nimport { listBuiltinPluginManifestsV1 } from \"../profile/plugin-profiles.ts\";\nimport type { PluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\nimport { createPluginManagerControllerV1 } from \"./plugin-manager-controller.ts\";\n\nexport interface PluginCommandOptionsV1 {\n\treadonly agentDir?: string;\n\t/** Working directory used for the project-local selection store. */\n\treadonly cwd?: string;\n\treadonly host?: {\n\t\treadonly os: string;\n\t\treadonly arch: string;\n\t\treadonly runtime: readonly { readonly name: string; readonly version: string }[];\n\t\treadonly apiVersion: string;\n\t\treadonly hostFeatures: readonly string[];\n\t};\n\t/** Optional host-owned boundaries used by install/update/remove commands. */\n\treadonly registry?: PluginEcosystemRegistryV1;\n\treadonly installer?: PluginInstallerV1;\n\t/** Optional host-owned multi-source package resolution used by install/update. */\n\treadonly acquisition?: PluginEcosystemCliAcquisitionV1;\n\t/** Optional host-owned package download boundary used by install/update. */\n\treadonly distribution?: PluginDistributionV1;\n\t/** Override persistence in tests or an embedding host; defaults remain agentDir files. */\n\treadonly stateStore?: PluginStateStoreV1;\n\t/** Override the project-local persistence boundary in tests or an embedding host. */\n\treadonly projectStateStore?: PluginStateStoreV1;\n\treadonly selectionStore?: PluginSelectionStoreV1;\n\treadonly projectSelectionStore?: PluginSelectionStoreV1;\n\treadonly write?: (line: string) => void;\n}\n\nfunction printResponse(response: PluginEcosystemCliResponseV1, write: (line: string) => void): void {\n\twrite(response.text);\n\tif (response.status !== \"succeeded\") process.exitCode = 1;\n}\n\ninterface MarketCliOptionsV1 {\n\treadonly agentDir: string;\n\treadonly cwd: string;\n\treadonly market?: DefaultPluginMarketWiringV1;\n\treadonly overrides?: PluginCommandOptionsV1;\n}\n\nfunction buildMarketCli(options: MarketCliOptionsV1): PluginEcosystemCliV1 {\n\tconst { market, overrides } = options;\n\treturn createPluginEcosystemCliV1({\n\t\thost: overrides?.host ?? defaultPluginHostFactsV1(),\n\t\tmanifests: listBuiltinPluginManifestsV1(),\n\t\tregistry: overrides?.registry ?? market?.cliRegistry,\n\t\t// Multi-source acquisition (`plugin install <ref>`) rides along with the\n\t\t// default market wiring; a fully host-injected stack replaces it wholesale.\n\t\t...(overrides?.acquisition === undefined && market?.acquisition === undefined\n\t\t\t? {}\n\t\t\t: { acquisition: overrides?.acquisition ?? market?.acquisition }),\n\t\tinstaller: overrides?.installer ?? market?.installer,\n\t\t...(overrides?.distribution !== undefined || market?.distribution !== undefined\n\t\t\t? { distribution: overrides?.distribution ?? market!.distribution }\n\t\t\t: {}),\n\t\tstateStore:\n\t\t\toverrides?.stateStore ??\n\t\t\tmarket?.stateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.agentDir, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectStateStore:\n\t\t\toverrides?.projectStateStore ??\n\t\t\tmarket?.projectStateStore ??\n\t\t\tcreatePluginStateStoreV1({\n\t\t\t\tfilePath: join(options.cwd, CONFIG_DIR_NAME, \"plugin-state.json\"),\n\t\t\t}),\n\t\tprojectScopeRef: projectPluginScopeRefV1(options.cwd),\n\t\tselectionStore:\n\t\t\toverrides?.selectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.agentDir, \".plugin-selection.json\") }),\n\t\tprojectSelectionStore:\n\t\t\toverrides?.projectSelectionStore ??\n\t\t\tcreatePluginSelectionStoreV1({ filePath: join(options.cwd, CONFIG_DIR_NAME, \".plugin-selection.json\") }),\n\t});\n}\n\n/**\n * Default TUI manager controller over the default marketplace wiring. The\n * controller reads the global or project state store per scope; callers must\n * invoke `close` after the config screen closes.\n */\nexport async function createDefaultPluginManagerControllerV1(options: {\n\treadonly agentDir?: string;\n\treadonly cwd?: string;\n\treadonly scope: \"global\" | \"project\";\n}): Promise<{ readonly controller: PluginManagerControllerV1; readonly close: () => Promise<void> }> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market = await createDefaultPluginMarketWiringV1({ agentDir, cwd });\n\tconst cli = buildMarketCli({ agentDir, cwd, market });\n\tconst controller = createPluginManagerControllerV1({\n\t\tregistry: market.registry,\n\t\tstateStore: options.scope === \"project\" ? market.projectStateStore : market.stateStore,\n\t\tcli,\n\t});\n\treturn { controller, close: market.close };\n}\n\n/**\n * Handle the independent ecosystem command namespace before legacy package\n * commands. Install/update/remove default to the disk install store plus an\n * optional configured marketplace origin; host injection of registry and\n * installer still wins entirely.\n */\nexport async function handlePluginEcosystemCommand(\n\targs: readonly string[],\n\toptions: PluginCommandOptionsV1 = {},\n): Promise<boolean> {\n\tif (args[0] !== \"plugin\") return false;\n\tconst write = options.write ?? ((line: string) => console.log(line));\n\t// Batch update convenience (0.85.7 user seat finding: a factory range bump\n\t// left seven plugins outdated and the per-plugin hint meant seven manual\n\t// commands). The ecosystem CLI protocol is unchanged — this outer layer\n\t// composes `state list` + one `update` per active plugin.\n\tif (args[1] === \"update\" && args[2] === \"--all\") {\n\t\tawait runBatchUpdate(args.slice(3), options, write);\n\t\treturn true;\n\t}\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst response = await cli.execute({ argv: args.slice(1) });\n\t\tprintResponse(response, write);\n\t\treturn true;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n\ninterface BatchUpdateEntry {\n\treadonly pluginId: string;\n\treadonly scope: string;\n\treadonly lifecycle: string;\n}\n\nasync function runBatchUpdate(\n\trestArgs: readonly string[],\n\toptions: PluginCommandOptionsV1,\n\twrite: (line: string) => void,\n): Promise<void> {\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst scopeIndex = restArgs.indexOf(\"--scope\");\n\tconst scope = scopeIndex !== -1 && restArgs[scopeIndex + 1] === \"project\" ? \"project\" : \"global\";\n\tconst market =\n\t\toptions.registry === undefined && options.installer === undefined\n\t\t\t? await createDefaultPluginMarketWiringV1({ agentDir, cwd })\n\t\t\t: undefined;\n\ttry {\n\t\tconst cli = buildMarketCli({ agentDir, cwd, market, overrides: options });\n\t\tconst listResponse = await cli.execute({ argv: [\"state\", \"list\", \"--scope\", scope] });\n\t\tif (listResponse.status !== \"succeeded\") {\n\t\t\tprintResponse(listResponse, write);\n\t\t\treturn;\n\t\t}\n\t\tconst entries = ((listResponse.data?.entries ?? []) as readonly BatchUpdateEntry[]).filter(\n\t\t\t(entry) => entry.lifecycle === \"active\" && entry.scope === scope,\n\t\t);\n\t\tif (entries.length === 0) {\n\t\t\twrite(\"No active plugins to update.\");\n\t\t\treturn;\n\t\t}\n\t\tconst updated: string[] = [];\n\t\tconst current: string[] = [];\n\t\tconst failed: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\t// Factory-listed first-party plugins upgrade through the npm range the\n\t\t\t// bootstrap warnings name (`install <npmName>@^range`): the default disk\n\t\t\t// registry only resolves already-installed versions, so a bare `update`\n\t\t\t// there re-resolves the current version and reports nothing to do.\n\t\t\t// Non-factory plugins keep the bare `update` registry semantics.\n\t\t\tconst factoryEntry = BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1.find((item) => item.pluginId === entry.pluginId);\n\t\t\tconst argv = factoryEntry\n\t\t\t\t? [\"install\", `${factoryEntry.npmName}@${factoryEntry.range ?? \"latest\"}`, \"--scope\", scope]\n\t\t\t\t: [\"update\", entry.pluginId, \"--scope\", scope];\n\t\t\tconst response = await cli.execute({ argv });\n\t\t\tif (response.status === \"succeeded\") {\n\t\t\t\tupdated.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t} else if (response.error?.code === \"already_installed\") {\n\t\t\t\tcurrent.push(entry.pluginId);\n\t\t\t} else {\n\t\t\t\tfailed.push(entry.pluginId);\n\t\t\t\twrite(response.text);\n\t\t\t}\n\t\t}\n\t\tconst summary = [\n\t\t\t`updated ${updated.length}${updated.length > 0 ? ` (${updated.join(\", \")})` : \"\"}`,\n\t\t\t`already up to date ${current.length}${current.length > 0 ? ` (${current.join(\", \")})` : \"\"}`,\n\t\t\t`failed ${failed.length}${failed.length > 0 ? ` (${failed.join(\", \")})` : \"\"}`,\n\t\t].join(\"; \");\n\t\twrite(`plugin update --all [${scope}]: ${summary}`);\n\t\tif (failed.length > 0) process.exitCode = 1;\n\t} finally {\n\t\tawait market?.close();\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-factory-manifest.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/bootstrap-factory-manifest.ts"],"names":[],"mappings":"AAoBA,uDAAuD;AACvD,MAAM,WAAW,6BAA6B;IAC7C,uEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,EAAE,SAAS,6BAA6B,
|
|
1
|
+
{"version":3,"file":"bootstrap-factory-manifest.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/bootstrap-factory-manifest.ts"],"names":[],"mappings":"AAoBA,uDAAuD;AACvD,MAAM,WAAW,6BAA6B;IAC7C,uEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,EAAE,SAAS,6BAA6B,EA0BvF,CAAC","sourcesContent":["/**\n * Factory plugin manifest for the startup bootstrap (design\n * `插件独立分发与启动装配设计.md` §4.4). Pure data only: the framework\n * declares which first-party plugin packages a fresh install should end up\n * with, as `pluginId → npm name + version constraint`. It ships with the\n * framework version and is never a code branch.\n *\n * Each S2–S4 migrated package appends one entry here with its publish name\n * (`@ai-agent-forge/plugin-<name>`, §0.8) together with the legacy short-id\n * mapping noted in §4.1.\n *\n * Ranges are derived from the framework's own VERSION at module init — a\n * hardcoded range here outlived a lockstep bump once (published 0.85.0 kept\n * `^0.84.4`, which excludes 0.85.0 under caret-on-0.x semantics, breaking\n * every fresh install's npm bootstrap). Deriving keeps the manifest in step\n * with the version the publish channel stamps, including the\n * rename/version rewrite in the local publish script.\n */\nimport { VERSION } from \"../../config.ts\";\n\n/** One factory-declared first-party plugin package. */\nexport interface PluginBootstrapFactoryEntryV1 {\n\t/** Ecosystem plugin id (`agent-forge.plugin.<name>` domain, §4.1). */\n\treadonly pluginId: string;\n\t/** npm publish name (`@ai-agent-forge/plugin-<name>`, §0.8). */\n\treadonly npmName: string;\n\t/**\n\t * Minimal range subset shared with npm resolution (`x.y.z`, `^x.y.z`,\n\t * `~x.y.z`, `latest`); omitted means the highest available version.\n\t */\n\treadonly range?: string;\n}\n\n/** Lockstep range every first-party bootstrap entry ships under. */\nconst FACTORY_PLUGIN_RANGE = `^${VERSION}`;\n\n/**\n * Frozen factory manifest consumed by `runPluginBootstrapV1`. D-075 S4 first\n * batch: the goal/plan/todo-set capability packages joined; second batch:\n * session-share and observability joined; third batch: subagent-delegate\n * joined; fourth batch: memory joined (completing the six-package split).\n * Later B-class batches append their entries per package.\n */\nexport const BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1: readonly PluginBootstrapFactoryEntryV1[] = Object.freeze([\n\t{ pluginId: \"agent-forge.plugin.goal\", npmName: \"@ai-agent-forge/plugin-goal\", range: FACTORY_PLUGIN_RANGE },\n\t{ pluginId: \"agent-forge.plugin.plan\", npmName: \"@ai-agent-forge/plugin-plan\", range: FACTORY_PLUGIN_RANGE },\n\t{ pluginId: \"agent-forge.plugin.todo-set\", npmName: \"@ai-agent-forge/plugin-todo-set\", range: FACTORY_PLUGIN_RANGE },\n\t{\n\t\tpluginId: \"agent-forge.plugin.session-share\",\n\t\tnpmName: \"@ai-agent-forge/plugin-session-share\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n\t{\n\t\tpluginId: \"agent-forge.plugin.observability\",\n\t\tnpmName: \"@ai-agent-forge/plugin-observability\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n\t{\n\t\tpluginId: \"agent-forge.plugin.subagent-delegate\",\n\t\tnpmName: \"@ai-agent-forge/plugin-subagent-delegate\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n\t{ pluginId: \"agent-forge.plugin.memory\", npmName: \"@ai-agent-forge/plugin-memory\", range: FACTORY_PLUGIN_RANGE },\n\t// image generation (2026-09-30): first-party generate/edit tools package.\n\t{\n\t\tpluginId: \"agent-forge.plugin.image-generation\",\n\t\tnpmName: \"@ai-agent-forge/plugin-image-generation\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n]);\n"]}
|
|
@@ -46,5 +46,11 @@ export const BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1 = Object.freeze([
|
|
|
46
46
|
range: FACTORY_PLUGIN_RANGE,
|
|
47
47
|
},
|
|
48
48
|
{ pluginId: "agent-forge.plugin.memory", npmName: "@ai-agent-forge/plugin-memory", range: FACTORY_PLUGIN_RANGE },
|
|
49
|
+
// image generation (2026-09-30): first-party generate/edit tools package.
|
|
50
|
+
{
|
|
51
|
+
pluginId: "agent-forge.plugin.image-generation",
|
|
52
|
+
npmName: "@ai-agent-forge/plugin-image-generation",
|
|
53
|
+
range: FACTORY_PLUGIN_RANGE,
|
|
54
|
+
},
|
|
49
55
|
]);
|
|
50
56
|
//# sourceMappingURL=bootstrap-factory-manifest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-factory-manifest.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/bootstrap-factory-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAe1C,oEAAoE;AACpE,MAAM,oBAAoB,GAAG,IAAI,OAAO,EAAE,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAA6C,MAAM,CAAC,MAAM,CAAC;IAC3G,EAAE,QAAQ,EAAE,yBAAyB,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAC5G,EAAE,QAAQ,EAAE,yBAAyB,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAC5G,EAAE,QAAQ,EAAE,6BAA6B,EAAE,OAAO,EAAE,iCAAiC,EAAE,KAAK,EAAE,oBAAoB,EAAE;IACpH;QACC,QAAQ,EAAE,kCAAkC;QAC5C,OAAO,EAAE,sCAAsC;QAC/C,KAAK,EAAE,oBAAoB;KAC3B;IACD;QACC,QAAQ,EAAE,kCAAkC;QAC5C,OAAO,EAAE,sCAAsC;QAC/C,KAAK,EAAE,oBAAoB;KAC3B;IACD;QACC,QAAQ,EAAE,sCAAsC;QAChD,OAAO,EAAE,0CAA0C;QACnD,KAAK,EAAE,oBAAoB;KAC3B;IACD,EAAE,QAAQ,EAAE,2BAA2B,EAAE,OAAO,EAAE,+BAA+B,EAAE,KAAK,EAAE,oBAAoB,EAAE;
|
|
1
|
+
{"version":3,"file":"bootstrap-factory-manifest.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/bootstrap-factory-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAe1C,oEAAoE;AACpE,MAAM,oBAAoB,GAAG,IAAI,OAAO,EAAE,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAA6C,MAAM,CAAC,MAAM,CAAC;IAC3G,EAAE,QAAQ,EAAE,yBAAyB,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAC5G,EAAE,QAAQ,EAAE,yBAAyB,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAC5G,EAAE,QAAQ,EAAE,6BAA6B,EAAE,OAAO,EAAE,iCAAiC,EAAE,KAAK,EAAE,oBAAoB,EAAE;IACpH;QACC,QAAQ,EAAE,kCAAkC;QAC5C,OAAO,EAAE,sCAAsC;QAC/C,KAAK,EAAE,oBAAoB;KAC3B;IACD;QACC,QAAQ,EAAE,kCAAkC;QAC5C,OAAO,EAAE,sCAAsC;QAC/C,KAAK,EAAE,oBAAoB;KAC3B;IACD;QACC,QAAQ,EAAE,sCAAsC;QAChD,OAAO,EAAE,0CAA0C;QACnD,KAAK,EAAE,oBAAoB;KAC3B;IACD,EAAE,QAAQ,EAAE,2BAA2B,EAAE,OAAO,EAAE,+BAA+B,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAChH,0EAA0E;IAC1E;QACC,QAAQ,EAAE,qCAAqC;QAC/C,OAAO,EAAE,yCAAyC;QAClD,KAAK,EAAE,oBAAoB;KAC3B;CACD,CAAC,CAAC","sourcesContent":["/**\n * Factory plugin manifest for the startup bootstrap (design\n * `插件独立分发与启动装配设计.md` §4.4). Pure data only: the framework\n * declares which first-party plugin packages a fresh install should end up\n * with, as `pluginId → npm name + version constraint`. It ships with the\n * framework version and is never a code branch.\n *\n * Each S2–S4 migrated package appends one entry here with its publish name\n * (`@ai-agent-forge/plugin-<name>`, §0.8) together with the legacy short-id\n * mapping noted in §4.1.\n *\n * Ranges are derived from the framework's own VERSION at module init — a\n * hardcoded range here outlived a lockstep bump once (published 0.85.0 kept\n * `^0.84.4`, which excludes 0.85.0 under caret-on-0.x semantics, breaking\n * every fresh install's npm bootstrap). Deriving keeps the manifest in step\n * with the version the publish channel stamps, including the\n * rename/version rewrite in the local publish script.\n */\nimport { VERSION } from \"../../config.ts\";\n\n/** One factory-declared first-party plugin package. */\nexport interface PluginBootstrapFactoryEntryV1 {\n\t/** Ecosystem plugin id (`agent-forge.plugin.<name>` domain, §4.1). */\n\treadonly pluginId: string;\n\t/** npm publish name (`@ai-agent-forge/plugin-<name>`, §0.8). */\n\treadonly npmName: string;\n\t/**\n\t * Minimal range subset shared with npm resolution (`x.y.z`, `^x.y.z`,\n\t * `~x.y.z`, `latest`); omitted means the highest available version.\n\t */\n\treadonly range?: string;\n}\n\n/** Lockstep range every first-party bootstrap entry ships under. */\nconst FACTORY_PLUGIN_RANGE = `^${VERSION}`;\n\n/**\n * Frozen factory manifest consumed by `runPluginBootstrapV1`. D-075 S4 first\n * batch: the goal/plan/todo-set capability packages joined; second batch:\n * session-share and observability joined; third batch: subagent-delegate\n * joined; fourth batch: memory joined (completing the six-package split).\n * Later B-class batches append their entries per package.\n */\nexport const BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1: readonly PluginBootstrapFactoryEntryV1[] = Object.freeze([\n\t{ pluginId: \"agent-forge.plugin.goal\", npmName: \"@ai-agent-forge/plugin-goal\", range: FACTORY_PLUGIN_RANGE },\n\t{ pluginId: \"agent-forge.plugin.plan\", npmName: \"@ai-agent-forge/plugin-plan\", range: FACTORY_PLUGIN_RANGE },\n\t{ pluginId: \"agent-forge.plugin.todo-set\", npmName: \"@ai-agent-forge/plugin-todo-set\", range: FACTORY_PLUGIN_RANGE },\n\t{\n\t\tpluginId: \"agent-forge.plugin.session-share\",\n\t\tnpmName: \"@ai-agent-forge/plugin-session-share\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n\t{\n\t\tpluginId: \"agent-forge.plugin.observability\",\n\t\tnpmName: \"@ai-agent-forge/plugin-observability\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n\t{\n\t\tpluginId: \"agent-forge.plugin.subagent-delegate\",\n\t\tnpmName: \"@ai-agent-forge/plugin-subagent-delegate\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n\t{ pluginId: \"agent-forge.plugin.memory\", npmName: \"@ai-agent-forge/plugin-memory\", range: FACTORY_PLUGIN_RANGE },\n\t// image generation (2026-09-30): first-party generate/edit tools package.\n\t{\n\t\tpluginId: \"agent-forge.plugin.image-generation\",\n\t\tnpmName: \"@ai-agent-forge/plugin-image-generation\",\n\t\trange: FACTORY_PLUGIN_RANGE,\n\t},\n]);\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HostFactsV1, PluginManifestV1, ProfileResolutionV1 } from "../plugins/ecosystem/types.ts";
|
|
2
2
|
import { type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from "./profile-assembly.ts";
|
|
3
|
-
export type BuiltinPluginProfileIdV1 = "coding-core" | "desktop-qa" | "desktop-observe" | "desktop-control" | "lsp-diagnostics" | "process-exec" | "test-runner" | "workspace-files" | "workspace-files-write" | "formatter-linter" | "git-repository";
|
|
3
|
+
export type BuiltinPluginProfileIdV1 = "coding-core" | "desktop-qa" | "desktop-observe" | "desktop-control" | "lsp-diagnostics" | "image-generation" | "process-exec" | "test-runner" | "workspace-files" | "workspace-files-write" | "formatter-linter" | "git-repository";
|
|
4
4
|
export interface BuiltinPluginProfileV1 {
|
|
5
5
|
readonly id: BuiltinPluginProfileIdV1;
|
|
6
6
|
readonly version: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-profiles.d.ts","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAmB,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEjH,MAAM,MAAM,wBAAwB,GACjC,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE1F,MAAM,MAAM,gCAAgC,GACzC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IACA,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC3C,CAAC;AAsCL,wBAAgB,2BAA2B,IAAI,SAAS,sBAAsB,EAAE,CAE/E;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,SAAS,gBAAgB,EAAE,CAO1E;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAOlG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;CAC9D,GAAG,gCAAgC,CA2FnC","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plugin-profiles.d.ts","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAmB,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEjH,MAAM,MAAM,wBAAwB,GACjC,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE1F,MAAM,MAAM,gCAAgC,GACzC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IACA,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC3C,CAAC;AAuCL,wBAAgB,2BAA2B,IAAI,SAAS,sBAAsB,EAAE,CAE/E;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,SAAS,gBAAgB,EAAE,CAO1E;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAOlG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;CAC9D,GAAG,gCAAgC,CA2FnC","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
|
|
@@ -21,6 +21,7 @@ const profiles = Object.freeze([
|
|
|
21
21
|
pluginIds: ["agent-forge.plugin.desktop-windows-observe", "agent-forge.plugin.desktop-windows-input"],
|
|
22
22
|
},
|
|
23
23
|
{ id: "lsp-diagnostics", version: "1", pluginIds: ["agent-forge.plugin.lsp-diagnostics"] },
|
|
24
|
+
{ id: "image-generation", version: "1", pluginIds: ["agent-forge.plugin.image-generation"] },
|
|
24
25
|
{ id: "process-exec", version: "1", pluginIds: ["agent-forge.plugin.process-exec"] },
|
|
25
26
|
{ id: "test-runner", version: "1", pluginIds: ["agent-forge.plugin.test-runner"] },
|
|
26
27
|
{ id: "workspace-files", version: "1", pluginIds: ["agent-forge.plugin.workspace-files"] },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-profiles.js","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plugin-profiles.js","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
|