diff --git a/skills/hwlab-code-agent/scripts/src/client.test.ts b/skills/hwlab-code-agent/scripts/src/client.test.ts new file mode 100644 index 00000000..51e3e6ed --- /dev/null +++ b/skills/hwlab-code-agent/scripts/src/client.test.ts @@ -0,0 +1,27 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { createAgentChatRequestBody, findRemovedWorkspaceFileInput } from "./client.ts"; + +test("direct helper agent chat body never sends legacy workspaceFiles", () => { + const body = createAgentChatRequestBody({ + message: "validate gitbundle direct helper payload", + providerProfile: "deepseek", + sessionId: "ses_test", + conversationId: "cnv_test", + projectId: "prj_test", + traceId: "trc_test" + }); + + assert.equal(body.shortConnection, true); + assert.equal(Object.hasOwn(body, "workspaceFiles"), false); + assert.equal(Object.hasOwn(body, "resourceWorkspaceFiles"), false); +}); + +test("direct helper rejects removed spec injection inputs", () => { + assert.equal(findRemovedWorkspaceFileInput({ "spec-path": ".hwlab/hwpod-spec.yaml" }, {}), "--spec-path"); + assert.equal(findRemovedWorkspaceFileInput({ specPath: ".hwlab/hwpod-spec.yaml" }, {}), "--specPath"); + assert.equal(findRemovedWorkspaceFileInput({}, { HWPOD_SPEC_CONTENT: "kind: Hwpod" }), "HWPOD_SPEC_CONTENT"); + assert.equal(findRemovedWorkspaceFileInput({}, { HWPOD_SPEC: "kind: Hwpod" }), "HWPOD_SPEC"); + assert.equal(findRemovedWorkspaceFileInput({}, {}), null); +}); diff --git a/skills/hwlab-code-agent/scripts/src/client.ts b/skills/hwlab-code-agent/scripts/src/client.ts index 090bc04d..7f34f3cc 100644 --- a/skills/hwlab-code-agent/scripts/src/client.ts +++ b/skills/hwlab-code-agent/scripts/src/client.ts @@ -4,7 +4,6 @@ * 遵循 cli-spec:配置从 config.json 单一来源 */ import { readFileSync } from "node:fs"; -import { existsSync } from "node:fs"; import path from "node:path"; // ---- config ---- @@ -45,35 +44,39 @@ function resolveProviderProfile(args: Record) { fail("provider_profile_required", `spawn requires --profile or ${INHERITED_PROVIDER_PROFILE_ENV}`); } -// ---- workspace files auto-inheritance ---- -type WorkspaceFile = { path: string; content: string; encoding: "utf8" }; +const REMOVED_WORKSPACE_FILE_ARGS = new Map([ + ["specPath", "--specPath"], + ["spec-path", "--spec-path"] +]); +const REMOVED_WORKSPACE_FILE_ENV = ["HWPOD_SPEC_CONTENT", "HWPOD_SPEC"]; -function collectWorkspaceFiles(args: Record): WorkspaceFile[] { - const files: WorkspaceFile[] = []; - const specPath = args.specPath; - - // 1. explicit --spec-path - if (specPath) { - if (!existsSync(specPath)) throw new Error(`spec file not found: ${specPath}`); - files.push({ path: ".hwlab/hwpod-spec.yaml", content: readFileSync(specPath, "utf-8"), encoding: "utf8" }); +export function findRemovedWorkspaceFileInput(args: Record, env: Record = process.env): string | null { + for (const [key, label] of REMOVED_WORKSPACE_FILE_ARGS.entries()) { + if (textValue(args[key])) return label; } - - // 2. auto-detect: .hwlab/hwpod-spec.yaml in CWD (casrun-injected) - const cwdSpec = ".hwlab/hwpod-spec.yaml"; - if (!specPath && existsSync(cwdSpec)) { - files.push({ path: cwdSpec, content: readFileSync(cwdSpec, "utf-8"), encoding: "utf8" }); + for (const name of REMOVED_WORKSPACE_FILE_ENV) { + if (textValue(env[name])) return name; } + return null; +} - // 3. env var HWPOD_SPEC_CONTENT (plain yaml or base64) - const envSpec = process.env.HWPOD_SPEC_CONTENT || process.env.HWPOD_SPEC; - if (!specPath && !existsSync(cwdSpec) && envSpec) { - const content = envSpec.startsWith("eyJ") || envSpec.startsWith("YXBp") - ? Buffer.from(envSpec, "base64").toString("utf-8") - : envSpec; - files.push({ path: ".hwlab/hwpod-spec.yaml", content, encoding: "utf8" }); - } - - return files; +export function createAgentChatRequestBody(input: { + message: string; + providerProfile: string; + sessionId: string; + conversationId: string; + projectId: string; + traceId: string; +}): Record { + return { + message: input.message, + providerProfile: input.providerProfile, + sessionId: input.sessionId, + conversationId: input.conversationId, + projectId: input.projectId, + traceId: input.traceId, + shortConnection: true + }; } function apiKey(): string { @@ -115,6 +118,10 @@ export async function spawn(args: Record): Promise): Promise 0 ? { workspaceFiles } : {}) }) + body: JSON.stringify(createAgentChatRequestBody({ message, providerProfile: profile, sessionId, conversationId, projectId, traceId })) }); const b = await r.json(); out({