@sema-agent/core 7.23.5 → 7.24.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/CHANGELOG.md +77 -0
- package/dist/agents/list-agents-tool.d.ts +7 -4
- package/dist/agents/list-agents-tool.js +12 -1
- package/dist/agents/observer.js +5 -8
- package/dist/agents/subagent.js +2 -2
- package/dist/agents/team.js +9 -0
- package/dist/brain/degrading.js +8 -9
- package/dist/brain/route-adjudicator.d.ts +25 -12
- package/dist/brain/route-adjudicator.js +89 -23
- package/dist/brain/route-conformance.js +9 -0
- package/dist/brain/stream-engine.js +11 -9
- package/dist/core/arg-summary.js +17 -6
- package/dist/core/auto-compaction.d.ts +42 -1
- package/dist/core/auto-compaction.js +21 -1
- package/dist/core/auto-mode.js +2 -8
- package/dist/core/exec-gate.js +3 -5
- package/dist/core/file-history-store.js +11 -10
- package/dist/core/hooks.d.ts +7 -0
- package/dist/core/mcp.js +7 -5
- package/dist/core/memory-engine/distiller.d.ts +7 -4
- package/dist/core/memory-engine/distiller.js +11 -3
- package/dist/core/memory.js +1 -0
- package/dist/core/runner/assemble-result.js +12 -19
- package/dist/core/runner/contracts.d.ts +1 -0
- package/dist/core/runner/prepare-file-history.js +19 -0
- package/dist/core/runner/run-recovery-lanes.js +4 -20
- package/dist/core/runner/run-settle-and-teardown.js +2 -16
- package/dist/core/runner/run-turn-boundary.js +4 -20
- package/dist/core/runner/runtask.js +3 -5
- package/dist/core/runner/stream-settle-backstop.js +5 -5
- package/dist/core/runner/tool-end-body.js +5 -4
- package/dist/core/runner/tool-output-projection.js +3 -2
- package/dist/core/runner/turn-attachments.d.ts +0 -20
- package/dist/core/runner/turn-attachments.js +41 -36
- package/dist/core/session-store.js +2 -4
- package/dist/core/session.d.ts +4 -1
- package/dist/core/session.js +2 -1
- package/dist/core/task-event.d.ts +19 -9
- package/dist/core/task-registry-shared.js +1 -0
- package/dist/core/thrown-value.d.ts +24 -13
- package/dist/core/thrown-value.js +13 -1
- package/dist/core/tool-errors.d.ts +6 -0
- package/dist/core/tool-errors.js +6 -14
- package/dist/core/tools.js +8 -9
- package/dist/engine/llm/types.d.ts +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/orchestration/workflow.js +44 -23
- package/dist/stores/file/file-history-store.js +12 -11
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +7 -3
- package/wire-changes/core@7.24.0.json +249 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createAssistantMessageEventStream, } from "../internal/llm.js";
|
|
2
2
|
import { STREAM_TORN_WARNING } from "./stream-shared.js";
|
|
3
3
|
import { FLOOR_OUTPUT_TOKENS, parseContextOverflow, planOutputCapAdjustment } from "./context-overflow.js";
|
|
4
|
-
import { abortLikeName, BrainError, classifyConnectFailure, classifyFetchThrow, classifyHttp, describeNetworkError, namesTheFailure, readProviderRequestId } from "./errors.js";
|
|
4
|
+
import { abortLikeName, BrainError, brainErrorCodeOf, classifyConnectFailure, classifyFetchThrow, classifyHttp, describeNetworkError, namesTheFailure, readProviderRequestId } from "./errors.js";
|
|
5
5
|
import { stripUrlCredentials } from "./route-adjudicator.js";
|
|
6
6
|
import { classifyInputTooLong } from "./input-too-long.js";
|
|
7
7
|
import { FAST_MAX_BACKOFF_MS, providerWaitHint, retryBackoffMs } from "./retry.js";
|
|
8
8
|
import { bindBrainStatusEmitter, emitBrainStatus, emitBrainTelemetry } from "./status-sink.js";
|
|
9
9
|
import { createConnectController, resolveStallTimeoutMs } from "./timeout.js";
|
|
10
|
-
import { thrownText } from "../core/thrown-value.js";
|
|
10
|
+
import { readMember, thrownText } from "../core/thrown-value.js";
|
|
11
11
|
import { redactSecrets } from "../core/untrusted-egress.js";
|
|
12
12
|
const DEFAULT_MAX_RETRIES = 10;
|
|
13
13
|
const MAX_RETRIES_ENV_CEILING = 15;
|
|
@@ -274,15 +274,17 @@ export function runStreamingBrain(args) {
|
|
|
274
274
|
const errorMsg = emptyAssistant(model);
|
|
275
275
|
errorMsg.stopReason = aborted ? "aborted" : "error";
|
|
276
276
|
errorMsg.errorMessage = thrownText(err);
|
|
277
|
-
if (!aborted && err
|
|
278
|
-
if (err
|
|
277
|
+
if (!aborted && brainErrorCodeOf(err) !== undefined) {
|
|
278
|
+
if (readMember(err, "inputTooLong") === true)
|
|
279
279
|
errorMsg.errorKind = "input_too_long";
|
|
280
|
-
else if (err
|
|
280
|
+
else if (readMember(err, "inputTooLongRuledOut") === true)
|
|
281
281
|
errorMsg.inputTooLongRuledOut = true;
|
|
282
|
-
if (err
|
|
282
|
+
if (readMember(err, "apiError") === true) {
|
|
283
283
|
errorMsg.isApiErrorMessage = true;
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
const status = readMember(err, "status");
|
|
285
|
+
const statusNum = typeof status === "number" ? status : undefined;
|
|
286
|
+
if (namesTheFailure(statusNum))
|
|
287
|
+
errorMsg.apiErrorStatus = statusNum;
|
|
286
288
|
if (requestIdSeen !== undefined)
|
|
287
289
|
errorMsg.requestId = requestIdSeen;
|
|
288
290
|
}
|
|
@@ -581,7 +583,7 @@ export function runStreamingBrain(args) {
|
|
|
581
583
|
return false;
|
|
582
584
|
}
|
|
583
585
|
catch (e) {
|
|
584
|
-
if (
|
|
586
|
+
if (brainErrorCodeOf(e) !== "server" || !parser.snapshot().hasSubstantiveText)
|
|
585
587
|
throw e;
|
|
586
588
|
return true;
|
|
587
589
|
}
|
package/dist/core/arg-summary.js
CHANGED
|
@@ -196,14 +196,15 @@ export function runRedactionPasses(input, passes, report) {
|
|
|
196
196
|
return result;
|
|
197
197
|
}
|
|
198
198
|
export const SECRET_PASSES = [
|
|
199
|
-
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])(?:sk|pk|rk|gh[opsur])[-_][A-Za-z0-9_-]{8,}/g, replace: "[redacted]" },
|
|
199
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])(?:sk|pk|rk|gh[opsur]|github_pat)[-_][A-Za-z0-9_-]{8,}/g, replace: "[redacted]" },
|
|
200
200
|
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])AIza[A-Za-z0-9_-]{20,}/g, replace: "[redacted]" },
|
|
201
201
|
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])xox[baprs]-[A-Za-z0-9-]{10,}/g, replace: "[redacted]" },
|
|
202
202
|
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{12,}/g, replace: "[redacted]" },
|
|
203
203
|
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{20,}/g, replace: "[redacted]" },
|
|
204
204
|
{ kind: "jwt", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])eyJ[A-Za-z0-9._-]{20,}/g, replace: "[redacted]" },
|
|
205
|
-
{ kind: "private-key-block", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /-----BEGIN[ A-
|
|
205
|
+
{ kind: "private-key-block", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /-----BEGIN[ A-Z0-9]*PRIVATE KEY(?: BLOCK)?-----[\s\S]*?(?:-----END[ A-Z0-9]*PRIVATE KEY(?: BLOCK)?-----|$)/g, replace: "[redacted]" },
|
|
206
206
|
{ kind: "bearer-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(?<![A-Za-z0-9])Bearer\s+[A-Za-z0-9._~+/-]{8,}=*/gi, replace: "[redacted]" },
|
|
207
|
+
{ kind: "prefixed-token", confidence: "high", marker: "[redacted]", source: "arg-summary", re: /(AccountKey=)[A-Za-z0-9+/]{40,}={0,2}/g, replace: "$1[redacted]" },
|
|
207
208
|
{
|
|
208
209
|
kind: "keyword-value",
|
|
209
210
|
confidence: "medium",
|
|
@@ -247,12 +248,22 @@ export function primaryActivityArg(args) {
|
|
|
247
248
|
val = basename(path);
|
|
248
249
|
}
|
|
249
250
|
else if (url !== undefined) {
|
|
250
|
-
try {
|
|
251
|
-
|
|
252
|
-
val = `${u.origin}${u.pathname}`;
|
|
251
|
+
const parsed = (() => { try {
|
|
252
|
+
return new URL(url);
|
|
253
253
|
}
|
|
254
254
|
catch {
|
|
255
|
-
|
|
255
|
+
return undefined;
|
|
256
|
+
} })();
|
|
257
|
+
if (parsed !== undefined && parsed.host !== "") {
|
|
258
|
+
val = `${parsed.origin}${parsed.pathname}`;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
const head = url.split(/[?#]/, 1)[0] ?? url;
|
|
262
|
+
const sep = head.indexOf("://");
|
|
263
|
+
const scheme = sep > 0 && /^[a-z][a-z0-9+.-]*$/i.test(head.slice(0, sep)) ? head.slice(0, sep + 3) : "";
|
|
264
|
+
const rest = head.slice(scheme.length);
|
|
265
|
+
const at = rest.lastIndexOf("@");
|
|
266
|
+
val = scheme + (at === -1 ? rest : rest.slice(at + 1));
|
|
256
267
|
}
|
|
257
268
|
}
|
|
258
269
|
else {
|
|
@@ -3,6 +3,7 @@ import type { Message, Model, Tool } from "../internal/llm.js";
|
|
|
3
3
|
import type { Hooks } from "./hooks.js";
|
|
4
4
|
import type { TraceEvent } from "./trace.js";
|
|
5
5
|
import type { Brain } from "./types.js";
|
|
6
|
+
import type { TaskEvent, TaskEventIdentity } from "./task-event.js";
|
|
6
7
|
/**
|
|
7
8
|
* Default summarization focus, applied when a task does not provide `compaction.instructions`.
|
|
8
9
|
* Addresses the common fidelity failure where summaries drop specific facts.
|
|
@@ -431,10 +432,13 @@ export interface MaybeCompactOptions {
|
|
|
431
432
|
* return). Does NOT alter control flow. `reused` distinguishes a provider-supplied summary from a real
|
|
432
433
|
* LLM `generateSummary`. `freedTokens` is the §25.2 structural delta (may be ~0 when a reused summary
|
|
433
434
|
* frees little — see reuse guard (b): such a compaction does NOT raise the caller's anti-thrash floor).
|
|
435
|
+
* ABSENT when the post measurement failed — never a stand-in ("fully effective" is not true of a
|
|
436
|
+
* landing that leaves a summary behind). Every consumer reads absence as "no evidence": the floor
|
|
437
|
+
* stays where it is and the backoff does not flip.
|
|
434
438
|
*/
|
|
435
439
|
onCompaction?: (info: {
|
|
436
440
|
messagesCompacted: number;
|
|
437
|
-
freedTokens
|
|
441
|
+
freedTokens?: number;
|
|
438
442
|
tokensBefore: number;
|
|
439
443
|
reused: boolean;
|
|
440
444
|
}) => void;
|
|
@@ -517,6 +521,8 @@ export declare function maybeCompact(opts: MaybeCompactOptions): Promise<{
|
|
|
517
521
|
* (`compaction_outcome{outcome:"noop"}`) reads this flag. */
|
|
518
522
|
noop?: true;
|
|
519
523
|
tokensBefore?: number;
|
|
524
|
+
/** The §25.2 STRUCTURAL pre/post delta in ONE coordinate — the only subtractable quantity here.
|
|
525
|
+
* Absent ⇒ the post measurement failed and no delta was taken. */
|
|
520
526
|
freedTokens?: number;
|
|
521
527
|
triggerTokens?: number;
|
|
522
528
|
/** P-13: post-compaction context size in the SAME coordinate as `triggerTokens` (estimate + anchor-less
|
|
@@ -627,6 +633,41 @@ export declare function maybeCompact(opts: MaybeCompactOptions): Promise<{
|
|
|
627
633
|
* ordinary truncation (disclosed, not silent). */
|
|
628
634
|
clampReason?: "budget" | "tolerance";
|
|
629
635
|
}>;
|
|
636
|
+
/** What a landed compaction hands the wire frame. Structural, so both the full `maybeCompact` result
|
|
637
|
+
* and the settle lane's narrower `EndOfTaskCompaction` satisfy it without either importing the other. */
|
|
638
|
+
export interface CompactedFrameSource {
|
|
639
|
+
tokensBefore?: number;
|
|
640
|
+
freedTokens?: number;
|
|
641
|
+
postTriggerTokens?: number;
|
|
642
|
+
triggerTokens?: number;
|
|
643
|
+
durationMs?: number;
|
|
644
|
+
phaseDurations?: CompactionPhaseDurations;
|
|
645
|
+
firstKeptEntryId?: string;
|
|
646
|
+
attachedFiles?: Array<{
|
|
647
|
+
path: string;
|
|
648
|
+
chars: number;
|
|
649
|
+
truncated: boolean;
|
|
650
|
+
}>;
|
|
651
|
+
modelFallback?: true;
|
|
652
|
+
fallbackReason?: "window";
|
|
653
|
+
clampedRatio?: number;
|
|
654
|
+
clampReason?: "budget" | "tolerance";
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* THE mint of the `compacted` wire frame — one function, three lanes (the turn boundary, the
|
|
658
|
+
* prompt-too-long recovery, the end-of-task settle). The three used to carry a verbatim copy of the
|
|
659
|
+
* same fourteen-line literal, which is how a field reaches the wire on two lanes out of three: a key
|
|
660
|
+
* added to one copy is invisible in the others' diffs, and the only guard against it was a test that
|
|
661
|
+
* grepped the SOURCE TEXT of all three for a matching line. A behavior can be pinned; a copy can only
|
|
662
|
+
* be spelled.
|
|
663
|
+
*
|
|
664
|
+
* What differs per lane is exactly `trigger` and the identity envelope, so those are the parameters;
|
|
665
|
+
* everything else is derived here, once. Absence semantics live on the event type
|
|
666
|
+
* ({@link import("./task-event.js").TaskEvent}) and are the same whichever lane fires.
|
|
667
|
+
*/
|
|
668
|
+
export declare function mintCompactedEvent(comp: CompactedFrameSource, trigger: "auto" | "manual" | "forced", identity: TaskEventIdentity): Extract<TaskEvent, {
|
|
669
|
+
type: "compacted";
|
|
670
|
+
}>;
|
|
630
671
|
/**
|
|
631
672
|
* design/123 D4 (r5) — trim-force BACKOFF transition (pure; the run-scoped bit lives in the caller).
|
|
632
673
|
* Spiral protection replacing the §25.2 floor's role on the trim-force path: trim pressure re-arms
|
|
@@ -478,7 +478,7 @@ export async function maybeCompact(opts) {
|
|
|
478
478
|
catch {
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
|
-
let freedTokens
|
|
481
|
+
let freedTokens;
|
|
482
482
|
let postTriggerTokens;
|
|
483
483
|
try {
|
|
484
484
|
const post = (await opts.session.buildContext()).messages;
|
|
@@ -502,6 +502,7 @@ export async function maybeCompact(opts) {
|
|
|
502
502
|
trigger,
|
|
503
503
|
summary,
|
|
504
504
|
tokensBefore: summaryTokensBefore,
|
|
505
|
+
...(freedTokens !== undefined ? { freedTokens } : {}),
|
|
505
506
|
...(postTriggerTokens !== undefined ? { tokensAfter: postTriggerTokens } : {}),
|
|
506
507
|
}), "compaction.postCompact");
|
|
507
508
|
}
|
|
@@ -534,6 +535,25 @@ export async function maybeCompact(opts) {
|
|
|
534
535
|
...(clampReason !== undefined ? { clampReason } : {}),
|
|
535
536
|
};
|
|
536
537
|
}
|
|
538
|
+
export function mintCompactedEvent(comp, trigger, identity) {
|
|
539
|
+
return {
|
|
540
|
+
type: "compacted",
|
|
541
|
+
trigger,
|
|
542
|
+
tokensBefore: comp.tokensBefore ?? 0,
|
|
543
|
+
...(comp.freedTokens !== undefined ? { freedTokens: comp.freedTokens } : {}),
|
|
544
|
+
...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
|
|
545
|
+
...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
|
|
546
|
+
...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
|
|
547
|
+
...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
|
|
548
|
+
...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
|
|
549
|
+
...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
|
|
550
|
+
...(comp.modelFallback ? { modelFallback: true } : {}),
|
|
551
|
+
...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
|
|
552
|
+
...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
|
|
553
|
+
...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
|
|
554
|
+
...identity,
|
|
555
|
+
};
|
|
556
|
+
}
|
|
537
557
|
export function nextTrimForceBackoff(prev, comp, trimForced = false) {
|
|
538
558
|
if (trimForced && comp.naturalTrigger !== true && comp.compacted && comp.freedTokens !== undefined && comp.freedTokens <= 0) {
|
|
539
559
|
return true;
|
package/dist/core/auto-mode.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AUTO_MODE_DEFAULT_TIMEOUT_MS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS, AUTO_MODE_DENIAL_LIMIT_DEFAULTS } from "./auto-mode-defaults.js";
|
|
2
|
+
import { thrownIs } from "./thrown-value.js";
|
|
2
3
|
import { describeRejectedValue } from "./tool-search-setting.js";
|
|
3
4
|
export const AUTO_MODE_UNAVAILABLE_CAUSES = ["error", "timeout"];
|
|
4
5
|
const AUTO_MODE_UNAVAILABLE_CAUSE_SET = new Set(AUTO_MODE_UNAVAILABLE_CAUSES);
|
|
@@ -286,14 +287,7 @@ class AutoModeTimeout extends Error {
|
|
|
286
287
|
super("auto-mode classify timeout");
|
|
287
288
|
}
|
|
288
289
|
}
|
|
289
|
-
|
|
290
|
-
try {
|
|
291
|
-
return e instanceof AutoModeTimeout;
|
|
292
|
-
}
|
|
293
|
-
catch {
|
|
294
|
-
return false;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
290
|
+
const isAutoModeTimeout = (e) => thrownIs(e, AutoModeTimeout);
|
|
297
291
|
export function readDenialLimitFallback(v) {
|
|
298
292
|
if (typeof v !== "object" || v === null)
|
|
299
293
|
return undefined;
|
package/dist/core/exec-gate.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isRemoteExecutionEnv, RemoteExecutionError } from "./remote-env.js";
|
|
2
|
+
import { readMember, thrownIs } from "./thrown-value.js";
|
|
2
3
|
const DEFAULT_MAX_OUTPUT_BYTES = 64 * 1024;
|
|
3
4
|
function clampBytes(s, maxBytes) {
|
|
4
5
|
const total = Buffer.byteLength(s, "utf8");
|
|
@@ -47,11 +48,8 @@ async function runStreamStep(env, step, options, maxOutputBytes) {
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
catch (e) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
: e?.name === "AbortError"
|
|
53
|
-
? "aborted"
|
|
54
|
-
: "unknown";
|
|
51
|
+
const remoteCode = thrownIs(e, RemoteExecutionError) ? readMember(e, "code") : undefined;
|
|
52
|
+
const code = typeof remoteCode === "string" ? remoteCode : readMember(e, "name") === "AbortError" ? "aborted" : "unknown";
|
|
55
53
|
return { label, command: step.command, exitCode: null, stdout: out.join(""), stderr: errOut.join(""), ok: false, errorCode: code, truncated };
|
|
56
54
|
}
|
|
57
55
|
return { label, command: step.command, exitCode, stdout: out.join(""), stderr: errOut.join(""), ok: exitCode === 0, truncated };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { thrownText } from "./thrown-value.js";
|
|
2
3
|
import { isAbsoluteForFamily, isAbsolutePathForm, isWinFormPath, pathFamilyOf } from "../tools/fs/safety.js";
|
|
3
4
|
import { fileHistoryBoundariesToKeep, resolveFileHistoryRetention } from "./file-history-retention.js";
|
|
4
5
|
const normSlash = (p) => p.replace(/\\/g, "/");
|
|
@@ -489,7 +490,7 @@ export class InMemoryFileHistoryStore {
|
|
|
489
490
|
return { ok: true, minted: true };
|
|
490
491
|
}
|
|
491
492
|
catch (err) {
|
|
492
|
-
return { ok: false, error: { code: "track_failed", message: `first-touch record for ${absPath} could not be persisted: ${err
|
|
493
|
+
return { ok: false, error: { code: "track_failed", message: `first-touch record for ${absPath} could not be persisted: ${thrownText(err)}` } };
|
|
493
494
|
}
|
|
494
495
|
}
|
|
495
496
|
async annulTrack(scope, absPath, root, verify) {
|
|
@@ -530,7 +531,7 @@ export class InMemoryFileHistoryStore {
|
|
|
530
531
|
return { ok: true };
|
|
531
532
|
}
|
|
532
533
|
catch (err) {
|
|
533
|
-
return { ok: false, error: { code: "track_failed", message: `annulling the first-touch record for ${absPath} failed: ${err
|
|
534
|
+
return { ok: false, error: { code: "track_failed", message: `annulling the first-touch record for ${absPath} failed: ${thrownText(err)}` } };
|
|
534
535
|
}
|
|
535
536
|
}
|
|
536
537
|
async snapshot(scope, entryId, env, root, signal) {
|
|
@@ -599,14 +600,14 @@ export class InMemoryFileHistoryStore {
|
|
|
599
600
|
}
|
|
600
601
|
catch (err) {
|
|
601
602
|
sc.spentAttempts.add(entryId);
|
|
602
|
-
return { ok: false, error: { code: "snapshot_failed", message: `boundary for entry "${entryId}" could not be committed: ${err
|
|
603
|
+
return { ok: false, error: { code: "snapshot_failed", message: `boundary for entry "${entryId}" could not be committed: ${thrownText(err)}` } };
|
|
603
604
|
}
|
|
604
605
|
this.applyBoundaryRetention(scope, entryId);
|
|
605
606
|
return { ok: true };
|
|
606
607
|
}
|
|
607
608
|
catch (err) {
|
|
608
609
|
sc.spentAttempts.add(entryId);
|
|
609
|
-
return { ok: false, error: { code: "snapshot_failed", message: err
|
|
610
|
+
return { ok: false, error: { code: "snapshot_failed", message: thrownText(err) } };
|
|
610
611
|
}
|
|
611
612
|
finally {
|
|
612
613
|
sc.activeAttempts.delete(entryId);
|
|
@@ -669,7 +670,7 @@ export class InMemoryFileHistoryStore {
|
|
|
669
670
|
});
|
|
670
671
|
}
|
|
671
672
|
catch (err) {
|
|
672
|
-
applied = { outcome: "failed", reason: err
|
|
673
|
+
applied = { outcome: "failed", reason: thrownText(err) };
|
|
673
674
|
}
|
|
674
675
|
if (applied.outcome === "applied")
|
|
675
676
|
ledger.filesChanged.push(key);
|
|
@@ -686,7 +687,7 @@ export class InMemoryFileHistoryStore {
|
|
|
686
687
|
}
|
|
687
688
|
catch (err) {
|
|
688
689
|
const touched = empty.filesChanged.length > 0 || empty.identicalSkipped.length > 0 || empty.refused.length > 0 || empty.failed.length > 0;
|
|
689
|
-
return { outcome: touched ? "partial" : "failed", ...empty, error: { code: "restore_failed", message: err
|
|
690
|
+
return { outcome: touched ? "partial" : "failed", ...empty, error: { code: "restore_failed", message: thrownText(err) } };
|
|
690
691
|
}
|
|
691
692
|
}
|
|
692
693
|
async canRestore(scope, entryId) {
|
|
@@ -793,7 +794,7 @@ export class InMemoryFileHistoryStore {
|
|
|
793
794
|
return { ok: true };
|
|
794
795
|
}
|
|
795
796
|
catch (err) {
|
|
796
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope failed: ${err
|
|
797
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope failed: ${thrownText(err)}` } };
|
|
797
798
|
}
|
|
798
799
|
}
|
|
799
800
|
async exportHistory(scope) {
|
|
@@ -846,7 +847,7 @@ export class InMemoryFileHistoryStore {
|
|
|
846
847
|
}
|
|
847
848
|
}
|
|
848
849
|
catch (err) {
|
|
849
|
-
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${err
|
|
850
|
+
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${thrownText(err)}` } };
|
|
850
851
|
}
|
|
851
852
|
}
|
|
852
853
|
async importStaged(scope, data, srcGetBlob, needed) {
|
|
@@ -860,7 +861,7 @@ export class InMemoryFileHistoryStore {
|
|
|
860
861
|
bytes = await srcGetBlob(hash);
|
|
861
862
|
}
|
|
862
863
|
catch (err) {
|
|
863
|
-
return { ok: false, error: { code: "unsupported_format", message: `source blob ${hash} fetch failed: ${err
|
|
864
|
+
return { ok: false, error: { code: "unsupported_format", message: `source blob ${hash} fetch failed: ${thrownText(err)}` } };
|
|
864
865
|
}
|
|
865
866
|
if (bytes === undefined)
|
|
866
867
|
return { ok: false, error: { code: "not_found", message: `source blob ${hash} is missing — the envelope's graph cannot be completed, so nothing is published` } };
|
|
@@ -892,7 +893,7 @@ export class InMemoryFileHistoryStore {
|
|
|
892
893
|
return { ok: true };
|
|
893
894
|
}
|
|
894
895
|
catch (err) {
|
|
895
|
-
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${err
|
|
896
|
+
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${thrownText(err)}` } };
|
|
896
897
|
}
|
|
897
898
|
}
|
|
898
899
|
}
|
package/dist/core/hooks.d.ts
CHANGED
|
@@ -515,8 +515,15 @@ export interface PostCompactContext {
|
|
|
515
515
|
trigger: "auto" | "manual" | "forced";
|
|
516
516
|
/** The conversation summary the compaction produced (CC `compact_summary` parity). */
|
|
517
517
|
summary: string;
|
|
518
|
+
/** DIAGNOSTIC, NOT subtractable: prepareCompaction's coordinate, LACKING the overhead term
|
|
519
|
+
* {@link tokensAfter} carries. Use {@link freedTokens}. */
|
|
518
520
|
tokensBefore?: number;
|
|
521
|
+
/** DIAGNOSTIC, NOT subtractable: always structural + prompt overhead, a different coordinate from
|
|
522
|
+
* {@link tokensBefore}, so the difference can go negative. Absent when the post measurement failed. */
|
|
519
523
|
tokensAfter?: number;
|
|
524
|
+
/** The engine's measured delta (clamped ≥ 0) — the ONE subtractable number here, and the same value
|
|
525
|
+
* this pass's `compacted` frame carries. Absent ⇒ the post measurement failed. */
|
|
526
|
+
freedTokens?: number;
|
|
520
527
|
/** {@link HookSeatSignal} — this invocation's own abort signal. */
|
|
521
528
|
signal?: AbortSignal;
|
|
522
529
|
}
|
package/dist/core/mcp.js
CHANGED
|
@@ -21,7 +21,7 @@ import { withContentOrigin } from "./memory-engine/content-origin.js";
|
|
|
21
21
|
import { snapshotMcpEntries } from "./locked-config.js";
|
|
22
22
|
import { validateJsonSchemaShape } from "./runner/strict-output-schema.js";
|
|
23
23
|
import { schemaKeyBoundProblem } from "./tool-roster.js";
|
|
24
|
-
import { thrownText } from "./thrown-value.js";
|
|
24
|
+
import { readMember, thrownIs, thrownName, thrownText } from "./thrown-value.js";
|
|
25
25
|
export const MCP_PREFIX = MCP_NAMESPACE.prefix;
|
|
26
26
|
const MCP_OUTPUT_TOKENS_DEFAULT = 25_000;
|
|
27
27
|
const MCP_CHARS_PER_TOKEN = 4;
|
|
@@ -187,7 +187,7 @@ function sanitizeMcpErrorTextInPlace(err) {
|
|
|
187
187
|
}
|
|
188
188
|
function namedMcpFailureText(err) {
|
|
189
189
|
const detail = remoteErrorText(err, { collapse: true });
|
|
190
|
-
const condition = err
|
|
190
|
+
const condition = thrownIs(err, McpError) ? describeMcpSpecErrorCode(readMember(err, "code")) : undefined;
|
|
191
191
|
return condition !== undefined ? `${condition}: ${detail}` : detail;
|
|
192
192
|
}
|
|
193
193
|
function remoteErrorText(err, opts) {
|
|
@@ -1769,9 +1769,11 @@ function asServerWarning(spec, err) {
|
|
|
1769
1769
|
}
|
|
1770
1770
|
function sanitizedCause(err) {
|
|
1771
1771
|
const copy = new Error(namedMcpFailureText(err));
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1772
|
+
const name = thrownName(err);
|
|
1773
|
+
if (name !== undefined) {
|
|
1774
|
+
if (name !== "")
|
|
1775
|
+
copy.name = name;
|
|
1776
|
+
const code = readMember(err, "code");
|
|
1775
1777
|
if (typeof code === "string" || typeof code === "number")
|
|
1776
1778
|
copy.code = code;
|
|
1777
1779
|
}
|
|
@@ -131,10 +131,13 @@ export type DistillerChatFn = (req: DistillerChatRequest) => Promise<DistillerCh
|
|
|
131
131
|
export declare function isAliasModelId(model: string): boolean;
|
|
132
132
|
/**
|
|
133
133
|
* An OpenAI-compatible chat seat over an explicit endpoint. Screened at CONSTRUCTION (the
|
|
134
|
-
* bad-value loudness law): a missing key
|
|
135
|
-
* is made — an alias can be re-pointed upstream and would move the
|
|
136
|
-
* the archived plan.
|
|
137
|
-
|
|
134
|
+
* bad-value loudness law): a missing key, an alias model id or an unservable request root refuses
|
|
135
|
+
* with a code before any call is made — an alias can be re-pointed upstream and would move the
|
|
136
|
+
* driven model with no trace in the archived plan.
|
|
137
|
+
*
|
|
138
|
+
* The root is judged by {@link assertServableRequestRoot} — the SAME law the brains apply, because
|
|
139
|
+
* emptiness alone let userinfo, a non-http(s) scheme and a non-URL spelling reach `fetch` as a
|
|
140
|
+
* TRANSPORT error. Only the ENVELOPE is this seat's; the driver routes config throws apart. */
|
|
138
141
|
export declare function openAiCompatChatSeat(seat: {
|
|
139
142
|
baseUrl: string;
|
|
140
143
|
apiKey: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readMember, thrownText } from "../thrown-value.js";
|
|
2
|
+
import { assertServableRequestRoot } from "../../brain/route-adjudicator.js";
|
|
2
3
|
export const DISTILLER_DEFAULT_MAX_INPUTS_PER_PRODUCT = 32;
|
|
3
4
|
const SIZE_CLAUSE = {
|
|
4
5
|
"dl-2": "- the index should be as small as it can be made without losing either of the above.",
|
|
@@ -132,8 +133,8 @@ function renderCandidate(n, c) {
|
|
|
132
133
|
return `[${n}] ${head}\n${String(c.entry?.body ?? "").trim()}`;
|
|
133
134
|
}
|
|
134
135
|
const fill = (tpl, vars) => Object.entries(vars).reduce((s, [k, v]) => s.split(`{{${k}}}`).join(String(v)), tpl);
|
|
135
|
-
function distillerConfigRefusal(message) {
|
|
136
|
-
const e = new Error(message);
|
|
136
|
+
function distillerConfigRefusal(message, cause) {
|
|
137
|
+
const e = (cause === undefined ? new Error(message) : new Error(message, { cause }));
|
|
137
138
|
e.code = "config.memory_consolidation_driver";
|
|
138
139
|
return e;
|
|
139
140
|
}
|
|
@@ -143,13 +144,20 @@ export function isAliasModelId(model) {
|
|
|
143
144
|
export function openAiCompatChatSeat(seat) {
|
|
144
145
|
if (typeof seat.baseUrl !== "string" || seat.baseUrl.trim() === "")
|
|
145
146
|
throw distillerConfigRefusal("memory consolidation driver chat seat needs a non-empty baseUrl.");
|
|
147
|
+
let requestRoot;
|
|
148
|
+
try {
|
|
149
|
+
requestRoot = (assertServableRequestRoot(seat.baseUrl, "memory consolidation driver chat seat baseUrl") ?? "").replace(/\/+$/, "");
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
throw distillerConfigRefusal(thrownText(e), e);
|
|
153
|
+
}
|
|
146
154
|
if (typeof seat.apiKey !== "string" || seat.apiKey === "")
|
|
147
155
|
throw distillerConfigRefusal("memory consolidation driver chat seat needs an api key — a driver that silently skips would publish an empty plan as a model's answer.");
|
|
148
156
|
if (typeof seat.model !== "string" || seat.model.trim() === "" || isAliasModelId(seat.model)) {
|
|
149
157
|
throw distillerConfigRefusal(`memory consolidation driver chat seat needs an EXPLICIT model id, got ${JSON.stringify(seat.model)} — an alias can be re-pointed upstream and would move the driver with no trace in the plan.`);
|
|
150
158
|
}
|
|
151
159
|
return async (req) => {
|
|
152
|
-
const res = await fetch(`${
|
|
160
|
+
const res = await fetch(`${requestRoot}/chat/completions`, {
|
|
153
161
|
method: "POST",
|
|
154
162
|
headers: { "content-type": "application/json", authorization: `Bearer ${seat.apiKey}` },
|
|
155
163
|
body: JSON.stringify({
|
package/dist/core/memory.js
CHANGED
|
@@ -46,6 +46,7 @@ const SECRET_PATTERNS = [
|
|
|
46
46
|
{ label: "stripe_secret_key", re: /\b[sr]k_(?:live|test)_[A-Za-z0-9]{24,}\b/ },
|
|
47
47
|
{ label: "slack_token", re: /\bxox[baprs]-(?:[A-Za-z0-9]+-){1,3}[A-Za-z0-9]{16,}\b/ },
|
|
48
48
|
{ label: "google_api_key", re: /\bAIza[0-9A-Za-z_-]{35}\b/ },
|
|
49
|
+
{ label: "huggingface_token", re: /\bhf_(?=[A-Za-z0-9]*[0-9])[A-Za-z0-9]{20,}\b/ },
|
|
49
50
|
{ label: "private_key", re: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----/ },
|
|
50
51
|
{ label: "jwt", re: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{16,}\b/ },
|
|
51
52
|
{ label: "azure_storage_account_key", re: /AccountKey=[A-Za-z0-9+/]{40,}={0,2}/ },
|
|
@@ -2,6 +2,7 @@ import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
|
|
|
2
2
|
import { extractErrorCode, stripErrorCodePrefix } from "../../brain/errors.js";
|
|
3
3
|
import { terminalProjection } from "./terminal-projection.js";
|
|
4
4
|
import { haltConsumed } from "./halt-attribution.js";
|
|
5
|
+
import { isErrorLike, readMember } from "../thrown-value.js";
|
|
5
6
|
import { describeRejectedValue } from "../tool-search-setting.js";
|
|
6
7
|
const SALVAGE_ELIGIBLE_TERMINALS = new Set([
|
|
7
8
|
"output.degenerate",
|
|
@@ -13,33 +14,25 @@ const SALVAGE_ELIGIBLE_TERMINALS = new Set([
|
|
|
13
14
|
"usage.window_exhausted",
|
|
14
15
|
]);
|
|
15
16
|
function thrownMessage(threw) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return m;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
17
|
+
if (isErrorLike(threw)) {
|
|
18
|
+
const m = readMember(threw, "message");
|
|
19
|
+
if (typeof m === "string")
|
|
20
|
+
return m;
|
|
24
21
|
}
|
|
25
22
|
return describeRejectedValue(threw);
|
|
26
23
|
}
|
|
27
24
|
export function errorCodeOf(err) {
|
|
28
25
|
let cur = err;
|
|
29
26
|
let fallback;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
return code;
|
|
36
|
-
}
|
|
37
|
-
fallback ??= code;
|
|
27
|
+
for (let depth = 0; cur !== null && cur !== undefined && typeof cur === "object" && depth < 8; depth++) {
|
|
28
|
+
const code = readMember(cur, "code");
|
|
29
|
+
if (typeof code === "string" && code) {
|
|
30
|
+
if (code !== "unknown") {
|
|
31
|
+
return code;
|
|
38
32
|
}
|
|
39
|
-
|
|
33
|
+
fallback ??= code;
|
|
40
34
|
}
|
|
41
|
-
|
|
42
|
-
catch {
|
|
35
|
+
cur = readMember(cur, "cause");
|
|
43
36
|
}
|
|
44
37
|
return fallback;
|
|
45
38
|
}
|
|
@@ -43,6 +43,16 @@ export async function prepareFileHistory(input) {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
const fileHistoryEnabled = fileHistoryStore !== undefined && handsEnabled;
|
|
46
|
+
if (!fileHistoryEnabled && (handsEnabled || fileHistoryStore !== undefined) && deps.onError !== undefined && !toldAlready(deps.onError, fileHistoryStore === undefined ? "no-store" : "no-env")) {
|
|
47
|
+
const reason = fileHistoryStore === undefined
|
|
48
|
+
? `this deployment wired no RunnerDeps.fileHistoryStore, so NOTHING is recorded: no first-touch snapshot before an edit, no turn boundary, and a later restoreFiles / rewindFilesTo has nothing to restore from and will refuse (rewind.store_unconfigured). Supply a store, or accept an unrecoverable working tree knowingly`
|
|
49
|
+
: `RunnerDeps.fileHistoryStore is wired but this run mounts no filesystem-capable ExecutionEnv, so the store is INERT: there is no working tree to snapshot and nothing will ever be written to it. Wire RunnerDeps.executionEnv, or drop the store from this deployment shape`;
|
|
50
|
+
try {
|
|
51
|
+
deps.onError(new Error(`file history is not live for this run — ${reason}.`), { phase: "config", sessionId });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
46
56
|
const { historyRoot, historyScope, historyFs } = await resolveFileHistoryCoordinates(fileHistoryEnabled, executionEnv, taskRootFinal, internals?.fileHistoryLineage, sessionId);
|
|
47
57
|
if (fileHistoryStore !== undefined && internals?.fileHistoryLineage === undefined)
|
|
48
58
|
await adoptForkedFileHistory(fileHistoryStore, session, sessionId, deps.onError);
|
|
@@ -197,6 +207,15 @@ function rewindRefusalTail(form) {
|
|
|
197
207
|
: `Either the boundary does not exist (its turns ran without a RunnerDeps.fileHistoryStore, or it was reaped), or it was produced in the retired whole-tree snapshot era, which this engine's per-edited-file seat does not restore.`;
|
|
198
208
|
}
|
|
199
209
|
const FILE_HISTORY_BOUNDARY_TIMEOUT_MS = 30_000;
|
|
210
|
+
const FILE_HISTORY_LIVENESS_MEMO = new WeakMap();
|
|
211
|
+
function toldAlready(sink, arm) {
|
|
212
|
+
const heard = FILE_HISTORY_LIVENESS_MEMO.get(sink) ?? new Set();
|
|
213
|
+
FILE_HISTORY_LIVENESS_MEMO.set(sink, heard);
|
|
214
|
+
if (heard.has(arm))
|
|
215
|
+
return true;
|
|
216
|
+
heard.add(arm);
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
200
219
|
const FILE_HISTORY_CARRY_MEMO = new WeakMap();
|
|
201
220
|
async function adoptForkedFileHistory(store, session, sessionId, onError) {
|
|
202
221
|
const memo = FILE_HISTORY_CARRY_MEMO.get(store) ?? { settled: new Set(), disclosed: new Set(), inFlight: new Map() };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_COMPACTION_SETTINGS } from "../../internal/harness.js";
|
|
2
2
|
import { planRejectionClears } from "../context-edit.js";
|
|
3
3
|
import { landStaleResultClears } from "./prepare-context-lane.js";
|
|
4
|
-
import { DEFAULT_COMPACTION_INSTRUCTIONS, maybeCompact } from "../auto-compaction.js";
|
|
4
|
+
import { DEFAULT_COMPACTION_INSTRUCTIONS, maybeCompact, mintCompactedEvent } from "../auto-compaction.js";
|
|
5
5
|
import { emitTrace } from "../trace.js";
|
|
6
6
|
import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
|
|
7
7
|
import { rebaseCadenceWindows } from "./turn-attachments.js";
|
|
@@ -48,26 +48,10 @@ export function runRecoveryLanes(input) {
|
|
|
48
48
|
if (comp.compacted) {
|
|
49
49
|
compactionBreaker.failures = 0;
|
|
50
50
|
recordCompactionReuse(runner, prepared, comp);
|
|
51
|
-
if ((comp.freedTokens ?? 0) >= COMPACTION_FREED_EPSILON) {
|
|
52
|
-
|
|
53
|
-
rs.counters.compactionFloor = Math.ceil(postSize * COMPACTION_REGROWTH_FACTOR);
|
|
51
|
+
if ((comp.freedTokens ?? 0) >= COMPACTION_FREED_EPSILON && comp.postTriggerTokens !== undefined) {
|
|
52
|
+
rs.counters.compactionFloor = Math.ceil(comp.postTriggerTokens * COMPACTION_REGROWTH_FACTOR);
|
|
54
53
|
}
|
|
55
|
-
queue.push(
|
|
56
|
-
type: "compacted",
|
|
57
|
-
trigger: "forced",
|
|
58
|
-
tokensBefore: comp.tokensBefore ?? 0,
|
|
59
|
-
...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
|
|
60
|
-
...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
|
|
61
|
-
...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
|
|
62
|
-
...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
|
|
63
|
-
...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
|
|
64
|
-
...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
|
|
65
|
-
...(comp.modelFallback ? { modelFallback: true } : {}),
|
|
66
|
-
...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
|
|
67
|
-
...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
|
|
68
|
-
...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
|
|
69
|
-
...ident(),
|
|
70
|
-
});
|
|
54
|
+
queue.push(mintCompactedEvent(comp, "forced", ident()));
|
|
71
55
|
if (comp.phaseDurations !== undefined && comp.durationMs !== undefined) {
|
|
72
56
|
const pd = comp.phaseDurations;
|
|
73
57
|
const pdDur = comp.durationMs;
|
|
@@ -20,27 +20,13 @@ import { generatePromptSuggestions } from "./prompt-suggestions.js";
|
|
|
20
20
|
import { settleTeardownLeg } from "./teardown-bounded.js";
|
|
21
21
|
import { autoRunConsolidationFromRecommendation, autoRunOnRecommendationEffective, scopeHasUnconsumedRecommendation } from "./memory-consolidation-driver.js";
|
|
22
22
|
import { amendTerminal, terminalProjection } from "./terminal-projection.js";
|
|
23
|
+
import { mintCompactedEvent } from "../auto-compaction.js";
|
|
23
24
|
import { asThrownError } from "../thrown-value.js";
|
|
24
25
|
export async function runSettleAndTeardown(input) {
|
|
25
26
|
const { spec, queue, prepared, resume, internals, rs, stats, ident, parentToolCallId, subagentName, loopLatch, timeout, ownCommittedTailRef, emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, owedUserInput, setResult, onSuggestions, onSuspend, runner, sessions } = input;
|
|
26
27
|
try {
|
|
27
28
|
if (comp?.compacted) {
|
|
28
|
-
queue.push(
|
|
29
|
-
type: "compacted",
|
|
30
|
-
trigger: "auto",
|
|
31
|
-
tokensBefore: comp.tokensBefore ?? 0,
|
|
32
|
-
...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
|
|
33
|
-
...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
|
|
34
|
-
...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
|
|
35
|
-
...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
|
|
36
|
-
...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
|
|
37
|
-
...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
|
|
38
|
-
...(comp.modelFallback ? { modelFallback: true } : {}),
|
|
39
|
-
...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
|
|
40
|
-
...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
|
|
41
|
-
...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
|
|
42
|
-
...ident(),
|
|
43
|
-
});
|
|
29
|
+
queue.push(mintCompactedEvent(comp, "auto", ident()));
|
|
44
30
|
if (comp.phaseDurations !== undefined && comp.durationMs !== undefined) {
|
|
45
31
|
const pd = comp.phaseDurations;
|
|
46
32
|
const pdDur = comp.durationMs;
|