fix: honor AgentRun durable dispatch boundary
This commit is contained in:
@@ -85,6 +85,20 @@ const AGENTRUN_PROVIDER_TRACE_WIRE_API = "agentrun-v01-command-result";
|
||||
const THREAD_CONTINUITY_POLICY = "hwlab-agentrun-v01-reuse-runner-thread";
|
||||
const SESSION_POLICY_RUN_LOCAL = "hwlab-agentrun-v01-session-runner-reuse";
|
||||
const TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "blocked", "cancelled", "canceled"]);
|
||||
const AGENTRUN_DURABLE_TRANSIENT_ENV_RESERVED = new Set([
|
||||
"AGENTRUN_API_KEY",
|
||||
"AUTH_PASSWORD",
|
||||
"CODEX_API_KEY",
|
||||
"CODEX_HOME",
|
||||
"GH_TOKEN",
|
||||
"GITHUB_TOKEN",
|
||||
"HOME",
|
||||
"OPENAI_API_KEY",
|
||||
"PROVIDER_TOKEN",
|
||||
"UNIDESK_AUTH_PASSWORD",
|
||||
"UNIDESK_PROVIDER_TOKEN",
|
||||
"UNIDESK_SSH_CLIENT_TOKEN"
|
||||
]);
|
||||
const HWLAB_RESOURCE_GIT_BUNDLES = Object.freeze([
|
||||
Object.freeze({ name: "hwlab-tools", subpath: "tools", target_path: "tools" }),
|
||||
Object.freeze({ name: "hwlab-agent-skills", subpath: "skills", target_path: ".agents/skills" })
|
||||
@@ -1599,22 +1613,47 @@ function buildAgentRunDurableDispatchInput({ env, traceId, backendProfile }) {
|
||||
const runtimeAuthority = requireAgentRunRuntimeAuthority(env);
|
||||
const baseTransient = buildAgentRunTransientEnv(env, { providerProfile: backendProfile, parentTraceId: traceId });
|
||||
assertAgentRunTransientRuntimeAuthority(baseTransient, runtimeAuthority);
|
||||
if (baseTransient.some((entry) => entry?.sensitive === true)) {
|
||||
throw adapterError("agentrun_durable_dispatch_secret_forbidden", "AgentRun durable dispatch input must not persist sensitive transient environment values.");
|
||||
}
|
||||
assertAgentRunDurableTransientEnv(baseTransient);
|
||||
return {
|
||||
idempotencyKey: traceId,
|
||||
namespace: firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE, env.AGENTRUN_RUNTIME_NAMESPACE, DEFAULT_RUNNER_NAMESPACE),
|
||||
...(firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_RUNNER_IMAGE, env.AGENTRUN_RUNNER_IMAGE)
|
||||
? { image: firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_RUNNER_IMAGE, env.AGENTRUN_RUNNER_IMAGE) }
|
||||
: {}),
|
||||
...(firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_RUNNER_SERVICE_ACCOUNT, env.AGENTRUN_RUNNER_SERVICE_ACCOUNT)
|
||||
? { serviceAccountName: firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_RUNNER_SERVICE_ACCOUNT, env.AGENTRUN_RUNNER_SERVICE_ACCOUNT) }
|
||||
: {}),
|
||||
...(baseTransient.length > 0 ? { transientEnv: baseTransient } : {})
|
||||
};
|
||||
}
|
||||
|
||||
function assertAgentRunDurableTransientEnv(entries) {
|
||||
const seen = new Set();
|
||||
for (const entry of Array.isArray(entries) ? entries : []) {
|
||||
const name = firstNonEmpty(entry?.name);
|
||||
const value = firstNonEmpty(entry?.value);
|
||||
if (!/^[A-Z_][A-Z0-9_]*$/u.test(name) || !value || seen.has(name)) {
|
||||
throw adapterError("agentrun_durable_dispatch_transient_env_invalid", "AgentRun durable dispatch transient environment must contain unique non-empty environment entries.");
|
||||
}
|
||||
if (entry?.sensitive === true) {
|
||||
throw adapterError("agentrun_durable_dispatch_secret_forbidden", "AgentRun durable dispatch input must not persist sensitive transient environment values.");
|
||||
}
|
||||
if (agentRunReservedTransientEnvName(name)) {
|
||||
throw adapterError("agentrun_durable_dispatch_transient_env_reserved", `AgentRun durable dispatch transient environment cannot override runtime-owned ${name}.`);
|
||||
}
|
||||
seen.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
function agentRunReservedTransientEnvName(name) {
|
||||
return name.startsWith("AGENTRUN_")
|
||||
|| name.startsWith("KUBERNETES_")
|
||||
|| AGENTRUN_DURABLE_TRANSIENT_ENV_RESERVED.has(name)
|
||||
|| new Set([
|
||||
"HTTP_PROXY",
|
||||
"HTTPS_PROXY",
|
||||
"ALL_PROXY",
|
||||
"NO_PROXY",
|
||||
"GIT_SSH_COMMAND",
|
||||
"OTEL_SERVICE_NAME",
|
||||
"OTEL_EXPORTER_OTLP_ENDPOINT",
|
||||
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
|
||||
]).has(name);
|
||||
}
|
||||
|
||||
function requireAgentRunDurableDispatchIntent(value) {
|
||||
const intent = value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
||||
const admittedStates = new Set(["pending", "dispatching", "retry", "dispatched"]);
|
||||
|
||||
Reference in New Issue
Block a user