fix: remove direct helper workspaceFiles injection
This commit is contained in:
@@ -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);
|
||||
});
|
||||
@@ -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<string, string | undefined>) {
|
||||
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<string, string | undefined>): 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<string, string | undefined>, env: Record<string, string | undefined> = 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<string, unknown> {
|
||||
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<string, string | undefined>): Promise<v
|
||||
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");
|
||||
const removedWorkspaceFileInput = findRemovedWorkspaceFileInput(args);
|
||||
if (removedWorkspaceFileInput) {
|
||||
fail("legacy_workspace_files_removed", `${removedWorkspaceFileInput} was removed; use AgentRun ResourceBundleRef kind=gitbundle with bundles[]`);
|
||||
}
|
||||
|
||||
// session
|
||||
let sessionId = args.sessionId || "";
|
||||
@@ -133,12 +140,11 @@ export async function spawn(args: Record<string, string | undefined>): Promise<v
|
||||
if (!conversationId) conversationId = `cnv_cli_${Date.now()}`;
|
||||
|
||||
// submit
|
||||
const workspaceFiles = collectWorkspaceFiles(args);
|
||||
const traceId = `trc_${profile}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
||||
const r = await fetch(`${cfg.apiBaseUrl}/v1/agent/chat`, {
|
||||
method: "POST",
|
||||
headers: { ...authHeaders(), "prefer": "respond-async", "x-trace-id": traceId, "x-hwlab-short-connection": "1" },
|
||||
body: JSON.stringify({ message, providerProfile: profile, sessionId, conversationId, projectId, traceId, shortConnection: true, ...(workspaceFiles.length > 0 ? { workspaceFiles } : {}) })
|
||||
body: JSON.stringify(createAgentChatRequestBody({ message, providerProfile: profile, sessionId, conversationId, projectId, traceId }))
|
||||
});
|
||||
const b = await r.json();
|
||||
out({
|
||||
|
||||
Reference in New Issue
Block a user