@caupulican/pi-agent-core 0.93.8 → 0.93.10

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.
@@ -1 +1 @@
1
- {"version":3,"file":"tool-failure-memory.d.ts","sourceRoot":"","sources":["../src/tool-failure-memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-failure-memory.d.ts","sourceRoot":"","sources":["../src/tool-failure-memory.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { getToolExecutionAttemptMemory, getToolExecutionErrorPolicy, } from "@caupulican/pi-ai/tool-repair-registry";
2
- import { MANDATORY_TOOL_FAILURE_RECOVERY_PROTOCOL_PROMPT, mandatoryToolFailureRecoveryMetadata, } from "./tool-failure-recovery-protocol.js";
2
+ import { MANDATORY_TOOL_FAILURE_RECOVERY_PROTOCOL_PROMPT, mandatoryToolFailureRecoveryMetadata, TOOL_FAILURE_READMISSION_RULE, } from "./tool-failure-recovery-protocol.js";
3
3
  import { sanitizeBinaryOutput } from "./utils/shell-output.js";
4
4
  const TOOL_FAILURE_MEMORY_VERSION = 1;
5
5
  const TOOL_FAILURE_DIRECTIVE_VERSION = 1;
@@ -9,7 +9,6 @@ const MAX_FAILURE_CODE_CHARS = 48;
9
9
  const MAX_DIAGNOSTIC_CHARS = 240;
10
10
  const MAX_CORRECTION_CHARS = 480;
11
11
  const MAX_TOOL_FAILURE_EVIDENCE_CHARS = 1_600;
12
- const MAX_ACTIVE_FAILURE_EVIDENCE_CHARS = 2_400;
13
12
  const MAX_TOOL_NAME_CHARS = 64;
14
13
  const TOOL_SIGNATURE_HEX_CHARS = 32;
15
14
  const TOOL_FALLBACK_OUTPUT_SIGNATURE_BASE62_CHARS = 22;
@@ -19,8 +18,7 @@ const MAX_ACTIVE_FAILURES = 8;
19
18
  const MAX_TRACKED_FAILURES = 64;
20
19
  const REPAIRABLE_REJECTION_CODES = new Set(["invalid_arguments", "malformed_call", "unknown_tool"]);
21
20
  const LEGACY_GENERIC_EXECUTION_CORRECTION = "Change the arguments or approach before retrying; do not resend the unchanged operation.";
22
- const BLOCKED_REPLAY_CAVEMAN_CORRECTION = "Blocked: this exact operation will not run again this session change the operation or continue other work.";
23
- const CLOSED_OPERATION_CAVEMAN_CORRECTION = "Closed: this exact operation was not executed and will not run again this session — use a different operation or continue other work.";
21
+ const BLOCKED_REPLAY_CORRECTION = `Not executed: its last result is already above. Do corrective work or use a different operation. ${TOOL_FAILURE_READMISSION_RULE}`;
24
22
  function truncate(value, maxChars) {
25
23
  if (value.length <= maxChars)
26
24
  return value;
@@ -373,9 +371,6 @@ export function readVisibleToolFailureCode(result) {
373
371
  }
374
372
  return undefined;
375
373
  }
376
- export function isClosedOperationFailureCode(code) {
377
- return code === "operation_recovery_exhausted" || code === "recovery_exhausted";
378
- }
379
374
  /** Failures that only a new owner prompt can clear. Do not restore their circuit across user turns. */
380
375
  export function isPromptScopedFailureCode(code) {
381
376
  return code === "owner_authorization_required";
@@ -390,6 +385,10 @@ export function restoreToolFailureRecord(result, tool, args) {
390
385
  };
391
386
  }
392
387
  const identity = operationIdentity(tool, args);
388
+ // A completed operation that reported a negative status keeps its own raw output, so there is no
389
+ // harness record to read back. Recover its terminal status from that output rather than flattening
390
+ // every such result to a generic `tool_error`.
391
+ const visibleCode = readVisibleToolFailureCode(result);
393
392
  return {
394
393
  version: TOOL_FAILURE_MEMORY_VERSION,
395
394
  failureKey: identity.failureKey,
@@ -399,7 +398,7 @@ export function restoreToolFailureRecord(result, tool, args) {
399
398
  occurrence: 1,
400
399
  state: "failed",
401
400
  phase: "execution",
402
- failureCode: boundedFailureCode(readVisibleToolFailureCode(result) ?? "tool_error"),
401
+ failureCode: boundedFailureCode(visibleCode ?? classifyToolFailure(firstText(result))),
403
402
  correction: fallbackFailureGuidance("failed", false, "execution"),
404
403
  };
405
404
  }
@@ -429,19 +428,6 @@ export function forEachPairedToolResult(messages, visit) {
429
428
  }
430
429
  }
431
430
  }
432
- export function transcriptHasClosedToolOperation(messages) {
433
- const closedByExecutionKey = new Map();
434
- forEachPairedToolResult(messages, ({ executionKey, result }) => {
435
- if (!result.isError) {
436
- closedByExecutionKey.delete(executionKey);
437
- return;
438
- }
439
- if (isClosedOperationFailureCode(readVisibleToolFailureCode(result))) {
440
- closedByExecutionKey.set(executionKey, true);
441
- }
442
- });
443
- return closedByExecutionKey.size > 0;
444
- }
445
431
  function boundedFailureCode(value) {
446
432
  const normalized = value
447
433
  .trim()
@@ -762,8 +748,18 @@ function fastTextSignature(text) {
762
748
  }
763
749
  function analyzeToolFailureContext(messages) {
764
750
  const callById = new Map();
751
+ /**
752
+ * A call the agent made is erased only in two cases: a superseded success, whose newer identical
753
+ * call is still present, and a discard-attempt directive, where the harness has taken ownership of
754
+ * the attempt and the original arguments must not come back — either because it holds the payload
755
+ * by reference (a retarget) or because replaying those bytes is itself the hazard (an encoding
756
+ * corruption). Never for an ordinary failure: being told to change an operation is unactionable
757
+ * once the operation itself is gone.
758
+ */
765
759
  const omittedCallIds = new Set();
766
- const orphanFailedResults = new Set();
760
+ const omittedResults = new Set();
761
+ /** Unbounded failure results to replace in place with their bounded record. */
762
+ const boundedReplacements = new Map();
767
763
  const active = new Map();
768
764
  const activeDirectives = new Map();
769
765
  let sequence = 0;
@@ -788,8 +784,18 @@ function analyzeToolFailureContext(messages) {
788
784
  const call = callById.get(message.toolCallId);
789
785
  callById.delete(message.toolCallId);
790
786
  const textPayload = firstText(message);
791
- const isFailure = message.isError === true || textPayload.startsWith("[harness] ");
792
- if (isFailure) {
787
+ // A completed operation reporting its own negative status is evidence, not a mistake: it never
788
+ // enters the ledger and its output stays exactly as the tool wrote it. It does resolve any
789
+ // earlier failure recorded for the same operation, though — a tool that could not run before
790
+ // has now run — so a transcript that predates this classification cannot keep an obsolete
791
+ // record active across the boundary.
792
+ if (message.errorKind === "operation_outcome") {
793
+ if (call)
794
+ active.delete(getToolFailureKey(call.name, call.arguments));
795
+ continue;
796
+ }
797
+ const isHarnessFailure = message.isError === true || textPayload.startsWith("[harness] ");
798
+ if (isHarnessFailure) {
793
799
  const toolName = call?.name ?? message.toolName;
794
800
  const kindCount = (kindMistakesMap.get(toolName) ?? 0) + 1;
795
801
  kindMistakesMap.set(toolName, kindCount);
@@ -797,10 +803,13 @@ function analyzeToolFailureContext(messages) {
797
803
  if (directive) {
798
804
  activeDirectives.delete(directive.failureCode);
799
805
  activeDirectives.set(directive.failureCode, directive);
806
+ // The harness has taken ownership of this attempt: the directive replaces it, and the
807
+ // original arguments must not reappear — a retarget keeps the payload by reference, and a
808
+ // corrupt payload must never be replayed at all. Either way the call comes out.
800
809
  if (call)
801
810
  omittedCallIds.add(call.id);
802
811
  else
803
- orphanFailedResults.add(message);
812
+ omittedResults.add(message);
804
813
  continue;
805
814
  }
806
815
  const retained = readFailureRecord(message.details);
@@ -854,10 +863,12 @@ function analyzeToolFailureContext(messages) {
854
863
  break;
855
864
  active.delete(oldest);
856
865
  }
857
- if (call)
858
- omittedCallIds.add(call.id);
859
- else
860
- orphanFailedResults.add(message);
866
+ // A failure result written before this harness bounded its own output — a legacy transcript,
867
+ // or a host that set isError directly — can carry unbounded raw text. Bounding it in place
868
+ // is the same treatment createToolFailureResult gives a fresh failure, applied late; the
869
+ // call that produced it still stands.
870
+ if (!retained)
871
+ boundedReplacements.set(message, record);
861
872
  continue;
862
873
  }
863
874
  if (call) {
@@ -878,16 +889,26 @@ function analyzeToolFailureContext(messages) {
878
889
  }
879
890
  }
880
891
  const kindMistakesSummary = Object.fromEntries(kindMistakesMap);
881
- if (omittedCallIds.size === 0 && orphanFailedResults.size === 0) {
882
- return { messages, activeRecords: [], activeDirectives: [], kindMistakesSummary };
892
+ const activeRecords = [...active.values()]
893
+ .sort((left, right) => left.sequence - right.sequence)
894
+ .map(({ record }) => record);
895
+ if (omittedCallIds.size === 0 && omittedResults.size === 0 && boundedReplacements.size === 0) {
896
+ return { messages, activeRecords, activeDirectives: [...activeDirectives.values()], kindMistakesSummary };
883
897
  }
884
898
  const filteredMessages = [];
885
899
  for (let index = 0; index < messages.length; index++) {
886
900
  const message = messages[index];
887
901
  if (message.role === "toolResult") {
888
- if (omittedCallIds.has(message.toolCallId) || orphanFailedResults.has(message))
902
+ if (omittedCallIds.has(message.toolCallId) || omittedResults.has(message))
889
903
  continue;
890
- filteredMessages.push(message);
904
+ const bounded = boundedReplacements.get(message);
905
+ filteredMessages.push(bounded
906
+ ? {
907
+ ...message,
908
+ content: [{ type: "text", text: `[harness] ${formatRecordJson(bounded, false)}` }],
909
+ details: { piToolFailureMemory: bounded },
910
+ }
911
+ : message);
891
912
  continue;
892
913
  }
893
914
  if (message.role !== "assistant") {
@@ -919,9 +940,6 @@ function analyzeToolFailureContext(messages) {
919
940
  filteredMessages.push({ ...message, content: retainedContent });
920
941
  }
921
942
  }
922
- const activeRecords = [...active.values()]
923
- .sort((left, right) => left.sequence - right.sequence)
924
- .map(({ record }) => record);
925
943
  return {
926
944
  messages: filteredMessages,
927
945
  activeRecords,
@@ -982,6 +1000,29 @@ export function rememberToolFailure(tracker, tool, args, state, failureCode, cor
982
1000
  }
983
1001
  return record;
984
1002
  }
1003
+ /**
1004
+ * Describe a completed operation that reported a negative status, without recording it as a mistake.
1005
+ *
1006
+ * The tool did its job, so nothing enters failure memory, nothing rewrites the tool's output, and no
1007
+ * correction is owed. The record exists only so the repetition governor can name the operation if the
1008
+ * agent replays it while nothing has changed.
1009
+ */
1010
+ export function describeOperationOutcome(tool, args, failureCode, diagnostic) {
1011
+ const identity = operationIdentity(tool, args);
1012
+ return {
1013
+ version: TOOL_FAILURE_MEMORY_VERSION,
1014
+ failureKey: identity.failureKey,
1015
+ [TOOL_FAILURE_EXECUTION_KEY]: identity.executionKey,
1016
+ tool: identity.tool,
1017
+ operation: identity.operation,
1018
+ occurrence: 1,
1019
+ state: "failed",
1020
+ phase: "execution",
1021
+ failureCode: boundedFailureCode(failureCode),
1022
+ ...(diagnostic ? { diagnostic: truncate(diagnostic, MAX_DIAGNOSTIC_CHARS) } : {}),
1023
+ correction: BLOCKED_REPLAY_CORRECTION,
1024
+ };
1025
+ }
985
1026
  export function clearToolFailure(tracker, tool, args) {
986
1027
  const failureKey = getToolFailureKey(tool, args);
987
1028
  const record = tracker.get(failureKey);
@@ -1040,14 +1081,19 @@ export function createToolFailureResult(record, terminate) {
1040
1081
  }
1041
1082
  export function createRepeatedToolFailureResult(record) {
1042
1083
  const retainedRecord = retainBlockedToolFailure(record);
1043
- const replayNotice = truncateMiddle(`The unchanged operation was not executed. Unchanged replay blocked after ${record.failureCode}`, MAX_DIAGNOSTIC_CHARS);
1084
+ // The note states why this call did not run and what makes it runnable again; the retained
1085
+ // root-cause correction stays the next_action, because that is the actionable half. Evidence is
1086
+ // left out: nothing executed, so there is none — the prior run's evidence is still in the
1087
+ // transcript, and repeating it here would only pay for the same bytes twice.
1088
+ const replayNotice = truncateMiddle(`Not executed: unchanged. ${TOOL_FAILURE_READMISSION_RULE}`, MAX_DIAGNOSTIC_CHARS);
1044
1089
  const blockedResult = createToolFailureResult({
1045
1090
  ...retainedRecord,
1091
+ evidence: undefined,
1046
1092
  state: "rejected",
1047
1093
  failureCode: "repeated_failed_operation",
1048
1094
  ...(retainedRecord.diagnostic
1049
1095
  ? { note: replayNotice }
1050
- : { diagnostic: replayNotice, correction: BLOCKED_REPLAY_CAVEMAN_CORRECTION }),
1096
+ : { diagnostic: replayNotice, correction: BLOCKED_REPLAY_CORRECTION }),
1051
1097
  });
1052
1098
  return {
1053
1099
  ...blockedResult,
@@ -1057,36 +1103,6 @@ export function createRepeatedToolFailureResult(record) {
1057
1103
  details: { piToolFailureMemory: retainedRecord },
1058
1104
  };
1059
1105
  }
1060
- export function createToolFailureRecoveryExhaustedResult(record, note) {
1061
- const retainedRecord = retainBlockedToolFailure(record);
1062
- const exhaustedResult = createToolFailureResult({
1063
- ...retainedRecord,
1064
- state: "rejected",
1065
- failureCode: "recovery_exhausted",
1066
- note: truncateMiddle(note, MAX_DIAGNOSTIC_CHARS),
1067
- correction: "Stop retrying tools in this run. Report the unresolved failure and the user or environment action required to continue.",
1068
- }, true);
1069
- return {
1070
- ...exhaustedResult,
1071
- details: { piToolFailureMemory: retainedRecord },
1072
- };
1073
- }
1074
- export function createToolFailureOperationExhaustedResult(record, note) {
1075
- const retainedRecord = {
1076
- ...retainBlockedToolFailure(record),
1077
- correction: CLOSED_OPERATION_CAVEMAN_CORRECTION,
1078
- };
1079
- const exhaustedResult = createToolFailureResult({
1080
- ...retainedRecord,
1081
- state: "rejected",
1082
- failureCode: "operation_recovery_exhausted",
1083
- note: truncateMiddle(note, MAX_DIAGNOSTIC_CHARS),
1084
- }, false);
1085
- return {
1086
- ...exhaustedResult,
1087
- details: { piToolFailureMemory: retainedRecord },
1088
- };
1089
- }
1090
1106
  function retainBlockedToolFailure(record) {
1091
1107
  return {
1092
1108
  ...record,
@@ -1107,17 +1123,9 @@ export function sanitizeToolFailureContext(messages, systemPrompt) {
1107
1123
  const kindSummary = Object.entries(analysis.kindMistakesSummary)
1108
1124
  .map(([kind, count]) => `${kind}:${count}`)
1109
1125
  .join(", ");
1110
- let remainingEvidenceChars = MAX_ACTIVE_FAILURE_EVIDENCE_CHARS;
1111
- const evidenceByFailureKey = new Map();
1112
- for (let index = records.length - 1; index >= 0 && remainingEvidenceChars > 1; index--) {
1113
- const record = records[index];
1114
- if (!record.evidence)
1115
- continue;
1116
- const retained = truncate(record.evidence, remainingEvidenceChars);
1117
- evidenceByFailureKey.set(record.failureKey, retained);
1118
- remainingEvidenceChars -= retained.length;
1119
- }
1120
- const lines = records.map((record) => escapePromptData(formatRecordJson(record, true, evidenceByFailureKey.get(record.failureKey) ?? null)));
1126
+ // Evidence is not repeated here: the failed call and its bounded record both remain in the
1127
+ // transcript, so the ledger only has to name what is still unresolved and what to do about it.
1128
+ const lines = records.map((record) => escapePromptData(formatRecordJson(record, true, null)));
1121
1129
  for (const directive of analysis.activeDirectives) {
1122
1130
  lines.push(escapePromptData(JSON.stringify({
1123
1131
  ...mandatoryToolFailureRecoveryMetadata(),