# v0.1 AipodSpec 规格 `AipodSpec` 是 AgentRun `v0.1` 的声明式 agent 装配规格。它把已有的 `backendProfile`、`executionPolicy.secretScope`、`ResourceBundleRef.kind="gitbundle"`、Queue task 和 Session turn 装配入口集中到 YAML 文件中,避免把某个 agent 的模型、SecretRef、gitbundle、skill 或 tool 写死在 manager、runner 或 CLI 源码里。 ## 设计边界 - `AipodSpec` 只声明装配意图,不保存 API key、SSH private key、token、`auth.json`、`config.toml` 或其他 Secret 明文。 - manager 通过 `/api/v1/aipod-specs` 对 YAML 做增删改查;默认目录为仓库 `config/aipods/`,可用 `AGENTRUN_AIPOD_SPEC_DIR` 覆盖。 - CLI 通过 `aipod-specs list|show|render|apply|delete` 管理规格,通过 `queue submit --aipod ` 或 `sessions turn --aipod ` 使用规格。 - `render` 只把规格展开为标准 Queue task / Session turn 输入,输出必须脱敏,只显示 SecretRef 名称、key、projection、gitbundle 摘要和 `valuesPrinted=false`。 - `AipodSpec` 不引入第二套 scheduler、runner、backend adapter 或 Code Queue;最终执行仍走 AgentRun Queue、Sessions、runner Job 和 Codex app-server stdio backend。 ## YAML 结构 最小结构: ```yaml apiVersion: agentrun.pikastech.local/v0.1 kind: AipodSpec metadata: name: Artificer spec: backendProfile: sub2api executionPolicy: sandbox: workspace-write approval: never timeoutMs: 1800000 network: enabled secretScope: allowCredentialEcho: false providerCredentials: - profile: sub2api secretRef: name: agentrun-v01-provider-sub2api keys: [auth.json, config.toml] resourceBundleRef: kind: gitbundle repoUrl: git@github.com:pikasTech/unidesk.git ref: master bundles: - subpath: .agents/skills targetPath: .agents/skills ``` 字段规则: - `apiVersion` 固定为 `agentrun.pikastech.local/v0.1`,`kind` 固定为 `AipodSpec`。 - `metadata.name` 是 CLI/API 查找名,允许大小写,但文件落盘名会归一为安全 YAML 文件名。 - `spec.backendProfile` 使用 AgentRun 已注册或动态的 Codex-compatible profile slug,例如 `codex`、`deepseek`、`minimax-m3`、`dsflash-go` 或 `sub2api`。 - `spec.model.model` 会展开为 command payload 的 `model` 字段;完整 `spec.model` 同时进入 `payload.modelConfig`,用于保留 `reasoningEffort` 等声明但不作为 Secret 输出。 - `spec.executionPolicy` 复用 run 的执行策略校验,且必须恰好包含一个匹配 `backendProfile` 的 provider credential SecretRef。 - `spec.resourceBundleRef` 复用 RuntimeAssembly 的 gitbundle 规则,可为 `null`,但需要注入 skill/tool 时必须使用 gitbundle。 - `spec.payloadDefaults` 与 CLI render 输入合并;用户 prompt 通过 `--prompt`、`--prompt-file` 或 `--prompt-stdin` 覆盖或补充。 ## Artificer 默认规格 仓库内置 `config/aipods/artificer.yaml`,名称为 `Artificer`。它的长期目标是承接 UniDesk 分布式开发任务: - 使用 `backendProfile=sub2api`,模型声明为 `gpt-5.5`,reasoning effort 为 `xhigh`。 - 通过 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`。 - 通过 `requiredSkills[]` 在 runner 启动 backend 前校验 `dad-dev` 与 UniDesk 关键 skills 已被 materialize;缺失时必须 `required-skill-unavailable`,不得使用模型默认 skill 猜测。 ## Git mirror `resourceBundleRef.gitMirror` 用于把 GitHub repo URL 改写为 G14 git mirror read URL,提高 runner checkout 的稳定性和速度。 规则: - `enabled` 缺省为 `true`;显式 `false` 时不改写。 - `baseUrl` 必须是无 credentials、query、fragment 的 HTTP(S) URL;未设置时 runner 使用 `AGENTRUN_GIT_MIRROR_BASE_URL`,再缺省为 `http://git-mirror-http.devops-infra.svc.cluster.local`。 - 支持 `git@github.com:owner/repo.git`、`ssh://git@github.com/owner/repo.git`、`ssh://git@ssh.github.com:443/owner/repo.git` 和 `https://github.com/owner/repo.git`。 - 非 GitHub URL 不改写,仍按原 `repoUrl` fetch。 - materialization event 必须输出 `repoUrl`、`fetchRepoUrl`、`mirrorUsed`、`mirrorBaseUrl`、requested ref/commit 和实际 commit;不得输出 credential 值。 ## Tool credential projection `toolCredentials[]` 支持两类 projection: - `env`:把 Secret key 作为环境变量注入 runner,例如 `UNIDESK_SSH_CLIENT_TOKEN`。 - `volume`:把 Secret keys 作为只读文件挂载到 `/home/agentrun/` 下,例如 GitHub SSH 的 `/home/agentrun/.ssh`。 约束: - `unidesk-ssh` 必须使用 env projection,且 env/key 都必须是 `UNIDESK_SSH_CLIENT_TOKEN`。 - volume projection 的 `mountPath` 必须位于 `/home/agentrun/` 下,不能包含 `..`。 - runner Job response、dry-run manifest、event 和日志只能显示 SecretRef 名称、key、projection kind 与 mount path,不得显示 Secret value。 ## API 与 CLI REST API: - `GET /api/v1/aipod-specs`:列出可用规格。 - `POST /api/v1/aipod-specs`:从 `{ yaml }` 或 `{ spec }` 创建/更新规格。 - `GET /api/v1/aipod-specs/:name`:查看规格和摘要。 - `PUT /api/v1/aipod-specs/:name`:按 URL 名称更新规格,URL name 必须匹配 `metadata.name`。 - `DELETE /api/v1/aipod-specs/:name`:删除规格文件。 - `POST /api/v1/aipod-specs/:name/render`:把规格和本次输入展开为 Queue task。 Artificer 依赖的 GitHub SSH Secret 由 `tool-credentials set-github-ssh` 单独 bootstrap。`AipodSpec` 只引用 SecretRef,不读取或保存 SSH private key。 CLI: ```bash ./scripts/agentrun aipod-specs list ./scripts/agentrun aipod-specs show Artificer ./scripts/agentrun aipod-specs render Artificer --prompt-stdin ./scripts/agentrun aipod-specs apply --yaml-stdin ./scripts/agentrun aipod-specs delete Artificer ./scripts/agentrun queue submit --aipod Artificer --prompt-stdin --idempotency-key ./scripts/agentrun sessions turn --aipod Artificer --prompt-stdin ./scripts/agentrun tool-credentials set-github-ssh --private-key-file --known-hosts-file [--config-file ] ``` 所有 mutating CLI 必须短返回 JSON;`--dry-run` 只输出 mutation plan 和确认命令,不写 manager。 ## 测试规格 - 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。 - A2:`queue submit --aipod Artificer --dry-run` 输出标准 `queue-submit-plan`,且 `idempotencyKey`、prompt 与 metadata 被保留。 - A3:GitHub URL 在启用 `gitMirror` 后改写到 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。