diff --git a/config/aipods/artificer.yaml b/config/aipods/artificer.yaml index fca9dd1..85815ce 100644 --- a/config/aipods/artificer.yaml +++ b/config/aipods/artificer.yaml @@ -62,8 +62,7 @@ spec: repoUrl: git@github.com:pikasTech/unidesk.git ref: master gitMirror: - enabled: true - baseUrl: http://git-mirror-http.devops-infra.svc.cluster.local + enabled: false bundles: - name: unidesk-skills subpath: .agents/skills diff --git a/docs/reference/spec-v01-aipod-spec.md b/docs/reference/spec-v01-aipod-spec.md index d250c91..eea5566 100644 --- a/docs/reference/spec-v01-aipod-spec.md +++ b/docs/reference/spec-v01-aipod-spec.md @@ -60,7 +60,7 @@ spec: - 通过 provider SecretRef `agentrun-v01-provider-sub2api` 获取 `auth.json` 与 `config.toml`。 - 通过 `toolCredentials` 获取 UniDesk SSH 透传 token:`agentrun-v01-tool-unidesk-ssh` -> env `UNIDESK_SSH_CLIENT_TOKEN`。 - 通过 `toolCredentials` 获取 GitHub SSH 凭据:`agentrun-v01-tool-github-ssh` -> volume `/home/agentrun/.ssh`。 -- 通过 gitbundle 装配 UniDesk repo 中的 `unidesk-*` skills、AgentRun repo 中的 `tools/trans`、`tools/tran`、`tools/apply_patch`,以及 `agent_skills` repo 中的 `dad-dev`、`cli-spec`、`docs-spec`、`git-spec`。 +- 通过 GitHub SSH 直接 checkout 多仓库 gitbundle,装配 UniDesk repo 中的 `unidesk-*` skills、AgentRun repo 中的 `tools/trans`、`tools/tran`、`tools/apply_patch`,以及 `agent_skills` repo 中的 `dad-dev`、`cli-spec`、`docs-spec`、`git-spec`;Artificer 默认不依赖 G14 git mirror 的覆盖范围。 - 通过 `requiredSkills[]` 在 runner 启动 backend 前校验 `dad-dev` 与 UniDesk 关键 skills 已被 materialize;缺失时必须 `required-skill-unavailable`,不得使用模型默认 skill 猜测。 ## Git mirror @@ -75,6 +75,8 @@ spec: - 非 GitHub URL 不改写,仍按原 `repoUrl` fetch。 - materialization event 必须输出 `repoUrl`、`fetchRepoUrl`、`mirrorUsed`、`mirrorBaseUrl`、requested ref/commit 和实际 commit;不得输出 credential 值。 +Artificer 默认 `gitMirror.enabled=false`,依靠 `agentrun-v01-tool-github-ssh` 投影的 SSH 凭据直接拉取 `unidesk`、`agentrun` 和 `agent_skills`。只有明确确认目标 repo 已纳入 G14 mirror cache 的规格,才应显式启用 `gitMirror`。 + ## Tool credential projection `toolCredentials[]` 支持两类 projection: @@ -118,8 +120,8 @@ CLI: ## 测试规格 -- A1:`config/aipods/artificer.yaml` 能被 manager list/show/render,render 结果包含 `backendProfile=sub2api`、`model=gpt-5.5`、`reasoningEffort=xhigh`、provider SecretRef、UniDesk SSH env projection、GitHub SSH volume projection、AgentRun runner tools gitbundle 和 gitbundle requiredSkills。 +- A1:`config/aipods/artificer.yaml` 能被 manager list/show/render,render 结果包含 `backendProfile=sub2api`、`model=gpt-5.5`、`reasoningEffort=xhigh`、provider SecretRef、UniDesk SSH env projection、GitHub SSH volume projection、Artificer `gitMirror.enabled=false`、AgentRun runner tools gitbundle 和 gitbundle requiredSkills。 - A2:`queue submit --aipod Artificer --dry-run` 输出标准 `queue-submit-plan`,且 `idempotencyKey`、prompt 与 metadata 被保留。 -- A3:GitHub URL 在启用 `gitMirror` 后改写到 mirror base URL;非 GitHub URL 不改写。 +- A3:Artificer 默认 `gitMirror.enabled=false` 时 GitHub URL 保持 SSH fetch;显式启用 `gitMirror` 后 GitHub URL 改写到 mirror base URL;非 GitHub URL 不改写。 - A4:runner Job dry-run 支持 tool credential volume mount,并且 response/manifest/event 不泄漏 Secret 明文。 - A5:`bun run check` 和 `bun run self-test` 必须覆盖 A1-A4。 diff --git a/src/selftest/cases/76-aipod-spec.ts b/src/selftest/cases/76-aipod-spec.ts index f672b08..65f9342 100644 --- a/src/selftest/cases/76-aipod-spec.ts +++ b/src/selftest/cases/76-aipod-spec.ts @@ -24,7 +24,7 @@ const selfTest: SelfTestCase = async (context) => { const shownItem = shown.item as JsonRecord; assert.equal(shownItem.backendProfile, "sub2api"); assert.equal(((shownItem.model as JsonRecord).model), "gpt-5.5"); - assert.equal(((shownItem.resourceBundleRef as JsonRecord).gitMirror as JsonRecord).enabled, true); + assert.equal(((shownItem.resourceBundleRef as JsonRecord).gitMirror as JsonRecord).enabled, false); const rendered = await client.post("/api/v1/aipod-specs/Artificer/render", { prompt: "处理 pikasTech/unidesk#245", idempotencyKey: "selftest-aipod-artificer" }) as JsonRecord; assert.equal(rendered.action, "aipod-spec-render"); @@ -42,7 +42,7 @@ const selfTest: SelfTestCase = async (context) => { assert.equal(toolCredentials.some((item) => item.tool === "unidesk-ssh" && ((item.projection as JsonRecord).envName) === "UNIDESK_SSH_CLIENT_TOKEN"), true); assert.equal(toolCredentials.some((item) => item.tool === "github" && ((item.projection as JsonRecord).kind) === "volume" && ((item.projection as JsonRecord).mountPath) === "/home/agentrun/.ssh"), true); const bundle = task.resourceBundleRef as JsonRecord; - assert.equal(((bundle.gitMirror as JsonRecord).enabled), true); + assert.equal(((bundle.gitMirror as JsonRecord).enabled), false); const bundles = bundle.bundles as JsonRecord[]; const toolBundle = bundles.find((item) => item.name === "agentrun-runner-tools") as JsonRecord | undefined; assert.equal(toolBundle?.repoUrl, "git@github.com:pikasTech/agentrun.git"); @@ -56,6 +56,9 @@ const selfTest: SelfTestCase = async (context) => { const mirrored = resolveGitBundleFetchSource("git@github.com:pikasTech/unidesk.git", { enabled: true, baseUrl: "http://mirror.example.test/root/" }, {}); assert.equal(mirrored.fetchRepoUrl, "http://mirror.example.test/root/pikasTech/unidesk.git"); assert.equal(mirrored.mirrorUsed, true); + const disabledMirror = resolveGitBundleFetchSource("git@github.com:pikasTech/unidesk.git", { enabled: false, baseUrl: "http://mirror.example.test/root/" }, {}); + assert.equal(disabledMirror.fetchRepoUrl, "git@github.com:pikasTech/unidesk.git"); + assert.equal(disabledMirror.mirrorUsed, false); const nonGithub = resolveGitBundleFetchSource("ssh://git@example.test/repo.git", { enabled: true, baseUrl: "http://mirror.example.test" }, {}); assert.equal(nonGithub.fetchRepoUrl, "ssh://git@example.test/repo.git"); assert.equal(nonGithub.mirrorUsed, false); @@ -72,7 +75,7 @@ const selfTest: SelfTestCase = async (context) => { assert.equal(commands.some((item) => item.includes("aipod-specs render ")), true); assert.equal(commands.some((item) => item.includes("queue submit --aipod ")), true); assertNoSecretLeak(submitPlan); - return { name: "aipod-spec", tests: ["aipod-spec-yaml-parser-runtime-compatible", "aipod-spec-artificer-yaml-render", "aipod-spec-git-mirror-url", "queue-submit-aipod-dry-run", "aipod-cli-help"] }; + return { name: "aipod-spec", tests: ["aipod-spec-yaml-parser-runtime-compatible", "aipod-spec-artificer-direct-ssh-render", "aipod-spec-git-mirror-url", "queue-submit-aipod-dry-run", "aipod-cli-help"] }; } finally { await new Promise((resolve) => server.server.close(() => resolve())); }