fix: 支持 ResourceBundleRef workspaceFiles

This commit is contained in:
Codex
2026-06-06 17:59:05 +08:00
parent c320459deb
commit 7b3c0ea584
8 changed files with 108 additions and 10 deletions
+34
View File
@@ -62,6 +62,7 @@ export async function materializeResourceBundle(resourceBundleRef: ResourceBundl
const toolAliases = await materializeToolAliases(checkoutPath, resourceBundleRef.toolAliases ?? [], env);
const skills = await materializeSkillRefs(checkoutPath, workspacePath, resourceBundleRef.skillRefs ?? []);
const prompts = await materializePromptRefs(checkoutPath, resourceBundleRef.promptRefs ?? []);
const workspaceFiles = await materializeWorkspaceFiles(workspacePath, resourceBundleRef.workspaceFiles ?? []);
const initialPrompt = assembleInitialPrompt(prompts.items, skills.items);
return {
workspacePath,
@@ -81,6 +82,7 @@ export async function materializeResourceBundle(resourceBundleRef: ResourceBundl
toolAliases: toolAliases.event,
skillRefs: skills.event,
promptRefs: prompts.event,
workspaceFiles: workspaceFiles.event,
initialPrompt: initialPrompt?.summary ?? { available: false, bytes: 0, sha256: null, promptRefCount: prompts.items.length, skillRefCount: skills.items.length, valuesPrinted: false },
valuesPrinted: false,
},
@@ -184,6 +186,31 @@ async function materializeSkillRefs(checkoutPath: string, workspacePath: string,
};
}
async function materializeWorkspaceFiles(workspacePath: string, files: NonNullable<ResourceBundleRef["workspaceFiles"]>): Promise<{ event: JsonRecord }> {
if (files.length === 0) return { event: { count: 0, materializedCount: 0, items: [], totalBytes: 0, valuesPrinted: false } };
const eventItems: JsonRecord[] = [];
let totalBytes = 0;
for (const file of files) {
const target = resolveWorkspaceFilePath(workspacePath, file.path, `workspaceFiles.${file.path}.path`);
const content = file.content;
const bytes = Buffer.byteLength(content, "utf8");
await mkdir(path.dirname(target), { recursive: true });
await writeFile(target, content, "utf8");
totalBytes += bytes;
eventItems.push({ path: file.path, encoding: file.encoding ?? "utf8", status: "materialized", bytes, sha256: sha256Text(content), valuesPrinted: false });
}
return {
event: {
count: files.length,
materializedCount: eventItems.length,
paths: eventItems.map((item) => item.path),
items: eventItems,
totalBytes,
valuesPrinted: false,
},
};
}
function assembleInitialPrompt(promptRefs: MaterializedPromptRef[], skillRefs: MaterializedSkillRef[]): InitialPromptAssembly | undefined {
if (promptRefs.length === 0 && skillRefs.length === 0) return undefined;
const sections: string[] = [
@@ -293,6 +320,13 @@ function resolveBundlePath(checkoutPath: string, relativePath: string, fieldName
return resolved;
}
function resolveWorkspaceFilePath(workspacePath: string, relativePath: string, fieldName: string): string {
const resolved = path.resolve(workspacePath, relativePath);
const root = path.resolve(workspacePath);
if (resolved === root || !resolved.startsWith(`${root}${path.sep}`)) throw new AgentRunError("schema-invalid", `${fieldName} escaped workspace`, { httpStatus: 400 });
return resolved;
}
function shellArg(value: string): string {
return `'${value.replace(/'/gu, `'"'"'`)}'`;
}