6a8e9b3d79
- submitAgentRunChatTurn resolves owner user API key via accessController.store.findActiveDefaultApiKeyForUser - buildAgentRunRunnerJobInput accepts ownerApiKey; when present, removes HWLAB_DEVICE_POD_API_KEY and adds HWLAB_API_KEY as sensitive - buildAgentRunTransientEnv no longer emits HWLAB_DEVICE_POD_API_KEY - codex-stdio child env now reads HWLAB_API_KEY (not HWLAB_DEVICE_POD_API_KEY) - server-code-agent-http codeAgentAuthEnv looks up user default API key; URL env vars still set unconditionally - tests: code-agent-session-registry Codex child env carries only device-pod API key now checks HWLAB_API_KEY - tests: server-agent-chat delegates v0.2 turns removes HWLAB_DEVICE_POD_API_KEY assertion - 58 pass / 4 pre-existing fail
79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
|
|
const DEFAULT_BODY_LIMIT_BYTES = 1024 * 1024;
|
|
|
|
export function readBody(request, limitBytes = DEFAULT_BODY_LIMIT_BYTES) {
|
|
const limit = Number.isInteger(limitBytes) && limitBytes > 0 ? limitBytes : DEFAULT_BODY_LIMIT_BYTES;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
let body = "";
|
|
request.setEncoding("utf8");
|
|
|
|
request.on("data", (chunk) => {
|
|
body += chunk;
|
|
if (Buffer.byteLength(body, "utf8") > limit) {
|
|
request.destroy(new Error(`request body exceeds ${limit} bytes`));
|
|
}
|
|
});
|
|
|
|
request.on("end", () => resolve(body));
|
|
request.on("error", reject);
|
|
});
|
|
}
|
|
|
|
export function sendJson(response, statusCode, body) {
|
|
response.writeHead(statusCode, {
|
|
"content-type": "application/json; charset=utf-8",
|
|
"cache-control": "no-store"
|
|
});
|
|
response.end(JSON.stringify(body) + "\n");
|
|
}
|
|
|
|
export function getHeader(request, name) {
|
|
const value = request.headers[name.toLowerCase()];
|
|
if (Array.isArray(value)) return value[0];
|
|
return value;
|
|
}
|
|
|
|
export function firstHeaderValue(request, name) {
|
|
return getHeader(request, name);
|
|
}
|
|
|
|
export function truthyFlag(value) {
|
|
return /^(?:1|true|yes|on|enabled)$/iu.test(String(value ?? "").trim());
|
|
}
|
|
|
|
export function safeTraceId(value) {
|
|
const text = String(value ?? "").trim();
|
|
return /^trc_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
|
|
}
|
|
|
|
export function safeSessionId(value) {
|
|
const text = String(value ?? "").trim();
|
|
return /^ses_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
|
|
}
|
|
|
|
export function safeConversationId(value) {
|
|
const text = String(value ?? "").trim();
|
|
return /^cnv_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
|
|
}
|
|
|
|
export function safeOpaqueId(value) {
|
|
const text = String(value ?? "").trim();
|
|
return /^[A-Za-z0-9_.:-]{3,180}$/u.test(text) ? text : null;
|
|
}
|
|
|
|
export function parsePositiveInteger(value, fallback) {
|
|
const parsed = Number.parseInt(value ?? "", 10);
|
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
}
|
|
|
|
export function positiveInteger(value, fallback) {
|
|
const parsed = Number.parseInt(value ?? "", 10);
|
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
}
|
|
|
|
export function text(value) {
|
|
if (value === null || value === undefined) return "";
|
|
return String(value);
|
|
}
|