@caupulican/pi-agent-core 0.90.12 → 0.91.3

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.
@@ -0,0 +1,27 @@
1
+ import type { AssistantMessage } from "@caupulican/pi-ai/types";
2
+ /** Consecutive identical non-empty units (lines or sentences) at or above this run count are degeneration. */
3
+ export declare const DEGENERATE_REPEATED_LINE_MIN = 4;
4
+ /** Mid-stream abort once a generation loop is already this long; cheaper than waiting for `done`. */
5
+ export declare const DEGENERATE_STREAM_ABORT_RUN = 8;
6
+ /** Shortest unit that may be an exact tiled status sentence (`Foo.Foo.` with no space). */
7
+ export declare const DEGENERATE_EXACT_REPEAT_MIN = 24;
8
+ /** Smallest power-of-two prose tile that repeats to `text` (`Foo.Foo.` / `Foo.`×4). */
9
+ export declare function exactTiledRepeat(text: string): {
10
+ unit: string;
11
+ times: number;
12
+ } | undefined;
13
+ /**
14
+ * Collapse consecutive identical assistant lines, period-2 ABAB line runs, and the same
15
+ * sentence repeated inside one paragraph. Session 01a0016f stored 551 copies of one
16
+ * sentence as a single line; newline-only collapse cannot see that.
17
+ * Session 01a00337 stored the same status sentence concatenated with no space (`Foo.Foo.`)
18
+ * because Responses deltas replayed the full sentence; whitespace split cannot see that.
19
+ */
20
+ export declare function collapseRepeatedLines(text: string): string;
21
+ export declare function isDegenerateRepeatedText(text: string): boolean;
22
+ export declare function shouldAbortDegenerateStream(text: string): boolean;
23
+ export declare function collapseDegenerateAssistantMessage(message: AssistantMessage): AssistantMessage;
24
+ /** True when this message is (or was collapsed from) a generation loop. */
25
+ export declare function isCollapsedDegenerateAssistantMessage(message: AssistantMessage): boolean;
26
+ export declare function assistantMessageText(message: AssistantMessage): string;
27
+ //# sourceMappingURL=degenerate-assistant-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"degenerate-assistant-text.d.ts","sourceRoot":"","sources":["../src/degenerate-assistant-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,8GAA8G;AAC9G,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,qGAAqG;AACrG,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,2FAA2F;AAC3F,eAAO,MAAM,2BAA2B,KAAK,CAAC;AA6D9C,uFAAuF;AACvF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAY1F;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW1D;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjE;AAID,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAsB9F;AAED,2EAA2E;AAC3E,wBAAgB,qCAAqC,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAExF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAKtE"}
@@ -0,0 +1,150 @@
1
+ /** Consecutive identical non-empty units (lines or sentences) at or above this run count are degeneration. */
2
+ export const DEGENERATE_REPEATED_LINE_MIN = 4;
3
+ /** Mid-stream abort once a generation loop is already this long; cheaper than waiting for `done`. */
4
+ export const DEGENERATE_STREAM_ABORT_RUN = 8;
5
+ /** Shortest unit that may be an exact tiled status sentence (`Foo.Foo.` with no space). */
6
+ export const DEGENERATE_EXACT_REPEAT_MIN = 24;
7
+ function collapseRepeatedUnits(units, joinWith) {
8
+ if (units.length < DEGENERATE_REPEATED_LINE_MIN)
9
+ return units.join(joinWith);
10
+ const out = [];
11
+ let index = 0;
12
+ while (index < units.length) {
13
+ const unit = units[index];
14
+ let run = 1;
15
+ while (index + run < units.length && units[index + run] === unit)
16
+ run++;
17
+ if (unit.trim() !== "" && run >= DEGENERATE_REPEATED_LINE_MIN) {
18
+ out.push(unit);
19
+ index += run;
20
+ continue;
21
+ }
22
+ if (index + 1 < units.length) {
23
+ const next = units[index + 1];
24
+ if (unit.trim() !== "" && next.trim() !== "" && unit !== next) {
25
+ let pairs = 1;
26
+ while (index + (pairs + 1) * 2 <= units.length &&
27
+ units[index + pairs * 2] === unit &&
28
+ units[index + pairs * 2 + 1] === next) {
29
+ pairs++;
30
+ }
31
+ if (pairs >= DEGENERATE_REPEATED_LINE_MIN) {
32
+ out.push(unit, next);
33
+ index += pairs * 2;
34
+ continue;
35
+ }
36
+ }
37
+ }
38
+ out.push(unit);
39
+ index++;
40
+ }
41
+ return out.join(joinWith);
42
+ }
43
+ function maxRepeatedUnitRun(units) {
44
+ let maxRun = 1;
45
+ let run = 1;
46
+ for (let index = 1; index < units.length; index++) {
47
+ if (units[index] === units[index - 1] && units[index].trim() !== "") {
48
+ run++;
49
+ if (run > maxRun)
50
+ maxRun = run;
51
+ }
52
+ else {
53
+ run = 1;
54
+ }
55
+ }
56
+ return units.length === 0 ? 0 : maxRun;
57
+ }
58
+ function splitSentences(text) {
59
+ return text.split(/(?<=[.!?])\s+/);
60
+ }
61
+ function isProseTile(unit) {
62
+ return /[.!?]/.test(unit) || /\s/.test(unit);
63
+ }
64
+ /** Smallest power-of-two prose tile that repeats to `text` (`Foo.Foo.` / `Foo.`×4). */
65
+ export function exactTiledRepeat(text) {
66
+ if (text.length < DEGENERATE_EXACT_REPEAT_MIN * 2)
67
+ return undefined;
68
+ let unit = text;
69
+ let times = 1;
70
+ while (unit.length >= DEGENERATE_EXACT_REPEAT_MIN * 2 && unit.length % 2 === 0) {
71
+ const half = unit.length / 2;
72
+ const next = unit.slice(0, half);
73
+ if (!isProseTile(next) || next !== unit.slice(half))
74
+ break;
75
+ unit = next;
76
+ times *= 2;
77
+ }
78
+ return times > 1 ? { unit, times } : undefined;
79
+ }
80
+ /**
81
+ * Collapse consecutive identical assistant lines, period-2 ABAB line runs, and the same
82
+ * sentence repeated inside one paragraph. Session 01a0016f stored 551 copies of one
83
+ * sentence as a single line; newline-only collapse cannot see that.
84
+ * Session 01a00337 stored the same status sentence concatenated with no space (`Foo.Foo.`)
85
+ * because Responses deltas replayed the full sentence; whitespace split cannot see that.
86
+ */
87
+ export function collapseRepeatedLines(text) {
88
+ const tiled = exactTiledRepeat(text);
89
+ const source = tiled ? tiled.unit : text;
90
+ const lineCollapsed = collapseRepeatedUnits(source.split("\n"), "\n");
91
+ return lineCollapsed
92
+ .split("\n")
93
+ .map((line) => {
94
+ const lineTile = exactTiledRepeat(line);
95
+ return collapseRepeatedUnits(splitSentences(lineTile ? lineTile.unit : line), " ");
96
+ })
97
+ .join("\n");
98
+ }
99
+ export function isDegenerateRepeatedText(text) {
100
+ return collapseRepeatedLines(text) !== text;
101
+ }
102
+ export function shouldAbortDegenerateStream(text) {
103
+ if (text.length < 400)
104
+ return false;
105
+ const tiled = exactTiledRepeat(text);
106
+ if (tiled && tiled.times >= DEGENERATE_STREAM_ABORT_RUN)
107
+ return true;
108
+ const sentences = splitSentences(text);
109
+ if (maxRepeatedUnitRun(sentences) >= DEGENERATE_STREAM_ABORT_RUN)
110
+ return true;
111
+ return maxRepeatedUnitRun(text.split("\n")) >= DEGENERATE_STREAM_ABORT_RUN;
112
+ }
113
+ const collapsedDegenerateMessages = new WeakSet();
114
+ export function collapseDegenerateAssistantMessage(message) {
115
+ let changed = false;
116
+ const seenText = new Set();
117
+ const content = [];
118
+ for (const block of message.content) {
119
+ if (block.type !== "text") {
120
+ content.push(block);
121
+ continue;
122
+ }
123
+ const collapsed = collapseRepeatedLines(block.text);
124
+ if (collapsed !== block.text)
125
+ changed = true;
126
+ if (collapsed.trim() !== "" && seenText.has(collapsed)) {
127
+ changed = true;
128
+ continue;
129
+ }
130
+ if (collapsed.trim() !== "")
131
+ seenText.add(collapsed);
132
+ content.push(collapsed === block.text ? block : { ...block, text: collapsed });
133
+ }
134
+ if (!changed)
135
+ return message;
136
+ const next = { ...message, content };
137
+ collapsedDegenerateMessages.add(next);
138
+ return next;
139
+ }
140
+ /** True when this message is (or was collapsed from) a generation loop. */
141
+ export function isCollapsedDegenerateAssistantMessage(message) {
142
+ return collapsedDegenerateMessages.has(message);
143
+ }
144
+ export function assistantMessageText(message) {
145
+ return message.content
146
+ .filter((block) => block.type === "text")
147
+ .map((block) => block.text)
148
+ .join("\n");
149
+ }
150
+ //# sourceMappingURL=degenerate-assistant-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"degenerate-assistant-text.js","sourceRoot":"","sources":["../src/degenerate-assistant-text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@caupulican/pi-ai/types\";\n\n/** Consecutive identical non-empty units (lines or sentences) at or above this run count are degeneration. */\nexport const DEGENERATE_REPEATED_LINE_MIN = 4;\n\n/** Mid-stream abort once a generation loop is already this long; cheaper than waiting for `done`. */\nexport const DEGENERATE_STREAM_ABORT_RUN = 8;\n\n/** Shortest unit that may be an exact tiled status sentence (`Foo.Foo.` with no space). */\nexport const DEGENERATE_EXACT_REPEAT_MIN = 24;\n\nfunction collapseRepeatedUnits(units: readonly string[], joinWith: string): string {\n\tif (units.length < DEGENERATE_REPEATED_LINE_MIN) return units.join(joinWith);\n\tconst out: string[] = [];\n\tlet index = 0;\n\twhile (index < units.length) {\n\t\tconst unit = units[index];\n\t\tlet run = 1;\n\t\twhile (index + run < units.length && units[index + run] === unit) run++;\n\t\tif (unit.trim() !== \"\" && run >= DEGENERATE_REPEATED_LINE_MIN) {\n\t\t\tout.push(unit);\n\t\t\tindex += run;\n\t\t\tcontinue;\n\t\t}\n\t\tif (index + 1 < units.length) {\n\t\t\tconst next = units[index + 1];\n\t\t\tif (unit.trim() !== \"\" && next.trim() !== \"\" && unit !== next) {\n\t\t\t\tlet pairs = 1;\n\t\t\t\twhile (\n\t\t\t\t\tindex + (pairs + 1) * 2 <= units.length &&\n\t\t\t\t\tunits[index + pairs * 2] === unit &&\n\t\t\t\t\tunits[index + pairs * 2 + 1] === next\n\t\t\t\t) {\n\t\t\t\t\tpairs++;\n\t\t\t\t}\n\t\t\t\tif (pairs >= DEGENERATE_REPEATED_LINE_MIN) {\n\t\t\t\t\tout.push(unit, next);\n\t\t\t\t\tindex += pairs * 2;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tout.push(unit);\n\t\tindex++;\n\t}\n\treturn out.join(joinWith);\n}\n\nfunction maxRepeatedUnitRun(units: readonly string[]): number {\n\tlet maxRun = 1;\n\tlet run = 1;\n\tfor (let index = 1; index < units.length; index++) {\n\t\tif (units[index] === units[index - 1] && units[index].trim() !== \"\") {\n\t\t\trun++;\n\t\t\tif (run > maxRun) maxRun = run;\n\t\t} else {\n\t\t\trun = 1;\n\t\t}\n\t}\n\treturn units.length === 0 ? 0 : maxRun;\n}\n\nfunction splitSentences(text: string): string[] {\n\treturn text.split(/(?<=[.!?])\\s+/);\n}\n\nfunction isProseTile(unit: string): boolean {\n\treturn /[.!?]/.test(unit) || /\\s/.test(unit);\n}\n\n/** Smallest power-of-two prose tile that repeats to `text` (`Foo.Foo.` / `Foo.`×4). */\nexport function exactTiledRepeat(text: string): { unit: string; times: number } | undefined {\n\tif (text.length < DEGENERATE_EXACT_REPEAT_MIN * 2) return undefined;\n\tlet unit = text;\n\tlet times = 1;\n\twhile (unit.length >= DEGENERATE_EXACT_REPEAT_MIN * 2 && unit.length % 2 === 0) {\n\t\tconst half = unit.length / 2;\n\t\tconst next = unit.slice(0, half);\n\t\tif (!isProseTile(next) || next !== unit.slice(half)) break;\n\t\tunit = next;\n\t\ttimes *= 2;\n\t}\n\treturn times > 1 ? { unit, times } : undefined;\n}\n\n/**\n * Collapse consecutive identical assistant lines, period-2 ABAB line runs, and the same\n * sentence repeated inside one paragraph. Session 01a0016f stored 551 copies of one\n * sentence as a single line; newline-only collapse cannot see that.\n * Session 01a00337 stored the same status sentence concatenated with no space (`Foo.Foo.`)\n * because Responses deltas replayed the full sentence; whitespace split cannot see that.\n */\nexport function collapseRepeatedLines(text: string): string {\n\tconst tiled = exactTiledRepeat(text);\n\tconst source = tiled ? tiled.unit : text;\n\tconst lineCollapsed = collapseRepeatedUnits(source.split(\"\\n\"), \"\\n\");\n\treturn lineCollapsed\n\t\t.split(\"\\n\")\n\t\t.map((line) => {\n\t\t\tconst lineTile = exactTiledRepeat(line);\n\t\t\treturn collapseRepeatedUnits(splitSentences(lineTile ? lineTile.unit : line), \" \");\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nexport function isDegenerateRepeatedText(text: string): boolean {\n\treturn collapseRepeatedLines(text) !== text;\n}\n\nexport function shouldAbortDegenerateStream(text: string): boolean {\n\tif (text.length < 400) return false;\n\tconst tiled = exactTiledRepeat(text);\n\tif (tiled && tiled.times >= DEGENERATE_STREAM_ABORT_RUN) return true;\n\tconst sentences = splitSentences(text);\n\tif (maxRepeatedUnitRun(sentences) >= DEGENERATE_STREAM_ABORT_RUN) return true;\n\treturn maxRepeatedUnitRun(text.split(\"\\n\")) >= DEGENERATE_STREAM_ABORT_RUN;\n}\n\nconst collapsedDegenerateMessages = new WeakSet<AssistantMessage>();\n\nexport function collapseDegenerateAssistantMessage(message: AssistantMessage): AssistantMessage {\n\tlet changed = false;\n\tconst seenText = new Set<string>();\n\tconst content: AssistantMessage[\"content\"] = [];\n\tfor (const block of message.content) {\n\t\tif (block.type !== \"text\") {\n\t\t\tcontent.push(block);\n\t\t\tcontinue;\n\t\t}\n\t\tconst collapsed = collapseRepeatedLines(block.text);\n\t\tif (collapsed !== block.text) changed = true;\n\t\tif (collapsed.trim() !== \"\" && seenText.has(collapsed)) {\n\t\t\tchanged = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (collapsed.trim() !== \"\") seenText.add(collapsed);\n\t\tcontent.push(collapsed === block.text ? block : { ...block, text: collapsed });\n\t}\n\tif (!changed) return message;\n\tconst next = { ...message, content };\n\tcollapsedDegenerateMessages.add(next);\n\treturn next;\n}\n\n/** True when this message is (or was collapsed from) a generation loop. */\nexport function isCollapsedDegenerateAssistantMessage(message: AssistantMessage): boolean {\n\treturn collapsedDegenerateMessages.has(message);\n}\n\nexport function assistantMessageText(message: AssistantMessage): string {\n\treturn message.content\n\t\t.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(\"\\n\");\n}\n"]}
@@ -37,16 +37,14 @@ export interface ToolFailureDirectiveDetails {
37
37
  }
