fix: Artificer 默认直连 SSH 拉取资源

This commit is contained in:
Codex
2026-06-10 18:47:46 +08:00
parent f7a3bbe3fe
commit 648975e4d8
3 changed files with 12 additions and 8 deletions
+1 -2
View File
@@ -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
+5 -3
View File
@@ -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/renderrender 结果包含 `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/renderrender 结果包含 `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 被保留。
- A3GitHub URL 在启用 `gitMirror` 后改写到 mirror base URL;非 GitHub URL 不改写。
- A3Artificer 默认 `gitMirror.enabled=false` 时 GitHub URL 保持 SSH fetch;显式启用 `gitMirror` GitHub URL 改写到 mirror base URL;非 GitHub URL 不改写。
- A4runner Job dry-run 支持 tool credential volume mount,并且 response/manifest/event 不泄漏 Secret 明文。
- A5`bun run check``bun run self-test` 必须覆盖 A1-A4。
+6 -3
View File
@@ -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 <name>")), true);
assert.equal(commands.some((item) => item.includes("queue submit --aipod <name>")), 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<void>((resolve) => server.server.close(() => resolve()));
}