@inhuman.tools/harness 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compact.prompt +12 -2
- package/dist/builtin-tools/catalog-entry.d.ts.map +1 -1
- package/dist/builtin-tools/catalog-entry.js +1 -0
- package/dist/builtin-tools/catalog-entry.js.map +1 -1
- package/dist/builtin-tools/index.d.ts +1 -2
- package/dist/builtin-tools/index.d.ts.map +1 -1
- package/dist/builtin-tools/index.js +1 -2
- package/dist/builtin-tools/index.js.map +1 -1
- package/dist/builtin-tools/metadata/context-need.d.ts +1 -0
- package/dist/builtin-tools/metadata/context-need.d.ts.map +1 -1
- package/dist/builtin-tools/metadata/context-need.js +13 -6
- package/dist/builtin-tools/metadata/context-need.js.map +1 -1
- package/dist/builtin-tools/metadata/context-recall.d.ts +1 -5
- package/dist/builtin-tools/metadata/context-recall.d.ts.map +1 -1
- package/dist/builtin-tools/metadata/context-recall.js +10 -7
- package/dist/builtin-tools/metadata/context-recall.js.map +1 -1
- package/dist/builtin-tools/metadata/update-metadata.d.ts +1 -0
- package/dist/builtin-tools/metadata/update-metadata.d.ts.map +1 -1
- package/dist/builtin-tools/metadata/update-metadata.js +12 -12
- package/dist/builtin-tools/metadata/update-metadata.js.map +1 -1
- package/dist/builtin-tools/named-agents/agent-catalog.d.ts.map +1 -1
- package/dist/builtin-tools/named-agents/agent-catalog.js +9 -9
- package/dist/builtin-tools/named-agents/agent-catalog.js.map +1 -1
- package/dist/builtin-tools/named-agents/agent-stdlib.d.ts.map +1 -1
- package/dist/builtin-tools/named-agents/agent-stdlib.js +2 -0
- package/dist/builtin-tools/named-agents/agent-stdlib.js.map +1 -1
- package/dist/builtin-tools/schemas/tool-result.d.ts +2 -0
- package/dist/builtin-tools/schemas/tool-result.d.ts.map +1 -1
- package/dist/builtin-tools/schemas/tool-result.js +2 -0
- package/dist/builtin-tools/schemas/tool-result.js.map +1 -1
- package/dist/builtin-tools/shell/job-stop.d.ts +1 -0
- package/dist/builtin-tools/shell/job-stop.d.ts.map +1 -1
- package/dist/builtin-tools/shell/shell-tool.d.ts +1 -0
- package/dist/builtin-tools/shell/shell-tool.d.ts.map +1 -1
- package/dist/builtin-tools/toolkit/dist-tools.d.ts +1 -0
- package/dist/builtin-tools/toolkit/dist-tools.d.ts.map +1 -1
- package/dist/builtin-tools/toolkit/dist-tools.js +1 -0
- package/dist/builtin-tools/toolkit/dist-tools.js.map +1 -1
- package/dist/connections/adopt.d.ts +2 -0
- package/dist/connections/adopt.d.ts.map +1 -1
- package/dist/connections/adopt.js.map +1 -1
- package/dist/connections/index.d.ts +1 -1
- package/dist/connections/index.d.ts.map +1 -1
- package/dist/extensions/behavior.d.ts.map +1 -1
- package/dist/extensions/behavior.js +17 -4
- package/dist/extensions/behavior.js.map +1 -1
- package/dist/extensions/consent.d.ts +0 -68
- package/dist/extensions/consent.d.ts.map +1 -1
- package/dist/extensions/consent.js +0 -69
- package/dist/extensions/consent.js.map +1 -1
- package/dist/extensions/contributions.d.ts.map +1 -1
- package/dist/extensions/contributions.js +1 -0
- package/dist/extensions/contributions.js.map +1 -1
- package/dist/extensions/dispatch.d.ts +1 -9
- package/dist/extensions/dispatch.d.ts.map +1 -1
- package/dist/extensions/dispatch.js +5 -7
- package/dist/extensions/dispatch.js.map +1 -1
- package/dist/extensions/eval.d.ts.map +1 -1
- package/dist/extensions/eval.js +2 -0
- package/dist/extensions/eval.js.map +1 -1
- package/dist/extensions/hook-deadline.d.ts +28 -0
- package/dist/extensions/hook-deadline.d.ts.map +1 -0
- package/dist/extensions/hook-deadline.js +72 -0
- package/dist/extensions/hook-deadline.js.map +1 -0
- package/dist/extensions/host.d.ts +2 -0
- package/dist/extensions/host.d.ts.map +1 -1
- package/dist/extensions/host.js +15 -0
- package/dist/extensions/host.js.map +1 -1
- package/dist/extensions/inventory.d.ts +9 -0
- package/dist/extensions/inventory.d.ts.map +1 -1
- package/dist/extensions/inventory.js +15 -1
- package/dist/extensions/inventory.js.map +1 -1
- package/dist/extensions/notes.d.ts +1 -0
- package/dist/extensions/notes.d.ts.map +1 -1
- package/dist/extensions/notes.js +1 -0
- package/dist/extensions/notes.js.map +1 -1
- package/dist/extensions/schemas/bot-definition.d.ts +1 -1
- package/dist/extensions/schemas/bot-definition.d.ts.map +1 -1
- package/dist/extensions/schemas/plugin-manifest.d.ts +4 -4
- package/dist/extensions/schemas/plugin-manifest.d.ts.map +1 -1
- package/dist/extensions/schemas/plugin-manifest.js +13 -1
- package/dist/extensions/schemas/plugin-manifest.js.map +1 -1
- package/dist/extensions/state.d.ts.map +1 -1
- package/dist/extensions/state.js +5 -0
- package/dist/extensions/state.js.map +1 -1
- package/dist/extensions/value.d.ts +4 -0
- package/dist/extensions/value.d.ts.map +1 -1
- package/dist/extensions/value.js.map +1 -1
- package/dist/protocol/schemas/health.d.ts +1 -3
- package/dist/protocol/schemas/health.d.ts.map +1 -1
- package/dist/protocol/schemas/health.js.map +1 -1
- package/dist/protocol/schemas/identity.d.ts +0 -4
- package/dist/protocol/schemas/identity.d.ts.map +1 -1
- package/dist/protocol/schemas/identity.js.map +1 -1
- package/dist/protocol/schemas/loss.d.ts +0 -2
- package/dist/protocol/schemas/loss.d.ts.map +1 -1
- package/dist/protocol/schemas/loss.js.map +1 -1
- package/dist/protocol/schemas/message.d.ts +0 -1
- package/dist/protocol/schemas/message.d.ts.map +1 -1
- package/dist/protocol/supervision/loss.d.ts +0 -1
- package/dist/protocol/supervision/loss.d.ts.map +1 -1
- package/dist/protocol/supervision/loss.js +0 -3
- package/dist/protocol/supervision/loss.js.map +1 -1
- package/dist/providers/auth/index.d.ts +2 -2
- package/dist/providers/auth/index.d.ts.map +1 -1
- package/dist/providers/auth/index.js +2 -2
- package/dist/providers/auth/index.js.map +1 -1
- package/dist/providers/auth/loopback.d.ts +0 -2
- package/dist/providers/auth/loopback.d.ts.map +1 -1
- package/dist/providers/auth/loopback.js.map +1 -1
- package/dist/providers/chatgpt/connection.d.ts +1 -0
- package/dist/providers/chatgpt/connection.d.ts.map +1 -1
- package/dist/providers/chatgpt/connection.js +1 -1
- package/dist/providers/chatgpt/connection.js.map +1 -1
- package/dist/providers/grok/connection.d.ts +2 -1
- package/dist/providers/grok/connection.d.ts.map +1 -1
- package/dist/providers/grok/connection.js +1 -1
- package/dist/providers/grok/connection.js.map +1 -1
- package/dist/providers/mcp/fetch.d.ts.map +1 -1
- package/dist/providers/mcp/fetch.js +2 -6
- package/dist/providers/mcp/fetch.js.map +1 -1
- package/dist/providers/nous/driver.d.ts +1 -0
- package/dist/providers/nous/driver.d.ts.map +1 -1
- package/dist/providers/openai-compat/actor.d.ts.map +1 -1
- package/dist/providers/openai-compat/actor.js +167 -39
- package/dist/providers/openai-compat/actor.js.map +1 -1
- package/dist/providers/openai-compat/adopt.d.ts +2 -0
- package/dist/providers/openai-compat/adopt.d.ts.map +1 -1
- package/dist/providers/openai-compat/adopt.js.map +1 -1
- package/dist/providers/openai-compat/connection.d.ts +9 -2
- package/dist/providers/openai-compat/connection.d.ts.map +1 -1
- package/dist/providers/openai-compat/connection.js +35 -27
- package/dist/providers/openai-compat/connection.js.map +1 -1
- package/dist/providers/openai-compat/fetch-types.d.ts.map +1 -1
- package/dist/providers/openai-compat/fetch-types.js +2 -6
- package/dist/providers/openai-compat/fetch-types.js.map +1 -1
- package/dist/providers/openai-compat/index.d.ts +2 -2
- package/dist/providers/openai-compat/index.d.ts.map +1 -1
- package/dist/providers/openai-compat/index.js +2 -2
- package/dist/providers/openai-compat/index.js.map +1 -1
- package/dist/providers/openai-compat/model-capabilities.d.ts +7 -0
- package/dist/providers/openai-compat/model-capabilities.d.ts.map +1 -0
- package/dist/providers/openai-compat/model-capabilities.js +24 -0
- package/dist/providers/openai-compat/model-capabilities.js.map +1 -0
- package/dist/providers/openai-compat/schema.d.ts +1 -1
- package/dist/providers/web/registrations/ids.d.ts +0 -2
- package/dist/providers/web/registrations/ids.d.ts.map +1 -1
- package/dist/providers/web/registrations/ids.js +0 -1
- package/dist/providers/web/registrations/ids.js.map +1 -1
- package/dist/runtime/bot-mcp.d.ts.map +1 -1
- package/dist/runtime/bot-mcp.js +1 -4
- package/dist/runtime/bot-mcp.js.map +1 -1
- package/dist/runtime/intent-recovery.d.ts +3 -20
- package/dist/runtime/intent-recovery.d.ts.map +1 -1
- package/dist/runtime/intent-recovery.js +1 -122
- package/dist/runtime/intent-recovery.js.map +1 -1
- package/dist/server/ask-answer.d.ts.map +1 -1
- package/dist/server/ask-answer.js +3 -3
- package/dist/server/ask-answer.js.map +1 -1
- package/dist/server/daemon/kernel/KernelDaemon.d.ts +4 -0
- package/dist/server/daemon/kernel/KernelDaemon.d.ts.map +1 -1
- package/dist/server/daemon/kernel/KernelDaemon.js +100 -40
- package/dist/server/daemon/kernel/KernelDaemon.js.map +1 -1
- package/dist/server/daemon/kernel/completion-catalog.d.ts +8 -0
- package/dist/server/daemon/kernel/completion-catalog.d.ts.map +1 -1
- package/dist/server/daemon/kernel/completion-catalog.js +16 -0
- package/dist/server/daemon/kernel/completion-catalog.js.map +1 -1
- package/dist/server/daemon/kernel/fs-reflection/reflectKernel.d.ts.map +1 -1
- package/dist/server/daemon/kernel/fs-reflection/reflectKernel.js +47 -1
- package/dist/server/daemon/kernel/fs-reflection/reflectKernel.js.map +1 -1
- package/dist/server/daemon/kernel/glance-ask-line.d.ts +1 -6
- package/dist/server/daemon/kernel/glance-ask-line.d.ts.map +1 -1
- package/dist/server/daemon/kernel/glance-ask-line.js +1 -35
- package/dist/server/daemon/kernel/glance-ask-line.js.map +1 -1
- package/dist/server/daemon/kernel/settings-files.d.ts +1 -1
- package/dist/server/daemon/kernel/settings-files.d.ts.map +1 -1
- package/dist/server/daemon/kernel/settings-files.js +3 -6
- package/dist/server/daemon/kernel/settings-files.js.map +1 -1
- package/dist/server/daemon/project/ProjectDaemon.d.ts +4 -0
- package/dist/server/daemon/project/ProjectDaemon.d.ts.map +1 -1
- package/dist/server/daemon/project/ProjectDaemon.js +11 -0
- package/dist/server/daemon/project/ProjectDaemon.js.map +1 -1
- package/dist/server/daemon/session/SessionDaemon.d.ts +5 -3
- package/dist/server/daemon/session/SessionDaemon.d.ts.map +1 -1
- package/dist/server/daemon/session/SessionDaemon.js +54 -37
- package/dist/server/daemon/session/SessionDaemon.js.map +1 -1
- package/dist/server/daemon/session/SessionOrchestrator.d.ts +1 -0
- package/dist/server/daemon/session/SessionOrchestrator.d.ts.map +1 -1
- package/dist/server/daemon/session/SessionOrchestrator.js +1371 -1146
- package/dist/server/daemon/session/SessionOrchestrator.js.map +1 -1
- package/dist/server/daemon/session/agent-runtime.d.ts +2 -0
- package/dist/server/daemon/session/agent-runtime.d.ts.map +1 -1
- package/dist/server/daemon/session/agent-runtime.js +55 -6
- package/dist/server/daemon/session/agent-runtime.js.map +1 -1
- package/dist/server/daemon/session/ambient-compact.d.ts +3 -21
- package/dist/server/daemon/session/ambient-compact.d.ts.map +1 -1
- package/dist/server/daemon/session/ambient-compact.js +7 -116
- package/dist/server/daemon/session/ambient-compact.js.map +1 -1
- package/dist/server/daemon/session/behavior-host.d.ts +9 -3
- package/dist/server/daemon/session/behavior-host.d.ts.map +1 -1
- package/dist/server/daemon/session/behavior-host.js +222 -47
- package/dist/server/daemon/session/behavior-host.js.map +1 -1
- package/dist/server/daemon/session/compact.d.ts +0 -1
- package/dist/server/daemon/session/compact.d.ts.map +1 -1
- package/dist/server/daemon/session/compact.js +7 -1
- package/dist/server/daemon/session/compact.js.map +1 -1
- package/dist/server/daemon/session/plugin-abi.d.ts.map +1 -1
- package/dist/server/daemon/session/plugin-abi.js +7 -11
- package/dist/server/daemon/session/plugin-abi.js.map +1 -1
- package/dist/server/daemon/session/prompt-message-of.d.ts +1 -8
- package/dist/server/daemon/session/prompt-message-of.d.ts.map +1 -1
- package/dist/server/daemon/session/prompt-message-of.js +2 -12
- package/dist/server/daemon/session/prompt-message-of.js.map +1 -1
- package/dist/server/daemon/session/re-act-loop-intent-detected-trigger.d.ts +3 -42
- package/dist/server/daemon/session/re-act-loop-intent-detected-trigger.d.ts.map +1 -1
- package/dist/server/daemon/session/re-act-loop-intent-detected-trigger.js +4 -145
- package/dist/server/daemon/session/re-act-loop-intent-detected-trigger.js.map +1 -1
- package/dist/server/daemon/session/round-boundary.d.ts +13 -0
- package/dist/server/daemon/session/round-boundary.d.ts.map +1 -0
- package/dist/server/daemon/session/round-boundary.js +196 -0
- package/dist/server/daemon/session/round-boundary.js.map +1 -0
- package/dist/server/daemon/session/round-stop.d.ts +1 -25
- package/dist/server/daemon/session/round-stop.d.ts.map +1 -1
- package/dist/server/daemon/session/round-stop.js +1 -75
- package/dist/server/daemon/session/round-stop.js.map +1 -1
- package/dist/server/daemon/session/turn-iterator.d.ts +1 -44
- package/dist/server/daemon/session/turn-iterator.d.ts.map +1 -1
- package/dist/server/daemon/session/turn-iterator.js +1 -435
- package/dist/server/daemon/session/turn-iterator.js.map +1 -1
- package/dist/server/daemon/session/turn-resolvers.d.ts +1 -16
- package/dist/server/daemon/session/turn-resolvers.d.ts.map +1 -1
- package/dist/server/daemon/session/turn-resolvers.js +1 -28
- package/dist/server/daemon/session/turn-resolvers.js.map +1 -1
- package/dist/server/daemon/session/visual-store.d.ts +2 -2
- package/dist/server/daemon/session/visual-store.d.ts.map +1 -1
- package/dist/server/daemon/session/visual-store.js +19 -20
- package/dist/server/daemon/session/visual-store.js.map +1 -1
- package/dist/server/drivers/request-timeout.d.ts +1 -0
- package/dist/server/drivers/request-timeout.d.ts.map +1 -1
- package/dist/server/drivers/request-timeout.js +2 -1
- package/dist/server/drivers/request-timeout.js.map +1 -1
- package/dist/server/runtime-bin.js +5 -8
- package/dist/server/runtime-bin.js.map +1 -1
- package/dist/server/schemas/index.d.ts +0 -1
- package/dist/server/schemas/index.d.ts.map +1 -1
- package/dist/server/schemas/index.js +0 -1
- package/dist/server/schemas/index.js.map +1 -1
- package/dist/server/schemas/json-record.d.ts +0 -6
- package/dist/server/schemas/json-record.d.ts.map +1 -1
- package/dist/server/schemas/json-record.js +0 -16
- package/dist/server/schemas/json-record.js.map +1 -1
- package/dist/server/schemas/well-known.d.ts +0 -2
- package/dist/server/schemas/well-known.d.ts.map +1 -1
- package/dist/server/schemas/well-known.js +0 -1
- package/dist/server/schemas/well-known.js.map +1 -1
- package/dist/server/testkit/scripted-model.d.ts +11 -0
- package/dist/server/testkit/scripted-model.d.ts.map +1 -1
- package/dist/server/testkit/scripted-model.js +42 -3
- package/dist/server/testkit/scripted-model.js.map +1 -1
- package/dist/server/toolkit/actor.d.ts +0 -1
- package/dist/server/toolkit/actor.d.ts.map +1 -1
- package/dist/server/toolkit/actor.js +2 -5
- package/dist/server/toolkit/actor.js.map +1 -1
- package/dist/server/toolkit/catalog.d.ts +0 -2
- package/dist/server/toolkit/catalog.d.ts.map +1 -1
- package/dist/server/toolkit/catalog.js +0 -81
- package/dist/server/toolkit/catalog.js.map +1 -1
- package/dist/server/toolkit/pack-catalog.d.ts +2 -1
- package/dist/server/toolkit/pack-catalog.d.ts.map +1 -1
- package/dist/server/toolkit/pack-catalog.js +1 -0
- package/dist/server/toolkit/pack-catalog.js.map +1 -1
- package/dist/server/toolkit/tool-entry.d.ts.map +1 -1
- package/dist/server/toolkit/tool-entry.js +1 -0
- package/dist/server/toolkit/tool-entry.js.map +1 -1
- package/dist/server/toolkit/tool-table.d.ts +0 -1
- package/dist/server/toolkit/tool-table.d.ts.map +1 -1
- package/dist/server/toolkit/tool-table.js +0 -3
- package/dist/server/toolkit/tool-table.js.map +1 -1
- package/dist/server/util/read-field.d.ts +0 -2
- package/dist/server/util/read-field.d.ts.map +1 -1
- package/dist/server/util/read-field.js +0 -9
- package/dist/server/util/read-field.js.map +1 -1
- package/dist/server/util/tool-call-json.d.ts +0 -1
- package/dist/server/util/tool-call-json.d.ts.map +1 -1
- package/dist/server/util/tool-call-json.js +0 -25
- package/dist/server/util/tool-call-json.js.map +1 -1
- package/dist/session/index.d.ts +4 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +10 -1
- package/dist/session/index.js.map +1 -1
- package/dist/tool-runtime/guard-tool.d.ts +3 -0
- package/dist/tool-runtime/guard-tool.d.ts.map +1 -1
- package/dist/tool-runtime/guard-tool.js +37 -3
- package/dist/tool-runtime/guard-tool.js.map +1 -1
- package/dist/yjs/document-service.d.ts +2 -4
- package/dist/yjs/document-service.d.ts.map +1 -1
- package/dist/yjs/document-service.js +0 -6
- package/dist/yjs/document-service.js.map +1 -1
- package/package.json +40 -40
|
@@ -40,7 +40,7 @@ const COMPLETION_FAILED_STATUS = /(?:openai-compat completion failed: |\bHTTP )(
|
|
|
40
40
|
const TRANSIENT_CODE = /^(?:ECONNRESET|ETIMEDOUT|ENOTFOUND|ECONNREFUSED|EAI_AGAIN|EPIPE|EHOSTUNREACH|ENETUNREACH|EPROTO|UND_ERR_)/;
|
|
41
41
|
const TRANSIENT_TEXT = /fetch failed|Failed to fetch|ECONNRESET|ETIMEDOUT|ENOTFOUND|ECONNREFUSED|EAI_AGAIN|Connect Timeout|Headers Timeout|other side closed|UND_ERR_|socket hang up/i;
|
|
42
42
|
/** Parsed SSE `data:` only. Socket bytes reset undici's body timer, including pings (`request-timeout.ts`). */
|
|
43
|
-
const STREAM_STALL_MS =
|
|
43
|
+
const STREAM_STALL_MS = 180_000;
|
|
44
44
|
/** Longest wait between attempts, whether it comes from our backoff or from the server. */
|
|
45
45
|
const BACKOFF_CAP_MS = 5 * 60 * 1000;
|
|
46
46
|
/** A 429 or 503 that named how long to wait. The message is the ordinary HTTP failure text. */
|
|
@@ -336,20 +336,6 @@ function visibleThought(raw, summary) {
|
|
|
336
336
|
return { thought: summary, kind: "summary" };
|
|
337
337
|
return { thought: "", kind: null };
|
|
338
338
|
}
|
|
339
|
-
/**
|
|
340
|
-
* Responses `incomplete` + `max_output_tokens` after a reasoning item is the
|
|
341
|
-
* model spending the budget on thought and stopping before a message. Not a
|
|
342
|
-
* failed generation — ReACT continues. Other incomplete reasons stay fatal.
|
|
343
|
-
*/
|
|
344
|
-
function incompleteThoughtExhausted(reason, thought) {
|
|
345
|
-
if (reason !== "max_output_tokens")
|
|
346
|
-
return false;
|
|
347
|
-
return (thought.raw.trim() !== "" ||
|
|
348
|
-
thought.summary.trim() !== "" ||
|
|
349
|
-
thought.encrypted !== "" ||
|
|
350
|
-
thought.kind != null ||
|
|
351
|
-
(thought.reasoningTokens ?? 0) > 0);
|
|
352
|
-
}
|
|
353
339
|
const THINKING_PART_TYPES = new Set(["thinking", "reasoning", "redacted_thinking", "reasoning_text"]);
|
|
354
340
|
function isThinkingPart(part) {
|
|
355
341
|
const type = readField(part, "type");
|
|
@@ -424,7 +410,107 @@ function chunkMessageReasoning(raw) {
|
|
|
424
410
|
const alt = readField(message, "reasoning");
|
|
425
411
|
return typeof alt === "string" && alt !== "" ? alt : "";
|
|
426
412
|
}
|
|
413
|
+
/** A no-progress deadline is terminal, unlike explicitly configured transient retries. */
|
|
414
|
+
async function withProgressDeadline(pending, signal, ms, phase, cancel) {
|
|
415
|
+
let timer;
|
|
416
|
+
let onAbort;
|
|
417
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
418
|
+
onAbort = () => reject(signal.reason ?? new Error("completion aborted"));
|
|
419
|
+
if (signal.aborted) {
|
|
420
|
+
onAbort();
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
424
|
+
timer = setTimeout(() => {
|
|
425
|
+
const reason = new StreamStallError(ms);
|
|
426
|
+
reason.message = `${phase} stalled after ${ms}ms`;
|
|
427
|
+
reject(reason);
|
|
428
|
+
cancel(reason);
|
|
429
|
+
}, ms);
|
|
430
|
+
timer.unref();
|
|
431
|
+
});
|
|
432
|
+
try {
|
|
433
|
+
return await Promise.race([pending, deadline]);
|
|
434
|
+
}
|
|
435
|
+
finally {
|
|
436
|
+
clearTimeout(timer);
|
|
437
|
+
if (onAbort)
|
|
438
|
+
signal.removeEventListener("abort", onAbort);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function readBulkText(response, signal, ms) {
|
|
442
|
+
return withProgressDeadline(response.text(), signal, ms, "response body", (reason) => {
|
|
443
|
+
// The fetch signal owns network cancellation. A synthetic response may not
|
|
444
|
+
// observe it; deadline rejection must not depend on its cancel implementation.
|
|
445
|
+
void response.body?.cancel(reason).catch(() => undefined);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
/** Only model output or an authoritative terminal can extend the no-progress deadline. */
|
|
449
|
+
function streamFrameProgress(frame) {
|
|
450
|
+
if (typeof frame !== "object" || frame === null)
|
|
451
|
+
return false;
|
|
452
|
+
const text = (value) => typeof value === "string" && value.length > 0;
|
|
453
|
+
const type = readField(frame, "type");
|
|
454
|
+
if (type === "error" ||
|
|
455
|
+
type === "response.completed" ||
|
|
456
|
+
type === "response.done" ||
|
|
457
|
+
type === "response.failed" ||
|
|
458
|
+
type === "response.incomplete")
|
|
459
|
+
return true;
|
|
460
|
+
if (typeof type === "string" && type.startsWith("response.") && type.endsWith(".delta"))
|
|
461
|
+
return text(readField(frame, "delta"));
|
|
462
|
+
if (type === "response.output_item.added" || type === "response.output_item.done") {
|
|
463
|
+
const item = readField(frame, "item");
|
|
464
|
+
if (typeof item !== "object" || item === null)
|
|
465
|
+
return false;
|
|
466
|
+
const content = splitMessageContent(readField(item, "content"));
|
|
467
|
+
return (text(readField(item, "name")) ||
|
|
468
|
+
text(readField(item, "arguments")) ||
|
|
469
|
+
text(readField(item, "encrypted_content")) ||
|
|
470
|
+
text(reasoningPartText(readField(item, "summary"))) ||
|
|
471
|
+
text(reasoningPartText(readField(item, "content"))) ||
|
|
472
|
+
text(content.text) ||
|
|
473
|
+
text(content.thought));
|
|
474
|
+
}
|
|
475
|
+
const choices = readField(frame, "choices");
|
|
476
|
+
if (!Array.isArray(choices))
|
|
477
|
+
return false;
|
|
478
|
+
return choices.some((choice) => {
|
|
479
|
+
if (typeof choice !== "object" || choice === null)
|
|
480
|
+
return false;
|
|
481
|
+
if (text(readField(choice, "finish_reason")))
|
|
482
|
+
return true;
|
|
483
|
+
const delta = readField(choice, "delta");
|
|
484
|
+
if (typeof delta !== "object" || delta === null)
|
|
485
|
+
return false;
|
|
486
|
+
const content = splitMessageContent(readField(delta, "content"));
|
|
487
|
+
if (text(content.text) ||
|
|
488
|
+
text(content.thought) ||
|
|
489
|
+
content.sawThinking ||
|
|
490
|
+
text(readField(delta, "reasoning_content")) ||
|
|
491
|
+
text(readField(delta, "reasoning")) ||
|
|
492
|
+
text(readField(delta, "thinking")))
|
|
493
|
+
return true;
|
|
494
|
+
const reasoningDetails = readField(delta, "reasoning_details");
|
|
495
|
+
if (Array.isArray(reasoningDetails) &&
|
|
496
|
+
reasoningDetails.some((entry) => typeof entry === "object" &&
|
|
497
|
+
entry !== null &&
|
|
498
|
+
(text(readField(entry, "text")) || text(readField(entry, "summary")) || text(readField(entry, "data")))))
|
|
499
|
+
return true;
|
|
500
|
+
const calls = readField(delta, "tool_calls");
|
|
501
|
+
return (Array.isArray(calls) &&
|
|
502
|
+
calls.some((call) => {
|
|
503
|
+
if (typeof call !== "object" || call === null)
|
|
504
|
+
return false;
|
|
505
|
+
if (text(readField(call, "id")))
|
|
506
|
+
return true;
|
|
507
|
+
const fn = readField(call, "function");
|
|
508
|
+
return (typeof fn === "object" && fn !== null && (text(readField(fn, "name")) || text(readField(fn, "arguments"))));
|
|
509
|
+
}));
|
|
510
|
+
});
|
|
511
|
+
}
|
|
427
512
|
export async function* readSseJson(body, signal, stallMs) {
|
|
513
|
+
signal.throwIfAborted();
|
|
428
514
|
if (!body)
|
|
429
515
|
return;
|
|
430
516
|
const reader = body.getReader();
|
|
@@ -432,6 +518,18 @@ export async function* readSseJson(body, signal, stallMs) {
|
|
|
432
518
|
let buf = "";
|
|
433
519
|
let armTimer;
|
|
434
520
|
let stalled;
|
|
521
|
+
let rejectInterrupted;
|
|
522
|
+
const interrupted = new Promise((_resolve, reject) => {
|
|
523
|
+
rejectInterrupted = reject;
|
|
524
|
+
});
|
|
525
|
+
const onAbort = () => {
|
|
526
|
+
rejectInterrupted(signal.reason ?? new Error("completion aborted"));
|
|
527
|
+
void reader.cancel(signal.reason).catch(() => undefined);
|
|
528
|
+
};
|
|
529
|
+
if (signal.aborted)
|
|
530
|
+
onAbort();
|
|
531
|
+
else
|
|
532
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
435
533
|
const clearArm = () => {
|
|
436
534
|
if (armTimer === undefined)
|
|
437
535
|
return;
|
|
@@ -443,6 +541,7 @@ export async function* readSseJson(body, signal, stallMs) {
|
|
|
443
541
|
clearArm();
|
|
444
542
|
const timer = setTimeout(() => {
|
|
445
543
|
stalled = new StreamStallError(stallMs);
|
|
544
|
+
rejectInterrupted(stalled);
|
|
446
545
|
void reader.cancel(stalled).catch(() => undefined);
|
|
447
546
|
}, stallMs);
|
|
448
547
|
timer.unref();
|
|
@@ -450,7 +549,7 @@ export async function* readSseJson(body, signal, stallMs) {
|
|
|
450
549
|
};
|
|
451
550
|
const read = async () => {
|
|
452
551
|
try {
|
|
453
|
-
const next = await reader.read();
|
|
552
|
+
const next = await Promise.race([reader.read(), interrupted]);
|
|
454
553
|
if (stalled !== undefined)
|
|
455
554
|
throw stalled;
|
|
456
555
|
return next;
|
|
@@ -470,11 +569,11 @@ export async function* readSseJson(body, signal, stallMs) {
|
|
|
470
569
|
buf += decoder.decode(value, { stream: true });
|
|
471
570
|
let yielded = false;
|
|
472
571
|
for (;;) {
|
|
473
|
-
const
|
|
474
|
-
if (
|
|
572
|
+
const separator = /\r?\n\r?\n/.exec(buf);
|
|
573
|
+
if (separator === null)
|
|
475
574
|
break;
|
|
476
|
-
const event = buf.slice(0,
|
|
477
|
-
buf = buf.slice(
|
|
575
|
+
const event = buf.slice(0, separator.index);
|
|
576
|
+
buf = buf.slice(separator.index + separator[0].length);
|
|
478
577
|
for (const line of event.split(/\r?\n/)) {
|
|
479
578
|
const trimmed = line.trimEnd();
|
|
480
579
|
if (!trimmed.startsWith("data:"))
|
|
@@ -486,8 +585,10 @@ export async function* readSseJson(body, signal, stallMs) {
|
|
|
486
585
|
continue;
|
|
487
586
|
}
|
|
488
587
|
try {
|
|
489
|
-
|
|
490
|
-
|
|
588
|
+
const parsed = parseJsonUnknown(data);
|
|
589
|
+
yield parsed;
|
|
590
|
+
if (streamFrameProgress(parsed))
|
|
591
|
+
yielded = true;
|
|
491
592
|
}
|
|
492
593
|
catch {
|
|
493
594
|
// skip malformed line
|
|
@@ -516,6 +617,8 @@ export async function* readSseJson(body, signal, stallMs) {
|
|
|
516
617
|
}
|
|
517
618
|
finally {
|
|
518
619
|
clearArm();
|
|
620
|
+
signal.removeEventListener("abort", onAbort);
|
|
621
|
+
void reader.cancel().catch(() => undefined);
|
|
519
622
|
try {
|
|
520
623
|
reader.releaseLock();
|
|
521
624
|
}
|
|
@@ -621,14 +724,14 @@ export class OpenAiCompatActor extends ExpectationActor {
|
|
|
621
724
|
const posted = Date.now();
|
|
622
725
|
trace("harness:complete", `post ${this.expectation.uuid} connection=${this.driverConnection.connectionId} model=${this.effectiveModel()} attempt=${n}`);
|
|
623
726
|
try {
|
|
624
|
-
response = await this.driverConnection.authorizedFetch(url, {
|
|
727
|
+
response = await withProgressDeadline(this.driverConnection.authorizedFetch(url, {
|
|
625
728
|
method: "POST",
|
|
626
729
|
headers: affinity.headers,
|
|
627
730
|
body: JSON.stringify(payload),
|
|
628
|
-
}, abort.signal);
|
|
731
|
+
}, abort.signal), abort.signal, this.stallMs, "completion request", (reason) => abort.abort(reason));
|
|
629
732
|
}
|
|
630
733
|
catch (error) {
|
|
631
|
-
if (error instanceof ConnectionMiss)
|
|
734
|
+
if (error instanceof ConnectionMiss || error instanceof StreamStallError)
|
|
632
735
|
throw error;
|
|
633
736
|
throw wrapFetchFailure(error, {
|
|
634
737
|
why: "completion",
|
|
@@ -637,7 +740,7 @@ export class OpenAiCompatActor extends ExpectationActor {
|
|
|
637
740
|
});
|
|
638
741
|
}
|
|
639
742
|
if (!response.ok) {
|
|
640
|
-
const errorBody = await response.text();
|
|
743
|
+
const errorBody = await withProgressDeadline(response.text(), abort.signal, this.stallMs, "error response body", (reason) => abort.abort(reason));
|
|
641
744
|
const detail = errorBody.trim().slice(0, 240);
|
|
642
745
|
const message = describeHttpFailure({
|
|
643
746
|
why: "completion",
|
|
@@ -658,6 +761,8 @@ export class OpenAiCompatActor extends ExpectationActor {
|
|
|
658
761
|
throw new Error(message);
|
|
659
762
|
}
|
|
660
763
|
const answer = await this.readAnswer(response, abort.signal);
|
|
764
|
+
if (this.signal.aborted)
|
|
765
|
+
return;
|
|
661
766
|
trace("harness:complete", `answer ${this.expectation.uuid} ms=${Date.now() - posted} status=${response.status} chars=${answer?.content.length ?? 0}`);
|
|
662
767
|
invariant(answer !== null, "openai-compat completion failed");
|
|
663
768
|
this.expectation.stampAnswer({
|
|
@@ -692,6 +797,8 @@ export class OpenAiCompatActor extends ExpectationActor {
|
|
|
692
797
|
return;
|
|
693
798
|
if (error instanceof ExpectationInvariant)
|
|
694
799
|
throw error;
|
|
800
|
+
if (error instanceof StreamStallError)
|
|
801
|
+
abort.abort(error);
|
|
695
802
|
if (!isTransientCompletionError(error)) {
|
|
696
803
|
const reason = error instanceof Error ? error.message : String(error);
|
|
697
804
|
this.expectation.failReason = reason;
|
|
@@ -968,12 +1075,12 @@ export class OpenAiCompatChatActor extends OpenAiCompatActor {
|
|
|
968
1075
|
async readAnswer(response, signal) {
|
|
969
1076
|
const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
|
|
970
1077
|
if (contentType.includes("application/json")) {
|
|
971
|
-
return this.#roundFromBulk(await response.
|
|
1078
|
+
return this.#roundFromBulk(parseJsonUnknown(await readBulkText(response, signal, this.stallMs)));
|
|
972
1079
|
}
|
|
973
1080
|
if (contentType.includes("text/event-stream") || contentType.includes("event-stream")) {
|
|
974
1081
|
return this.#consumeStream(readSseJson(response.body, signal, this.stallMs));
|
|
975
1082
|
}
|
|
976
|
-
const text = await response.
|
|
1083
|
+
const text = await readBulkText(response, signal, this.stallMs);
|
|
977
1084
|
const head = text.trimStart();
|
|
978
1085
|
if (head.startsWith("{") || head.startsWith("[")) {
|
|
979
1086
|
try {
|
|
@@ -997,6 +1104,9 @@ export class OpenAiCompatChatActor extends OpenAiCompatActor {
|
|
|
997
1104
|
const choice = Array.isArray(choices) && typeof choices[0] === "object" && choices[0] !== null ? choices[0] : undefined;
|
|
998
1105
|
const message = choice == null ? undefined : readField(choice, "message");
|
|
999
1106
|
const messageRec = typeof message === "object" && message !== null ? message : undefined;
|
|
1107
|
+
const terminal = choice == null ? undefined : readField(choice, "finish_reason");
|
|
1108
|
+
if (messageRec == null || typeof terminal !== "string" || terminal === "")
|
|
1109
|
+
throw new Error("Chat completion response is missing its message or terminal finish reason");
|
|
1000
1110
|
const reasoningContent = messageRec == null ? undefined : readField(messageRec, "reasoning_content");
|
|
1001
1111
|
const reasoningAlt = messageRec == null ? undefined : readField(messageRec, "reasoning");
|
|
1002
1112
|
const reasoning = typeof reasoningContent === "string" && reasoningContent.length > 0
|
|
@@ -1054,6 +1164,7 @@ export class OpenAiCompatChatActor extends OpenAiCompatActor {
|
|
|
1054
1164
|
const partial = new Set();
|
|
1055
1165
|
const dropped = [];
|
|
1056
1166
|
let finishReason;
|
|
1167
|
+
let sawTerminal = false;
|
|
1057
1168
|
const onEvent = (ev) => {
|
|
1058
1169
|
switch (ev.type) {
|
|
1059
1170
|
case "reasoning_delta": {
|
|
@@ -1109,6 +1220,8 @@ export class OpenAiCompatChatActor extends OpenAiCompatActor {
|
|
|
1109
1220
|
if (typeof raw === "object" && raw !== null) {
|
|
1110
1221
|
const rec = raw;
|
|
1111
1222
|
const choice = rec.choices?.[0];
|
|
1223
|
+
if (typeof choice?.finish_reason === "string" && choice.finish_reason !== "")
|
|
1224
|
+
sawTerminal = true;
|
|
1112
1225
|
const delta = choice?.delta;
|
|
1113
1226
|
let chunk = rec;
|
|
1114
1227
|
if (delta != null) {
|
|
@@ -1144,7 +1257,11 @@ export class OpenAiCompatChatActor extends OpenAiCompatActor {
|
|
|
1144
1257
|
}
|
|
1145
1258
|
if (thoughtAcc === "")
|
|
1146
1259
|
thoughtAcc = chunkMessageReasoning(raw);
|
|
1260
|
+
if (sawTerminal)
|
|
1261
|
+
break;
|
|
1147
1262
|
}
|
|
1263
|
+
if (!sawTerminal)
|
|
1264
|
+
throw new Error("Chat completion stream ended without a terminal finish reason");
|
|
1148
1265
|
for (const ev of session.close())
|
|
1149
1266
|
onEvent(ev);
|
|
1150
1267
|
const settled = settleCalls(calls, partial, dropped, finishReason);
|
|
@@ -1258,8 +1375,19 @@ export class OpenAiCompatResponsesActor extends OpenAiCompatActor {
|
|
|
1258
1375
|
async readAnswer(response, signal) {
|
|
1259
1376
|
const contentType = response.headers.get("content-type") ?? "";
|
|
1260
1377
|
if (contentType.toLowerCase().includes("application/json") && !contentType.toLowerCase().includes("event-stream")) {
|
|
1261
|
-
const payload = await response.
|
|
1378
|
+
const payload = parseJsonUnknown(await readBulkText(response, signal, this.stallMs));
|
|
1262
1379
|
this.stampConsumed(payload);
|
|
1380
|
+
const status = typeof payload === "object" && payload !== null ? readField(payload, "status") : undefined;
|
|
1381
|
+
if (status !== "completed" && status !== "incomplete") {
|
|
1382
|
+
const error = readField(payload, "error");
|
|
1383
|
+
const message = typeof error === "object" && error !== null ? readField(error, "message") : undefined;
|
|
1384
|
+
throw new Error(typeof message === "string" ? message : `Responses request ended with status ${status}`);
|
|
1385
|
+
}
|
|
1386
|
+
const incomplete = typeof payload === "object" && payload !== null ? readField(payload, "incomplete_details") : undefined;
|
|
1387
|
+
const incompleteReason = typeof incomplete === "object" && incomplete !== null ? readField(incomplete, "reason") : undefined;
|
|
1388
|
+
if (status === "incomplete" && incompleteReason !== "max_output_tokens" && incompleteReason !== "content_filter")
|
|
1389
|
+
throw new Error(`Responses request incomplete: ${String(incompleteReason)}`);
|
|
1390
|
+
const finishReason = status === "incomplete" ? (incompleteReason === "content_filter" ? "content_filter" : "length") : undefined;
|
|
1263
1391
|
const parts = [];
|
|
1264
1392
|
const rawParts = [];
|
|
1265
1393
|
const summaryParts = [];
|
|
@@ -1319,7 +1447,13 @@ export class OpenAiCompatResponsesActor extends OpenAiCompatActor {
|
|
|
1319
1447
|
this.#stampReasoningEncrypted(encrypted);
|
|
1320
1448
|
this.stampThoughtKind(thoughtKind);
|
|
1321
1449
|
this.speech(text, visible.thought);
|
|
1322
|
-
return {
|
|
1450
|
+
return {
|
|
1451
|
+
content: text,
|
|
1452
|
+
reasoning: visible.thought,
|
|
1453
|
+
thoughtKind,
|
|
1454
|
+
calls,
|
|
1455
|
+
...(finishReason == null ? {} : { finishReason }),
|
|
1456
|
+
};
|
|
1323
1457
|
}
|
|
1324
1458
|
let acc = {
|
|
1325
1459
|
text: "",
|
|
@@ -1422,19 +1556,11 @@ export class OpenAiCompatResponsesActor extends OpenAiCompatActor {
|
|
|
1422
1556
|
}
|
|
1423
1557
|
}
|
|
1424
1558
|
}
|
|
1425
|
-
if (
|
|
1426
|
-
raw: acc.raw,
|
|
1427
|
-
summary: acc.summary,
|
|
1428
|
-
encrypted,
|
|
1429
|
-
kind: this.expectation.responseThoughtKind,
|
|
1430
|
-
reasoningTokens: this.expectation.reasoningTokens,
|
|
1431
|
-
})) {
|
|
1559
|
+
if (details === "max_output_tokens") {
|
|
1432
1560
|
sawTerminal = true;
|
|
1433
1561
|
finish = "length";
|
|
1434
1562
|
break;
|
|
1435
1563
|
}
|
|
1436
|
-
// Speech cut off by max_output_tokens stays a failed round (chatgpt-complete.test); only
|
|
1437
|
-
// the filter is a stop of its own.
|
|
1438
1564
|
if (details === "content_filter") {
|
|
1439
1565
|
sawTerminal = true;
|
|
1440
1566
|
finish = "content_filter";
|
|
@@ -1493,6 +1619,8 @@ export class OpenAiCompatResponsesActor extends OpenAiCompatActor {
|
|
|
1493
1619
|
emitSpeech();
|
|
1494
1620
|
}
|
|
1495
1621
|
}
|
|
1622
|
+
if (sawTerminal)
|
|
1623
|
+
break;
|
|
1496
1624
|
}
|
|
1497
1625
|
if (!sawTerminal)
|
|
1498
1626
|
throw new Error("Responses stream ended before terminal response event");
|