@caupulican/pi-agent-core 0.93.3 → 0.93.5
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/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +9 -4
- package/dist/agent-loop.js.map +1 -1
- package/dist/session/session-manager.d.ts +4 -1
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +45 -4
- package/dist/session/session-manager.js.map +1 -1
- package/dist/tool-failure-memory.d.ts +9 -1
- package/dist/tool-failure-memory.d.ts.map +1 -1
- package/dist/tool-failure-memory.js +98 -41
- package/dist/tool-failure-memory.js.map +1 -1
- package/dist/tool-failure-recovery-gate.d.ts +4 -2
- package/dist/tool-failure-recovery-gate.d.ts.map +1 -1
- package/dist/tool-failure-recovery-gate.js +33 -7
- package/dist/tool-failure-recovery-gate.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -19,6 +19,8 @@ export interface ToolFailureMemoryRecord {
|
|
|
19
19
|
phase: ToolFailurePhase;
|
|
20
20
|
failureCode: string;
|
|
21
21
|
diagnostic?: string;
|
|
22
|
+
/** Bounded tool-owned source evidence needed to construct a changed operation. */
|
|
23
|
+
evidence?: string;
|
|
22
24
|
correction: string;
|
|
23
25
|
attemptMemory?: "discard";
|
|
24
26
|
}
|
|
@@ -37,6 +39,8 @@ export interface ToolFailureDirectiveDetails {
|
|
|
37
39
|
}
|
|
38
40
|
export type ToolFailureResultDetails = ToolFailureMemoryDetails | ToolFailureDirectiveDetails;
|
|
39
41
|
export type ToolFailureMemoryTracker = Map<string, ToolFailureMemoryRecord>;
|
|
42
|
+
/** Normalize and bound tool-owned evidence at every live and persisted ingress. */
|
|
43
|
+
export declare function sanitizeToolFailureEvidence(value: unknown): string | undefined;
|
|
40
44
|
export declare function normalizeToolSignature(pairs: Array<[string, unknown]>): string;
|
|
41
45
|
export declare function getToolExecutionKey(tool: string, args: unknown): string;
|
|
42
46
|
/** Read the four hash words already encoded by this module's exact execution-key owner. */
|
|
@@ -62,7 +66,11 @@ export interface ToolFailureAssessment {
|
|
|
62
66
|
failureCode: string;
|
|
63
67
|
phase: ToolFailurePhase;
|
|
64
68
|
diagnostic?: string;
|
|
69
|
+
/** Bounded raw-output tail of an executed process-exit failure. */
|
|
70
|
+
evidence?: string;
|
|
65
71
|
guidance: string;
|
|
72
|
+
/** Catalogued per-error guidance; set only when a registry policy matched the failure message. */
|
|
73
|
+
policyGuidance?: string;
|
|
66
74
|
attemptMemory?: "discard";
|
|
67
75
|
}
|
|
68
76
|
export declare function assessToolFailure(message: string, state: ToolFailureState, errorClass?: string): ToolFailureAssessment;
|
|
@@ -76,7 +84,7 @@ export interface ToolFailureTelemetry {
|
|
|
76
84
|
/** Read only bounded failure identity and guidance; operation arguments never cross this telemetry boundary. */
|
|
77
85
|
export declare function readToolFailureTelemetry(details: unknown): ToolFailureTelemetry | undefined;
|
|
78
86
|
export declare function createToolFailureMemoryTracker(messages: AgentMessage[]): ToolFailureMemoryTracker;
|
|
79
|
-
export declare function rememberToolFailure(tracker: ToolFailureMemoryTracker, tool: string, args: unknown, state: ToolFailureState, failureCode: string, correction: string, diagnostic?: string, phase?: ToolFailurePhase): ToolFailureMemoryRecord;
|
|
87
|
+
export declare function rememberToolFailure(tracker: ToolFailureMemoryTracker, tool: string, args: unknown, state: ToolFailureState, failureCode: string, correction: string, diagnostic?: string, phase?: ToolFailurePhase, evidence?: string): ToolFailureMemoryRecord;
|
|
80
88
|
export declare function clearToolFailure(tracker: ToolFailureMemoryTracker, tool: string, args: unknown): void;
|
|
81
89
|
export declare function createToolFailureResult(record: ToolFailureMemoryRecord, terminate?: boolean): AgentToolResult<ToolFailureResultDetails>;
|
|
82
90
|
export declare function createRepeatedToolFailureResult(record: ToolFailureMemoryRecord): AgentToolResult<ToolFailureMemoryDetails>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-failure-memory.d.ts","sourceRoot":"","sources":["../src/tool-failure-memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,gBAAgB,EACrB,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAKnF,OAAO,KAAK,EAAE,YAAY,EAAiB,eAAe,EAAE,MAAM,YAAY,CAAC;AAG/E,QAAA,MAAM,2BAA2B,IAAI,CAAC;AACtC,QAAA,MAAM,8BAA8B,IAAI,CAAC;AACzC,QAAA,MAAM,0BAA0B,eAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-failure-memory.d.ts","sourceRoot":"","sources":["../src/tool-failure-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,9 @@ const TOOL_FAILURE_EXECUTION_KEY = Symbol("ToolFailureExecutionKey");
|
|
|
7
7
|
const MAX_OPERATION_CHARS = 240;
|
|
8
8
|
const MAX_FAILURE_CODE_CHARS = 48;
|
|
9
9
|
const MAX_DIAGNOSTIC_CHARS = 240;
|
|
10
|
-
const MAX_CORRECTION_CHARS =
|
|
10
|
+
const MAX_CORRECTION_CHARS = 480;
|
|
11
|
+
const MAX_TOOL_FAILURE_EVIDENCE_CHARS = 1_600;
|
|
12
|
+
const MAX_ACTIVE_FAILURE_EVIDENCE_CHARS = 2_400;
|
|
11
13
|
const MAX_TOOL_NAME_CHARS = 64;
|
|
12
14
|
const TOOL_SIGNATURE_HEX_CHARS = 32;
|
|
13
15
|
const MAX_ACTIVE_FAILURES = 8;
|
|
@@ -25,6 +27,13 @@ function truncate(value, maxChars) {
|
|
|
25
27
|
end--;
|
|
26
28
|
return `${value.slice(0, end)}…`;
|
|
27
29
|
}
|
|
30
|
+
/** Normalize and bound tool-owned evidence at every live and persisted ingress. */
|
|
31
|
+
export function sanitizeToolFailureEvidence(value) {
|
|
32
|
+
if (typeof value !== "string")
|
|
33
|
+
return undefined;
|
|
34
|
+
const sanitized = sanitizeBinaryOutput(value).trim();
|
|
35
|
+
return sanitized ? truncate(sanitized, MAX_TOOL_FAILURE_EVIDENCE_CHARS) : undefined;
|
|
36
|
+
}
|
|
28
37
|
function truncateMiddle(value, maxChars) {
|
|
29
38
|
if (value.length <= maxChars)
|
|
30
39
|
return value;
|
|
@@ -429,6 +438,19 @@ function boundedFailureCode(value) {
|
|
|
429
438
|
* always the last line it appends — outranks any earlier, non-authoritative line that matches.
|
|
430
439
|
*/
|
|
431
440
|
const EXIT_STATUS_LINE_PATTERN = /^(?:\S+\s+)?(?:exit(?:ed)?(?:\s+with)?(?:\s+code)?|exitcode)\s*[:=]?\s*(-?\d+)\b/i;
|
|
441
|
+
/**
|
|
442
|
+
* bash.ts appends `cwd: <dir>` after its exit trailer on failures. The line is harness status, not
|
|
443
|
+
* a cause: it must never displace a real diagnostic (a path may contain words like "error"), and it
|
|
444
|
+
* reaches the model through the process-exit evidence tail instead.
|
|
445
|
+
*/
|
|
446
|
+
const CWD_STATUS_LINE_PATTERN = /^cwd:\s/i;
|
|
447
|
+
/** Tool-owned status/marker lines that carry no cause and never belong in diagnostic or evidence. */
|
|
448
|
+
function isFailureStatusLine(line) {
|
|
449
|
+
return (/^command (?:exited with code|timed out after|aborted|killed after)\b/i.test(line) ||
|
|
450
|
+
/^outcome:\s*(?:failed|aborted|timeout|output_limit)\b/i.test(line) ||
|
|
451
|
+
/^exitcode:\s*-?\d+\b/i.test(line) ||
|
|
452
|
+
/^(?:stdout|stderr):(?:\s*\(empty\))?$/i.test(line));
|
|
453
|
+
}
|
|
432
454
|
function processExitFailureCode(message) {
|
|
433
455
|
const lines = message.split(/\r\n|\n/);
|
|
434
456
|
for (let index = lines.length - 1; index >= 0; index--) {
|
|
@@ -513,7 +535,9 @@ function extractFailureDiagnostic(message, allowUnclassifiedFallback, requireStr
|
|
|
513
535
|
const stderrLines = rawLines
|
|
514
536
|
.slice(stderrMarkerIndex + 1)
|
|
515
537
|
.map((line) => line.trim())
|
|
516
|
-
.filter((line) => line.length > 0 &&
|
|
538
|
+
.filter((line) => line.length > 0 &&
|
|
539
|
+
!/^command (?:exited with code|timed out after|aborted|killed after)\b/i.test(line) &&
|
|
540
|
+
!CWD_STATUS_LINE_PATTERN.test(line));
|
|
517
541
|
if (stderrLines.length > 0) {
|
|
518
542
|
const classified = stderrLines.find((line) => strongDiagnosticPattern.test(line));
|
|
519
543
|
if (classified)
|
|
@@ -530,11 +554,7 @@ function extractFailureDiagnostic(message, allowUnclassifiedFallback, requireStr
|
|
|
530
554
|
}
|
|
531
555
|
const lines = rawLines
|
|
532
556
|
.map((line) => line.trim())
|
|
533
|
-
.filter((line) => line.length > 0 &&
|
|
534
|
-
!/^command (?:exited with code|timed out after|aborted|killed after)\b/i.test(line) &&
|
|
535
|
-
!/^outcome:\s*(?:failed|aborted|timeout|output_limit)\b/i.test(line) &&
|
|
536
|
-
!/^exitcode:\s*-?\d+\b/i.test(line) &&
|
|
537
|
-
!/^(?:stdout|stderr):(?:\s*\(empty\))?$/i.test(line));
|
|
557
|
+
.filter((line) => line.length > 0 && !isFailureStatusLine(line) && !CWD_STATUS_LINE_PATTERN.test(line));
|
|
538
558
|
if (lines.length === 0)
|
|
539
559
|
return undefined;
|
|
540
560
|
const diagnosticPattern = requireStrongSignal
|
|
@@ -546,6 +566,35 @@ function extractFailureDiagnostic(message, allowUnclassifiedFallback, requireStr
|
|
|
546
566
|
const diagnostic = classified ?? (allowUnclassifiedFallback ? lines.at(-1) : undefined);
|
|
547
567
|
return diagnostic ? truncateMiddle(diagnostic, MAX_DIAGNOSTIC_CHARS) : undefined;
|
|
548
568
|
}
|
|
569
|
+
/**
|
|
570
|
+
* Bounded raw-output tail of an executed process-exit failure. Evidence is the raw-data channel:
|
|
571
|
+
* it keeps the trailing lines that strong-signal diagnostic classification refuses to promote, so
|
|
572
|
+
* strictness never destroys the output needed to construct a changed operation.
|
|
573
|
+
*/
|
|
574
|
+
function extractProcessExitEvidence(message) {
|
|
575
|
+
const lines = sanitizeBinaryOutput(message)
|
|
576
|
+
.replaceAll("\r\n", "\n")
|
|
577
|
+
.split("\n")
|
|
578
|
+
.map((line) => line.trim())
|
|
579
|
+
.filter((line) => line.length > 0 && !isFailureStatusLine(line));
|
|
580
|
+
if (lines.length === 0)
|
|
581
|
+
return undefined;
|
|
582
|
+
let start = lines.length - 1;
|
|
583
|
+
let retainedChars = lines[start].length;
|
|
584
|
+
while (start > 0 && retainedChars + 1 + lines[start - 1].length <= MAX_TOOL_FAILURE_EVIDENCE_CHARS) {
|
|
585
|
+
start--;
|
|
586
|
+
retainedChars += 1 + lines[start].length;
|
|
587
|
+
}
|
|
588
|
+
let tail = lines.slice(start).join("\n");
|
|
589
|
+
if (tail.length > MAX_TOOL_FAILURE_EVIDENCE_CHARS) {
|
|
590
|
+
let tailStart = tail.length - MAX_TOOL_FAILURE_EVIDENCE_CHARS;
|
|
591
|
+
const firstCode = tail.charCodeAt(tailStart);
|
|
592
|
+
if (firstCode >= 0xdc00 && firstCode <= 0xdfff)
|
|
593
|
+
tailStart++;
|
|
594
|
+
tail = tail.slice(tailStart);
|
|
595
|
+
}
|
|
596
|
+
return sanitizeToolFailureEvidence(tail);
|
|
597
|
+
}
|
|
549
598
|
export function assessToolFailure(message, state, errorClass) {
|
|
550
599
|
const policy = getToolExecutionErrorPolicy(message);
|
|
551
600
|
const exitFailureCode = processExitFailureCode(message);
|
|
@@ -553,14 +602,17 @@ export function assessToolFailure(message, state, errorClass) {
|
|
|
553
602
|
const diagnostic = state === "failed" && (!policy || policy.retainDiagnostic)
|
|
554
603
|
? extractFailureDiagnostic(message, exitFailureCode === undefined && (errorClass !== undefined || retainPolicyDiagnostic), exitFailureCode !== undefined && !retainPolicyDiagnostic)
|
|
555
604
|
: undefined;
|
|
605
|
+
const evidence = state === "failed" && exitFailureCode !== undefined ? extractProcessExitEvidence(message) : undefined;
|
|
556
606
|
const failureCode = policy?.failureCode ?? classifyToolFailure(message, errorClass);
|
|
557
607
|
return {
|
|
558
608
|
failureCode,
|
|
559
609
|
phase: policy?.phase ?? inferToolFailurePhase(state, failureCode),
|
|
560
610
|
...(diagnostic ? { diagnostic } : {}),
|
|
611
|
+
...(evidence ? { evidence } : {}),
|
|
561
612
|
guidance: policy
|
|
562
613
|
? truncate(policy.guidance, MAX_CORRECTION_CHARS)
|
|
563
614
|
: fallbackFailureGuidance(state, diagnostic !== undefined, inferToolFailurePhase(state, failureCode)),
|
|
615
|
+
...(policy ? { policyGuidance: truncate(policy.guidance, MAX_CORRECTION_CHARS) } : {}),
|
|
564
616
|
...(policy?.attemptMemory === "discard" ? { attemptMemory: "discard" } : {}),
|
|
565
617
|
};
|
|
566
618
|
}
|
|
@@ -583,6 +635,7 @@ function readFailureRecord(details) {
|
|
|
583
635
|
return undefined;
|
|
584
636
|
}
|
|
585
637
|
const diagnostic = typeof candidate.diagnostic === "string" ? truncate(candidate.diagnostic, MAX_DIAGNOSTIC_CHARS) : undefined;
|
|
638
|
+
const evidence = sanitizeToolFailureEvidence(candidate.evidence);
|
|
586
639
|
const retainedCorrection = typeof candidate.correction === "string" ? truncate(candidate.correction, MAX_CORRECTION_CHARS) : undefined;
|
|
587
640
|
const correction = candidate.state === "failed" && retainedCorrection === LEGACY_GENERIC_EXECUTION_CORRECTION
|
|
588
641
|
? fallbackFailureGuidance("failed", diagnostic !== undefined, "execution")
|
|
@@ -606,6 +659,7 @@ function readFailureRecord(details) {
|
|
|
606
659
|
phase,
|
|
607
660
|
failureCode: boundedFailureCode(candidate.failureCode),
|
|
608
661
|
diagnostic,
|
|
662
|
+
evidence,
|
|
609
663
|
correction,
|
|
610
664
|
};
|
|
611
665
|
}
|
|
@@ -750,6 +804,7 @@ function analyzeToolFailureContext(messages) {
|
|
|
750
804
|
phase: retained?.phase ?? assessment?.phase ?? inferToolFailurePhase(state, "tool_error"),
|
|
751
805
|
failureCode: retained?.failureCode ?? assessment?.failureCode ?? "tool_error",
|
|
752
806
|
diagnostic: retained?.diagnostic ?? assessment?.diagnostic,
|
|
807
|
+
evidence: retained?.evidence,
|
|
753
808
|
correction: retained?.correction ??
|
|
754
809
|
assessment?.guidance ??
|
|
755
810
|
fallbackFailureGuidance(state, false, inferToolFailurePhase(state, "tool_error")),
|
|
@@ -840,59 +895,50 @@ function analyzeToolFailureContext(messages) {
|
|
|
840
895
|
export function createToolFailureMemoryTracker(messages) {
|
|
841
896
|
return new Map(analyzeToolFailureContext(messages).activeRecords.map((record) => [record.failureKey, record]));
|
|
842
897
|
}
|
|
843
|
-
export function rememberToolFailure(tracker, tool, args, state, failureCode, correction, diagnostic, phase = inferToolFailurePhase(state, failureCode)) {
|
|
898
|
+
export function rememberToolFailure(tracker, tool, args, state, failureCode, correction, diagnostic, phase = inferToolFailurePhase(state, failureCode), evidence) {
|
|
844
899
|
let kindCount = 1;
|
|
845
900
|
for (const previous of tracker.values()) {
|
|
846
901
|
if (previous.tool === tool) {
|
|
847
902
|
kindCount = Math.max(kindCount, (previous.kindMistakes ?? previous.occurrence) + 1);
|
|
848
903
|
}
|
|
849
904
|
}
|
|
850
|
-
|
|
905
|
+
const isDiscard = getToolExecutionAttemptMemory(failureCode) === "discard";
|
|
906
|
+
if (isDiscard) {
|
|
851
907
|
for (const [failureKey, previous] of tracker) {
|
|
852
908
|
if (previous.tool === tool && previous.failureCode === failureCode)
|
|
853
909
|
tracker.delete(failureKey);
|
|
854
910
|
}
|
|
855
|
-
return {
|
|
856
|
-
version: TOOL_FAILURE_MEMORY_VERSION,
|
|
857
|
-
failureKey: `directive:${boundedFailureCode(failureCode)}`,
|
|
858
|
-
[TOOL_FAILURE_EXECUTION_KEY]: getToolExecutionKey(tool, args),
|
|
859
|
-
tool: truncate(tool, MAX_TOOL_NAME_CHARS),
|
|
860
|
-
operation: "[discarded]",
|
|
861
|
-
occurrence: 1,
|
|
862
|
-
kindMistakes: kindCount,
|
|
863
|
-
mistakeKind: tool,
|
|
864
|
-
state,
|
|
865
|
-
phase,
|
|
866
|
-
failureCode: boundedFailureCode(failureCode),
|
|
867
|
-
diagnostic: diagnostic ? truncate(diagnostic, MAX_DIAGNOSTIC_CHARS) : undefined,
|
|
868
|
-
correction: truncate(correction, MAX_CORRECTION_CHARS),
|
|
869
|
-
attemptMemory: "discard",
|
|
870
|
-
};
|
|
871
911
|
}
|
|
872
|
-
const identity = operationIdentity(tool, args);
|
|
873
|
-
const previous = tracker.get(identity.failureKey);
|
|
912
|
+
const identity = isDiscard ? undefined : operationIdentity(tool, args);
|
|
913
|
+
const previous = identity ? tracker.get(identity.failureKey) : undefined;
|
|
874
914
|
const record = {
|
|
875
915
|
version: TOOL_FAILURE_MEMORY_VERSION,
|
|
876
|
-
failureKey: identity.failureKey
|
|
877
|
-
[TOOL_FAILURE_EXECUTION_KEY]: identity.executionKey,
|
|
878
|
-
tool: identity.tool,
|
|
879
|
-
operation: identity.operation,
|
|
880
|
-
occurrence: (previous?.occurrence ?? 0) + 1,
|
|
916
|
+
failureKey: identity ? identity.failureKey : `directive:${boundedFailureCode(failureCode)}`,
|
|
917
|
+
[TOOL_FAILURE_EXECUTION_KEY]: identity ? identity.executionKey : getToolExecutionKey(tool, args),
|
|
918
|
+
tool: identity ? identity.tool : truncate(tool, MAX_TOOL_NAME_CHARS),
|
|
919
|
+
operation: identity ? identity.operation : "[discarded]",
|
|
920
|
+
occurrence: isDiscard ? 1 : (previous?.occurrence ?? 0) + 1,
|
|
881
921
|
kindMistakes: kindCount,
|
|
882
922
|
mistakeKind: tool,
|
|
883
923
|
state,
|
|
884
924
|
phase,
|
|
885
925
|
failureCode: boundedFailureCode(failureCode),
|
|
886
926
|
diagnostic: diagnostic ? truncate(diagnostic, MAX_DIAGNOSTIC_CHARS) : undefined,
|
|
927
|
+
evidence: sanitizeToolFailureEvidence(evidence),
|
|
887
928
|
correction: truncate(correction, MAX_CORRECTION_CHARS),
|
|
929
|
+
...(isDiscard ? { attemptMemory: "discard" } : {}),
|
|
888
930
|
};
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
931
|
+
if (isDiscard)
|
|
932
|
+
return record;
|
|
933
|
+
if (identity) {
|
|
934
|
+
tracker.delete(identity.failureKey);
|
|
935
|
+
tracker.set(identity.failureKey, record);
|
|
936
|
+
while (tracker.size > MAX_TRACKED_FAILURES) {
|
|
937
|
+
const oldest = tracker.keys().next().value;
|
|
938
|
+
if (oldest === undefined)
|
|
939
|
+
break;
|
|
940
|
+
tracker.delete(oldest);
|
|
941
|
+
}
|
|
896
942
|
}
|
|
897
943
|
return record;
|
|
898
944
|
}
|
|
@@ -908,7 +954,7 @@ function failureGuidance(record) {
|
|
|
908
954
|
? { repair: record.correction }
|
|
909
955
|
: { next_action: record.correction };
|
|
910
956
|
}
|
|
911
|
-
function formatRecordJson(record, includeOperation = false) {
|
|
957
|
+
function formatRecordJson(record, includeOperation = false, evidence = record.evidence) {
|
|
912
958
|
const guidance = failureGuidance(record);
|
|
913
959
|
return JSON.stringify({
|
|
914
960
|
...mandatoryToolFailureRecoveryMetadata(),
|
|
@@ -922,6 +968,7 @@ function formatRecordJson(record, includeOperation = false) {
|
|
|
922
968
|
...(includeOperation ? { operation: record.operation } : {}),
|
|
923
969
|
failure_code: record.failureCode,
|
|
924
970
|
...(record.diagnostic ? { diagnostic: record.diagnostic } : {}),
|
|
971
|
+
...(evidence ? { evidence } : {}),
|
|
925
972
|
...guidance,
|
|
926
973
|
...(record.attemptMemory === "discard" ? { attempt_memory: "discarded" } : {}),
|
|
927
974
|
});
|
|
@@ -1020,7 +1067,17 @@ export function sanitizeToolFailureContext(messages, systemPrompt) {
|
|
|
1020
1067
|
const kindSummary = Object.entries(analysis.kindMistakesSummary)
|
|
1021
1068
|
.map(([kind, count]) => `${kind}:${count}`)
|
|
1022
1069
|
.join(", ");
|
|
1023
|
-
|
|
1070
|
+
let remainingEvidenceChars = MAX_ACTIVE_FAILURE_EVIDENCE_CHARS;
|
|
1071
|
+
const evidenceByFailureKey = new Map();
|
|
1072
|
+
for (let index = records.length - 1; index >= 0 && remainingEvidenceChars > 1; index--) {
|
|
1073
|
+
const record = records[index];
|
|
1074
|
+
if (!record.evidence)
|
|
1075
|
+
continue;
|
|
1076
|
+
const retained = truncate(record.evidence, remainingEvidenceChars);
|
|
1077
|
+
evidenceByFailureKey.set(record.failureKey, retained);
|
|
1078
|
+
remainingEvidenceChars -= retained.length;
|
|
1079
|
+
}
|
|
1080
|
+
const lines = records.map((record) => escapePromptData(formatRecordJson(record, true, evidenceByFailureKey.get(record.failureKey) ?? null)));
|
|
1024
1081
|
for (const directive of analysis.activeDirectives) {
|
|
1025
1082
|
lines.push(escapePromptData(JSON.stringify({
|
|
1026
1083
|
...mandatoryToolFailureRecoveryMetadata(),
|