diff --git a/.changeset/temporary-marketplace-isolation.md b/.changeset/temporary-marketplace-isolation.md new file mode 100644 index 000000000..6478b29e7 --- /dev/null +++ b/.changeset/temporary-marketplace-isolation.md @@ -0,0 +1,5 @@ +--- +"agent-bundle": patch +--- + +Preserve `output.repositoryMarketplace` files during temporary MCP, hook, and `serve-app` builds, including failed operations (#828). diff --git a/packages/agent-bundle/src/api.ts b/packages/agent-bundle/src/api.ts index 2c51df559..1268c2069 100644 --- a/packages/agent-bundle/src/api.ts +++ b/packages/agent-bundle/src/api.ts @@ -791,6 +791,7 @@ const temporaryArtifact = async ( logger: options.logger, mode: options.mode, output: artifact, + repositoryMarketplaces: false, registry: options.registry, root: options.root, targets: options.targets, @@ -1620,6 +1621,7 @@ const scopedThrowawayArtifact = ( logger: options.logger, mode: options.mode, output: artifact, + repositoryMarketplaces: false, registry: options.registry, root: options.root, targets: options.targets, diff --git a/packages/agent-bundle/tests/api.test.ts b/packages/agent-bundle/tests/api.test.ts index ef75c592c..2042405fe 100644 --- a/packages/agent-bundle/tests/api.test.ts +++ b/packages/agent-bundle/tests/api.test.ts @@ -5,7 +5,7 @@ import { join } from 'node:path'; import { expect, it } from '@rstest/core'; -import { TargetRegistry, build, createDefaultRegistry, inspect, invokeMcp, listHooks, listMcp, simulateHook, validate } from '../src/api.ts'; +import { TargetRegistry, build, createDefaultRegistry, inspect, invokeMcp, listHooks, listMcp, serveApp, simulateHook, validate } from '../src/api.ts'; import { unavailableCapability } from '../src/adapters/capability-state.ts'; import { nativeHookWrapperSource, @@ -386,6 +386,18 @@ it('emits repository marketplaces from the selected host plans without making ou const first = await build({ root }); const second = await build({ root }); expect(second.projectContext.sourceInputs).toEqual(first.projectContext.sourceInputs); + const marketplaceBeforeOperations = await readFile(join(root, '.cursor-plugin/marketplace.json'), 'utf8'); + await listHooks({ root, target: 'cursor' }); + expect(await readFile(join(root, '.cursor-plugin/marketplace.json'), 'utf8')).toBe(marketplaceBeforeOperations); + const serveEvents: string[] = []; + await expect(serveApp({ + app: 'missing/missing', + logger: { log: (event) => { serveEvents.push(event); } }, + root, + target: 'cursor', + })).rejects.toThrow(); + expect(serveEvents).toContain('artifact.build'); + expect(await readFile(join(root, '.cursor-plugin/marketplace.json'), 'utf8')).toBe(marketplaceBeforeOperations); for (const path of ['.claude-plugin/marketplace.json', '.cursor-plugin/marketplace.json', '.agents/plugins/marketplace.json']) { const repository = JSON.parse(await readFile(join(root, path), 'utf8')); const artifact = JSON.parse(await readFile(join(root, 'artifact', path), 'utf8')); diff --git a/website/docs/en/reference/configuration.mdx b/website/docs/en/reference/configuration.mdx index 510c353fb..ff61fd02e 100644 --- a/website/docs/en/reference/configuration.mdx +++ b/website/docs/en/reference/configuration.mdx @@ -162,6 +162,8 @@ the selected marketplace files; do not hand-edit them. It refuses symlinked dest paths that overlap the artifact, custom adapters, and authored marketplace source or `metadata.pluginRoot` overrides. These generated files are excluded from source snapshots. Development and evaluation staging do not publish repository marketplaces. +Temporary builds used by MCP commands, hook inspection/simulation, and `serve-app` also +leave these files unchanged, including when the operation fails. `output.distPath` is the artifact output directory relative to the project root — the composite plugin root every selected host reads, with no per-host subdirectory beneath it. The CLI diff --git a/website/docs/zh/reference/configuration.mdx b/website/docs/zh/reference/configuration.mdx index f17998f7d..f709e76b8 100644 --- a/website/docs/zh/reference/configuration.mdx +++ b/website/docs/zh/reference/configuration.mdx @@ -141,6 +141,7 @@ Claude Code 的 `.claude-plugin/plugin.json` 不携带描述字段——其固 一起提交后,即可从 GitHub 直接安装。编译器会替换所选市场清单,请勿手工编辑。它会拒绝符号链接、 与产物目录重叠的路径、自定义适配器,以及手写的市场来源或 `metadata.pluginRoot` 覆盖。 这些生成文件不计入源码快照。开发与评估的暂存构建不会发布项目根目录市场清单。 +MCP 命令、钩子查看或模拟以及 `serve-app` 使用的临时构建也不会修改这些文件,即使操作失败。 `output.distPath` 是相对项目根目录的产物输出目录——每个所选宿主都读取的组合插件根目录,其下没有逐宿主 子目录。命令行(`build`、`prepack`、`dev`)把它默认为 `artifact`,