fix: 修复 runner Codex shell 工具环境
This commit is contained in:
@@ -4,6 +4,7 @@ import { backendProfileSpec } from "../common/backend-profiles.js";
|
||||
|
||||
const defaultBootRepoUrl = "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/agentrun.git";
|
||||
const defaultResourceBinPath = "/usr/local/bin";
|
||||
const defaultCodexShellSandbox = "danger-full-access";
|
||||
|
||||
export interface RunnerJobRenderOptions {
|
||||
run: RunRecord;
|
||||
@@ -177,6 +178,7 @@ function runnerEnv(options: RunnerJobRenderOptions, context: { namespace: string
|
||||
{ name: "AGENTRUN_RUNNER_ID", value: context.runnerId },
|
||||
{ name: "AGENTRUN_BACKEND_PROFILE", value: options.run.backendProfile },
|
||||
{ name: "AGENTRUN_EXECUTION_POLICY_JSON", value: JSON.stringify(options.run.executionPolicy) },
|
||||
{ name: "AGENTRUN_CODEX_SHELL_SANDBOX", value: codexShellSandbox(options.run.executionPolicy) },
|
||||
{ name: "AGENTRUN_SESSION_REF_JSON", value: JSON.stringify(options.run.sessionRef ?? null) },
|
||||
{ name: "AGENTRUN_RESOURCE_BUNDLE_JSON", value: JSON.stringify(options.run.resourceBundleRef ?? null) },
|
||||
{ name: "AGENTRUN_WORKSPACE_ROOT", value: "/home/agentrun/workspaces" },
|
||||
@@ -205,6 +207,11 @@ function runnerEnv(options: RunnerJobRenderOptions, context: { namespace: string
|
||||
];
|
||||
}
|
||||
|
||||
function codexShellSandbox(policy: ExecutionPolicy): string {
|
||||
if (policy.sandbox === "workspace-write") return defaultCodexShellSandbox;
|
||||
return policy.sandbox;
|
||||
}
|
||||
|
||||
function toolCredentialEnvVars(items: ToolCredentialProjection[]): JsonRecord[] {
|
||||
return items.map((item) => ({
|
||||
name: item.envName,
|
||||
|
||||
@@ -90,7 +90,7 @@ export async function materializeResourceBundle(resourceBundleRef: ResourceBundl
|
||||
};
|
||||
const defaultCheckout = await checkoutFor(defaultSource);
|
||||
const materializedBundles = await materializeGitBundles(workspacePath, resourceBundleRef, defaultSource, defaultCheckout, checkoutFor);
|
||||
const tools = await prepareGitBundleTools(workspacePath);
|
||||
const tools = await prepareGitBundleTools(workspacePath, env);
|
||||
const skills = await discoverGitBundleSkills(workspacePath);
|
||||
const prompts = await materializePromptRefs(defaultCheckout.checkoutPath, resourceBundleRef.promptRefs ?? []);
|
||||
const initialPrompt = assembleInitialPrompt(prompts.items, skills.items);
|
||||
@@ -193,28 +193,50 @@ function optionalNonEmpty(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
async function prepareGitBundleTools(workspacePath: string): Promise<{ binPath?: string; event: JsonRecord }> {
|
||||
const binPath = path.join(workspacePath, "tools");
|
||||
async function prepareGitBundleTools(workspacePath: string, env: NodeJS.ProcessEnv): Promise<{ binPath?: string; event: JsonRecord }> {
|
||||
const sourceBinPath = path.join(workspacePath, "tools");
|
||||
const installedBinPath = optionalNonEmpty(env.AGENTRUN_RESOURCE_BIN_PATH);
|
||||
const runtimeBinPath = installedBinPath ?? sourceBinPath;
|
||||
let entries;
|
||||
try {
|
||||
entries = await readdir(binPath, { withFileTypes: true });
|
||||
entries = await readdir(sourceBinPath, { withFileTypes: true });
|
||||
} catch (error) {
|
||||
if (error && typeof error === "object" && "code" in error && (error as { code?: unknown }).code === "ENOENT") return { event: { count: 0, names: [], binPath: null, valuesPrinted: false } };
|
||||
if (error && typeof error === "object" && "code" in error && (error as { code?: unknown }).code === "ENOENT") return { event: { count: 0, names: [], binPath: null, sourceBinPath: null, installedBinPath: null, installed: false, valuesPrinted: false } };
|
||||
throw error;
|
||||
}
|
||||
const names: string[] = [];
|
||||
const items: JsonRecord[] = [];
|
||||
if (installedBinPath) await mkdir(installedBinPath, { recursive: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isFile()) continue;
|
||||
const filePath = path.join(binPath, entry.name);
|
||||
const filePath = path.join(sourceBinPath, entry.name);
|
||||
const text = await readFile(filePath, "utf8");
|
||||
const firstLine = text.split(/\r?\n/u, 1)[0] ?? "";
|
||||
if (!firstLine.startsWith("#!")) continue;
|
||||
await chmod(filePath, 0o755);
|
||||
if (installedBinPath) {
|
||||
const targetPath = path.join(installedBinPath, entry.name);
|
||||
if (targetPath !== filePath) {
|
||||
await cp(filePath, targetPath, { force: true, dereference: false });
|
||||
await chmod(targetPath, 0o755);
|
||||
}
|
||||
}
|
||||
names.push(entry.name);
|
||||
items.push({ name: entry.name, sha256: sha256Text(text), bytes: Buffer.byteLength(text, "utf8"), shebang: firstLine.slice(0, 80), valuesPrinted: false });
|
||||
}
|
||||
return { binPath, event: { count: names.length, names, items, binPath: pathSummary(binPath), valuesPrinted: false } };
|
||||
return {
|
||||
...(names.length > 0 ? { binPath: runtimeBinPath } : {}),
|
||||
event: {
|
||||
count: names.length,
|
||||
names,
|
||||
items,
|
||||
binPath: names.length > 0 ? pathSummary(runtimeBinPath) : null,
|
||||
sourceBinPath: pathSummary(sourceBinPath),
|
||||
installedBinPath: installedBinPath ? pathSummary(installedBinPath) : null,
|
||||
installed: Boolean(installedBinPath && names.length > 0),
|
||||
valuesPrinted: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function materializePromptRefs(checkoutPath: string, refs: NonNullable<ResourceBundleRef["promptRefs"]>): Promise<{ items: MaterializedPromptRef[]; event: JsonRecord }> {
|
||||
|
||||
Reference in New Issue
Block a user