38
38
  export type ToolFailureResultDetails = ToolFailureMemoryDetails | ToolFailureDirectiveDetails;
39
39
  export type ToolFailureMemoryTracker = Map<string, ToolFailureMemoryRecord>;
40
- /**
41
- * Fingerprint a tool operation without materializing or retaining its serialized payload.
42
- * Volatile identifiers normalize before hashing; short numbers and ordinary paths remain significant.
43
- */
44
40
  export declare function normalizeToolSignature(pairs: Array<[string, unknown]>): string;
45
41
  export declare function getToolExecutionKey(tool: string, args: unknown): string;
46
42
  export declare function getToolFailureRecordExecutionKey(record: ToolFailureMemoryRecord): string | undefined;
47
43
  export declare function getUnresolvedToolFailure(tracker: ToolFailureMemoryTracker, tool: string, args: unknown): ToolFailureMemoryRecord | undefined;
48
44
  export declare function readVisibleToolFailureCode(result: ToolResultMessage): string | undefined;
49
45
  export declare function isClosedOperationFailureCode(code: string | undefined): boolean;
46
+ /** Failures that only a new owner prompt can clear. Do not restore their circuit across user turns. */
47
+ export declare function isPromptScopedFailureCode(code: string | undefined): boolean;
50
48
  export declare function restoreToolFailureRecord(result: ToolResultMessage, tool: string, args: unknown): ToolFailureMemoryRecord;
