From 6d1b1fd7ea2f5d7b761ee4f1d8c8c8ee2f8ad680 Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Mon, 8 Jun 2026 08:18:13 +0800 Subject: [PATCH] code-agent: inherit child profile via env --- internal/cloud/code-agent-agentrun-adapter.ts | 14 +++++++---- skills/hwlab-code-agent/SKILL.md | 13 +++++++++- skills/hwlab-code-agent/config.json | 1 - .../scripts/hwlab-code-agent-cli.ts | 2 +- skills/hwlab-code-agent/scripts/src/client.ts | 24 ++++++++++++++++--- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/internal/cloud/code-agent-agentrun-adapter.ts b/internal/cloud/code-agent-agentrun-adapter.ts index 08e2fa4d..1c0ed961 100644 --- a/internal/cloud/code-agent-agentrun-adapter.ts +++ b/internal/cloud/code-agent-agentrun-adapter.ts @@ -297,7 +297,7 @@ export async function submitAgentRunChatTurn({ params = {}, options = {}, traceI }); let runnerJob = null; try { - const runnerJobInput = buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, toolCapabilities }); + const runnerJobInput = buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, toolCapabilities, backendProfile }); runnerJob = await agentRunJson(fetchImpl, managerUrl, `/api/v1/runs/${encodeURIComponent(reusable.mapping.runId)}/runner-jobs`, { method: "POST", body: runnerJobInput, @@ -395,7 +395,7 @@ export async function submitAgentRunChatTurn({ params = {}, options = {}, traceI message: "AgentRun command " + commandId + " created; hwlab-cloud-api will start a runner Job explicitly without relying on scheduler automation.", runId, commandId, backendProfile, waitingFor: "agentrun-runner-job-create", valuesPrinted: false, }); - const runnerJobInput = buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, toolCapabilities }); + const runnerJobInput = buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, toolCapabilities, backendProfile }); try { runnerJob = await agentRunJson(fetchImpl, managerUrl, "/api/v1/runs/" + encodeURIComponent(runId) + "/runner-jobs", { method: "POST", body: runnerJobInput, timeoutMs }); } catch (error) { @@ -933,8 +933,8 @@ async function resolveOwnerApiKey({ params, options, now }) { if (!key) return ""; return text(key.displaySecret ?? ""); } -function buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, toolCapabilities = null }) { - const baseTransient = buildAgentRunTransientEnv(env); +function buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, toolCapabilities = null, backendProfile }) { + const baseTransient = buildAgentRunTransientEnv(env, { providerProfile: backendProfile, parentTraceId: traceId }); const hwpodAllowed = toolCapabilityAllowed(toolCapabilities, "hwpod"); const transientEnv = ownerApiKey && hwpodAllowed ? baseTransient.concat([{ name: "HWLAB_API_KEY", value: ownerApiKey, sensitive: true }]) @@ -953,7 +953,9 @@ function buildAgentRunRunnerJobInput({ env, traceId, commandId, ownerApiKey, too }; } -function buildAgentRunTransientEnv(env = process.env) { +function buildAgentRunTransientEnv(env = process.env, options = {}) { + const providerProfile = firstNonEmpty(options.providerProfile); + const parentTraceId = firstNonEmpty(options.parentTraceId); const entries = []; for (const name of [ "HWLAB_RUNTIME_API_URL", @@ -967,6 +969,8 @@ function buildAgentRunTransientEnv(env = process.env) { const value = firstNonEmpty(env[name]); if (value) entries.push({ name, value, sensitive: false }); } + if (providerProfile) entries.push({ name: "HWLAB_CODE_AGENT_PROVIDER_PROFILE", value: providerProfile, sensitive: false }); + if (parentTraceId) entries.push({ name: "HWLAB_CODE_AGENT_PARENT_TRACE_ID", value: parentTraceId, sensitive: false }); return entries; } diff --git a/skills/hwlab-code-agent/SKILL.md b/skills/hwlab-code-agent/SKILL.md index fec14273..1317b77a 100644 --- a/skills/hwlab-code-agent/SKILL.md +++ b/skills/hwlab-code-agent/SKILL.md @@ -26,7 +26,9 @@ bun scripts/hwlab-code-agent-cli.ts result bun scripts/hwlab-code-agent-cli.ts trace [--full] ``` -输出均为 JSON。`spawn` 创建 session + 提交 prompt,立即返回 `sessionId` + `traceId`。`poll` 阻塞轮询至 terminal 或超时。 +`spawn` 的 profile 解析只认两种来源:显式 `--profile`,或环境变量 `HWLAB_CODE_AGENT_PROVIDER_PROFILE`。未提供时直接返回 `provider_profile_required`,不再静默回落 `deepseek`。 + +输出均为 JSON。`spawn` 创建 session + 提交 prompt,立即返回 `sessionId` + `traceId`,并暴露 `resolvedProviderProfile`、`profileSource`、`parentTraceId`。`poll` 阻塞轮询至 terminal 或超时。 ### hwpod spec 自动继承 @@ -45,6 +47,15 @@ caserun 注入 .hwlab/hwpod-spec.yaml 到 Leader workspace -> Coder/Reviewer 拿到相同 spec ``` +provider profile 继承链: + +``` +外层 AgentRun runner env 注入 HWLAB_CODE_AGENT_PROVIDER_PROFILE=当前 providerProfile + -> Leader 调用 hwlab-code-agent spawn 且未显式传 --profile + -> spawn 从同一环境变量继承 profile + -> 子 agent 与父 agent 使用同一个 providerProfile +``` + --- ## 外部管理 CLI(G14 workspace 透传) diff --git a/skills/hwlab-code-agent/config.json b/skills/hwlab-code-agent/config.json index 3b762a62..404265e1 100644 --- a/skills/hwlab-code-agent/config.json +++ b/skills/hwlab-code-agent/config.json @@ -1,6 +1,5 @@ { "apiBaseUrl": "http://74.48.78.17:19666", - "defaultProviderProfile": "deepseek", "defaultProjectId": "prj_hwpod_workbench", "defaultPollTimeoutMs": 300000 } diff --git a/skills/hwlab-code-agent/scripts/hwlab-code-agent-cli.ts b/skills/hwlab-code-agent/scripts/hwlab-code-agent-cli.ts index 2a0dc037..8543870a 100644 --- a/skills/hwlab-code-agent/scripts/hwlab-code-agent-cli.ts +++ b/skills/hwlab-code-agent/scripts/hwlab-code-agent-cli.ts @@ -67,7 +67,7 @@ async function main() { process.stderr.write(JSON.stringify({ ok: false, usage: { - spawn: "bun scripts/hwlab-code-agent-cli.ts spawn --message '...' [--profile deepseek]", + spawn: "HWLAB_CODE_AGENT_PROVIDER_PROFILE=PROFILE bun scripts/hwlab-code-agent-cli.ts spawn --message '...' [--profile PROFILE]", poll: "bun scripts/hwlab-code-agent-cli.ts poll [--timeout 600000]", result: "bun scripts/hwlab-code-agent-cli.ts result ", trace: "bun scripts/hwlab-code-agent-cli.ts trace [--full]" diff --git a/skills/hwlab-code-agent/scripts/src/client.ts b/skills/hwlab-code-agent/scripts/src/client.ts index d1cf2d0e..090bc04d 100644 --- a/skills/hwlab-code-agent/scripts/src/client.ts +++ b/skills/hwlab-code-agent/scripts/src/client.ts @@ -13,11 +13,13 @@ const configPath = path.join(SKILL_ROOT, "config.json"); interface Config { apiBaseUrl: string; - defaultProviderProfile: string; defaultProjectId: string; defaultPollTimeoutMs: number; } +const INHERITED_PROVIDER_PROFILE_ENV = "HWLAB_CODE_AGENT_PROVIDER_PROFILE"; +const PARENT_TRACE_ID_ENV = "HWLAB_CODE_AGENT_PARENT_TRACE_ID"; + let _cfg: Config | null = null; function config(): Config { if (!_cfg) { @@ -27,11 +29,22 @@ function config(): Config { throw new Error(`hwlab-code-agent: failed to load config from ${configPath}`); } if (!_cfg.apiBaseUrl) throw new Error("hwlab-code-agent: config.apiBaseUrl is required"); - if (!_cfg.defaultProviderProfile) throw new Error("hwlab-code-agent: config.defaultProviderProfile is required"); } return _cfg; } +function textValue(value: string | undefined): string { + return String(value ?? "").trim(); +} + +function resolveProviderProfile(args: Record) { + const explicit = textValue(args.profile || args.providerProfile); + if (explicit) return { profile: explicit, source: "explicit" }; + const inherited = textValue(process.env[INHERITED_PROVIDER_PROFILE_ENV]); + if (inherited) return { profile: inherited, source: "env" }; + fail("provider_profile_required", `spawn requires --profile or ${INHERITED_PROVIDER_PROFILE_ENV}`); +} + // ---- workspace files auto-inheritance ---- type WorkspaceFile = { path: string; content: string; encoding: "utf8" }; @@ -97,7 +110,8 @@ export interface SpawnResult { export async function spawn(args: Record): Promise { const cfg = config(); - const profile = args.profile || cfg.defaultProviderProfile; + const resolvedProfile = resolveProviderProfile(args); + const profile = resolvedProfile.profile; const projectId = args.projectId || cfg.defaultProjectId; const message = args.message || (args.messageFile ? readFileSync(args.messageFile, "utf-8") : null); if (!message) fail("message_required", "--message or --message-file required"); @@ -130,6 +144,10 @@ export async function spawn(args: Record): Promise