51
49
  export interface PairedToolResult {
52
50
  tool: string;
@@ -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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"}
@@ -243,10 +243,49 @@ function boundedJsonPreview(value, maxChars) {
243
243
  * Fingerprint a tool operation without materializing or retaining its serialized payload.
244
244
  * Volatile identifiers normalize before hashing; short numbers and ordinary paths remain significant.
245
245
  */
246
+ /**
247
+ * Resource-envelope fields are not the operation. Changing `timeout` (or a sibling wait bound)
248
+ * must not mint a new execution identity — that is how a failed command is replayed forever.
249
+ */
250
+ const OPERATION_ENVELOPE_KEYS = new Set([
251
+ "timeout",
252
+ "timeoutms",
253
+ "timeout_ms",
254
+ "timeoutsec",
255
+ "timeout_sec",
256
+ "timeoutseconds",
257
+ "timeout_seconds",
258
+ "maxwait",
259
+ "max_wait",
260
+ "maxwaitms",
261
+ "max_wait_ms",
262
+ "waitms",
263
+ "wait_ms",
264
+ "waitsec",
265
+ "wait_sec",
266
+ "waitseconds",
267
+ "wait_seconds",
268
+ ]);
269
+ function omitOperationEnvelopeFields(value) {
270
+ if (!value || typeof value !== "object" || Array.isArray(value))
271
+ return value;
272
+ const record = value;
273
+ let changed = false;
274
+ const next = {};
275
+ for (const [key, entry] of Object.entries(record)) {
276
+ if (OPERATION_ENVELOPE_KEYS.has(key.toLowerCase())) {
277
+ changed = true;
278
+ continue;
279
+ }
280
+ next[key] = entry;
281
+ }
282
+ return changed ? next : value;
283
+ }
246
284
  export function normalizeToolSignature(pairs) {
247
- return structuredHash(pairs, true);
285
+ return structuredHash(pairs.map(([name, args]) => [name, omitOperationEnvelopeFields(args)]), true);
248
286
  }
249
287
  function toolOperationKey(tool, args, normalizeVolatile) {
288
+ const identityArgs = omitOperationEnvelopeFields(args);
250
289
  const boundedTool = truncate(tool, MAX_TOOL_NAME_CHARS);
251
290
  const hash = createSignatureHash();
252
291
  const updateHashString = normalizeVolatile ? updateNormalizedHashString : updateExactHashString;
@@ -254,7 +293,7 @@ function toolOperationKey(tool, args, normalizeVolatile) {
254
293
  // Preserve the stable structured-hash wire identity without allocating the two synthetic arrays.
255
294
  updateHashRange(hash, "array:1[array:2[");
256
295
  updateStructuredHash(hash, tool, active, 2, updateHashString);
257
- updateStructuredHash(hash, args, active, 2, updateHashString);
296
+ updateStructuredHash(hash, identityArgs, active, 2, updateHashString);
258
297
  updateHashRange(hash, "];];");
259
298
  const signature = renderSignatureHash(hash);
260
299
  return `${boundedTool}:${signature}`;
@@ -292,6 +331,10 @@ export function readVisibleToolFailureCode(result) {
292
331
  export function isClosedOperationFailureCode(code) {
293
332
  return code === "operation_recovery_exhausted" || code === "recovery_exhausted";
294
333
  }
334
+ /** Failures that only a new owner prompt can clear. Do not restore their circuit across user turns. */
335
+ export function isPromptScopedFailureCode(code) {
336
+ return code === "owner_authorization_required";
337
+ }
295
338
  export function restoreToolFailureRecord(result, tool, args) {
296
339
  const executionKey = getToolExecutionKey(tool, args);
297
340
  const persisted = readFailureRecord(result.details);
@@ -404,8 +447,11 @@ function inferToolFailurePhase(state, failureCode) {
404
447
  if (failureCode === "malformed_call" || failureCode === "unknown_tool" || failureCode === "invalid_arguments") {
405
448
  return "validation";
406
449
  }
407
- if (failureCode === "blocked" || failureCode === "permission_denied")
450
+ if (failureCode === "blocked" ||
451
+ failureCode === "permission_denied" ||
452
+ failureCode === "owner_authorization_required") {
408
453
  return "policy";
454
+ }
409
455
  if (failureCode === "preflight_error")
410
456
  return "preflight";
411
457
  if (failureCode === "aborted" || failureCode === "cancelled")