agentfootprint 2.13.0 → 2.14.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.
Files changed (117) hide show
  1. package/dist/adapters/llm/AnthropicProvider.js +69 -2
  2. package/dist/adapters/llm/AnthropicProvider.js.map +1 -1
  3. package/dist/adapters/llm/BrowserAnthropicProvider.js +110 -2
  4. package/dist/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
  5. package/dist/core/Agent.js +47 -1
  6. package/dist/core/Agent.js.map +1 -1
  7. package/dist/core/agent/AgentBuilder.js +112 -1
  8. package/dist/core/agent/AgentBuilder.js.map +1 -1
  9. package/dist/core/agent/buildAgentChart.js +20 -1
  10. package/dist/core/agent/buildAgentChart.js.map +1 -1
  11. package/dist/core/agent/stages/callLLM.js +11 -0
  12. package/dist/core/agent/stages/callLLM.js.map +1 -1
  13. package/dist/core/agent/stages/prepareFinal.js +12 -1
  14. package/dist/core/agent/stages/prepareFinal.js.map +1 -1
  15. package/dist/core/agent/stages/seed.js +4 -0
  16. package/dist/core/agent/stages/seed.js.map +1 -1
  17. package/dist/core/agent/stages/toolCalls.js +7 -0
  18. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  19. package/dist/core/slots/buildThinkingSubflow.js +112 -0
  20. package/dist/core/slots/buildThinkingSubflow.js.map +1 -0
  21. package/dist/esm/adapters/llm/AnthropicProvider.js +69 -2
  22. package/dist/esm/adapters/llm/AnthropicProvider.js.map +1 -1
  23. package/dist/esm/adapters/llm/BrowserAnthropicProvider.js +110 -2
  24. package/dist/esm/adapters/llm/BrowserAnthropicProvider.js.map +1 -1
  25. package/dist/esm/core/Agent.js +47 -1
  26. package/dist/esm/core/Agent.js.map +1 -1
  27. package/dist/esm/core/agent/AgentBuilder.js +112 -1
  28. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  29. package/dist/esm/core/agent/buildAgentChart.js +20 -1
  30. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  31. package/dist/esm/core/agent/stages/callLLM.js +11 -0
  32. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  33. package/dist/esm/core/agent/stages/prepareFinal.js +12 -1
  34. package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
  35. package/dist/esm/core/agent/stages/seed.js +4 -0
  36. package/dist/esm/core/agent/stages/seed.js.map +1 -1
  37. package/dist/esm/core/agent/stages/toolCalls.js +7 -0
  38. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  39. package/dist/esm/core/slots/buildThinkingSubflow.js +108 -0
  40. package/dist/esm/core/slots/buildThinkingSubflow.js.map +1 -0
  41. package/dist/esm/events/registry.js +6 -0
  42. package/dist/esm/events/registry.js.map +1 -1
  43. package/dist/esm/security/index.js +1 -0
  44. package/dist/esm/security/index.js.map +1 -1
  45. package/dist/esm/security/thinkingRedaction.js +66 -0
  46. package/dist/esm/security/thinkingRedaction.js.map +1 -0
  47. package/dist/esm/thinking/AnthropicThinkingHandler.js +111 -0
  48. package/dist/esm/thinking/AnthropicThinkingHandler.js.map +1 -0
  49. package/dist/esm/thinking/MockThinkingHandler.js +94 -0
  50. package/dist/esm/thinking/MockThinkingHandler.js.map +1 -0
  51. package/dist/esm/thinking/OpenAIThinkingHandler.js +72 -0
  52. package/dist/esm/thinking/OpenAIThinkingHandler.js.map +1 -0
  53. package/dist/esm/thinking/index.js +51 -0
  54. package/dist/esm/thinking/index.js.map +1 -0
  55. package/dist/esm/thinking/registry.js +46 -0
  56. package/dist/esm/thinking/registry.js.map +1 -0
  57. package/dist/esm/thinking/types.js +30 -0
  58. package/dist/esm/thinking/types.js.map +1 -0
  59. package/dist/events/registry.js +6 -0
  60. package/dist/events/registry.js.map +1 -1
  61. package/dist/security/index.js +4 -1
  62. package/dist/security/index.js.map +1 -1
  63. package/dist/security/thinkingRedaction.js +70 -0
  64. package/dist/security/thinkingRedaction.js.map +1 -0
  65. package/dist/thinking/AnthropicThinkingHandler.js +114 -0
  66. package/dist/thinking/AnthropicThinkingHandler.js.map +1 -0
  67. package/dist/thinking/MockThinkingHandler.js +99 -0
  68. package/dist/thinking/MockThinkingHandler.js.map +1 -0
  69. package/dist/thinking/OpenAIThinkingHandler.js +75 -0
  70. package/dist/thinking/OpenAIThinkingHandler.js.map +1 -0
  71. package/dist/thinking/index.js +61 -0
  72. package/dist/thinking/index.js.map +1 -0
  73. package/dist/thinking/registry.js +50 -0
  74. package/dist/thinking/registry.js.map +1 -0
  75. package/dist/thinking/types.js +31 -0
  76. package/dist/thinking/types.js.map +1 -0
  77. package/dist/types/adapters/llm/AnthropicProvider.d.ts +11 -0
  78. package/dist/types/adapters/llm/AnthropicProvider.d.ts.map +1 -1
  79. package/dist/types/adapters/llm/BrowserAnthropicProvider.d.ts.map +1 -1
  80. package/dist/types/adapters/types.d.ts +97 -0
  81. package/dist/types/adapters/types.d.ts.map +1 -1
  82. package/dist/types/core/Agent.d.ts +16 -1
  83. package/dist/types/core/Agent.d.ts.map +1 -1
  84. package/dist/types/core/agent/AgentBuilder.d.ts +99 -0
  85. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  86. package/dist/types/core/agent/buildAgentChart.d.ts +8 -0
  87. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  88. package/dist/types/core/agent/stages/callLLM.d.ts +4 -0
  89. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  90. package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
  91. package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
  92. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  93. package/dist/types/core/agent/types.d.ts +12 -0
  94. package/dist/types/core/agent/types.d.ts.map +1 -1
  95. package/dist/types/core/slots/buildThinkingSubflow.d.ts +41 -0
  96. package/dist/types/core/slots/buildThinkingSubflow.d.ts.map +1 -0
  97. package/dist/types/events/payloads.d.ts +100 -0
  98. package/dist/types/events/payloads.d.ts.map +1 -1
  99. package/dist/types/events/registry.d.ts +7 -1
  100. package/dist/types/events/registry.d.ts.map +1 -1
  101. package/dist/types/security/index.d.ts +1 -0
  102. package/dist/types/security/index.d.ts.map +1 -1
  103. package/dist/types/security/thinkingRedaction.d.ts +51 -0
  104. package/dist/types/security/thinkingRedaction.d.ts.map +1 -0
  105. package/dist/types/thinking/AnthropicThinkingHandler.d.ts +43 -0
  106. package/dist/types/thinking/AnthropicThinkingHandler.d.ts.map +1 -0
  107. package/dist/types/thinking/MockThinkingHandler.d.ts +51 -0
  108. package/dist/types/thinking/MockThinkingHandler.d.ts.map +1 -0
  109. package/dist/types/thinking/OpenAIThinkingHandler.d.ts +38 -0
  110. package/dist/types/thinking/OpenAIThinkingHandler.d.ts.map +1 -0
  111. package/dist/types/thinking/index.d.ts +52 -0
  112. package/dist/types/thinking/index.d.ts.map +1 -0
  113. package/dist/types/thinking/registry.d.ts +34 -0
  114. package/dist/types/thinking/registry.d.ts.map +1 -0
  115. package/dist/types/thinking/types.d.ts +163 -0
  116. package/dist/types/thinking/types.d.ts.map +1 -0
  117. package/package.json +6 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * thinkingRedaction — content scrubbing for ThinkingBlock[] before
3
+ * persistence + audit-log adapters fire.
4
+ *
5
+ * Pattern: Pure function. Same shape as the v2.4 RedactionPolicy.scope-
6
+ * patterns / emit-patterns helpers — regex match + replace.
7
+ *
8
+ * Mental model — TWO-LAYER persistence:
9
+ * - LLMMessage.thinkingBlocks IS persisted to scope.history (required
10
+ * for Anthropic signature round-trip).
11
+ * - Audit-log adapters (CloudWatch, Datadog OTel, etc.) read from
12
+ * scope.history. Sensitive reasoning (PII in chain-of-thought,
13
+ * internal IDs the model worked through) lands there too.
14
+ * - This helper scrubs content patterns BEFORE the assistant message
15
+ * pushes to scope.history, so the audit-log surface only sees
16
+ * redacted content while the LLM still sees the unredacted reasoning
17
+ * for round-trip integrity.
18
+ *
19
+ * The signature field is NEVER touched by redaction — Anthropic's
20
+ * server-side signature is bound to the original content; modifying
21
+ * content here would invalidate the signature. Resolution: signature
22
+ * survives byte-exact, content gets scrubbed. This means the Anthropic
23
+ * API will reject the next turn IF the consumer wired thinkingPatterns
24
+ * AND uses Anthropic with extended-thinking-plus-tools. Document.
25
+ *
26
+ * Recommended use:
27
+ * - DON'T wire thinkingPatterns when using Anthropic extended thinking
28
+ * + tool calls (signature breaks).
29
+ * - DO wire thinkingPatterns when using OpenAI o1/o3 (no signature,
30
+ * no round-trip requirement) or for offline log scrubbing.
31
+ * - For Anthropic + sensitive reasoning, prefer audit-log-side
32
+ * redaction (filter in your CloudWatch / Datadog adapter rather
33
+ * than the framework's persistence point).
34
+ */
35
+ /** Sentinel string used in place of redacted content. */
36
+ export const REDACTED_PLACEHOLDER = '[REDACTED]';
37
+ /**
38
+ * Return a copy of `blocks` with each block's `content` field scrubbed
39
+ * by every pattern in `patterns`. Returns the input array unchanged
40
+ * when `patterns` is undefined, empty, or no block content matches.
41
+ *
42
+ * Signature + summary + providerMeta fields are preserved BYTE-EXACT
43
+ * — only `content` is touched.
44
+ *
45
+ * Anthropic signature warning: scrubbing content invalidates the
46
+ * Anthropic server-side signature. Round-trip will fail with HTTP 400
47
+ * on the next turn. Document this in the consumer recipe.
48
+ */
49
+ export function redactThinkingBlocks(blocks, patterns) {
50
+ if (!patterns || patterns.length === 0)
51
+ return blocks;
52
+ if (blocks.length === 0)
53
+ return blocks;
54
+ let anyChanged = false;
55
+ const out = blocks.map((b) => {
56
+ const scrubbed = patterns.reduce((c, re) => c.replace(re, REDACTED_PLACEHOLDER), b.content);
57
+ if (scrubbed === b.content)
58
+ return b;
59
+ anyChanged = true;
60
+ return { ...b, content: scrubbed };
61
+ });
62
+ // Return the original array reference when nothing changed —
63
+ // downstream reference-equality checks (cache markers) stay stable.
64
+ return anyChanged ? out : blocks;
65
+ }
66
+ //# sourceMappingURL=thinkingRedaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinkingRedaction.js","sourceRoot":"","sources":["../../../src/security/thinkingRedaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAgC,EAChC,QAAuC;IAEvC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAEvC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3B,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,oBAAoB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5F,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC;QACrC,UAAU,GAAG,IAAI,CAAC;QAClB,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,6DAA6D;IAC7D,oEAAoE;IACpE,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AACnC,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * AnthropicThinkingHandler — normalizes Anthropic's extended-thinking
3
+ * response shape into the framework's `ThinkingBlock[]` contract.
4
+ *
5
+ * Anthropic emits thinking via blocks in `response.content`:
6
+ *
7
+ * ```ts
8
+ * { type: 'thinking', thinking: 'reasoning text', signature: 'opaque-base64' }
9
+ * { type: 'redacted_thinking', signature: 'opaque-base64' }
10
+ * { type: 'text', text: 'visible content' }
11
+ * { type: 'tool_use', id, name, input }
12
+ * ```
13
+ *
14
+ * The handler filters for `'thinking'` + `'redacted_thinking'` blocks,
15
+ * preserves the `signature` field BYTE-EXACT (Anthropic validates
16
+ * signatures server-side on the next turn — any modification = HTTP 400),
17
+ * and ignores other block types (visible text + tool calls flow through
18
+ * the existing `LLMResponse.content` / `LLMResponse.toolCalls` paths).
19
+ *
20
+ * **Critical invariant:** signature pass-through is byte-exact. The
21
+ * handler MUST NOT trim, normalize encoding, JSON-roundtrip, or
22
+ * otherwise touch the signature string. Tests verify this explicitly.
23
+ *
24
+ * **Three input shapes** Anthropic produces (per Phase 4a panel review):
25
+ * 1. Non-streaming response: full `response.content` array
26
+ * 2. Streaming aggregated: AnthropicProvider accumulates chunks +
27
+ * calls handler with the same array shape
28
+ * 3. Bedrock-via-Anthropic: deferred to Phase 5+ (separate handler
29
+ * or extension of this one)
30
+ *
31
+ * Streaming + non-streaming converge on shape #1 because the provider
32
+ * handles the distinction — handler only sees the assembled content
33
+ * array.
34
+ *
35
+ * **`parseChunk` is OPTIONAL** — Phase 3's framework path populates
36
+ * `LLMChunk.thinkingDelta` from inside AnthropicProvider's `stream()`
37
+ * directly, bypassing handler.parseChunk. We still implement it for
38
+ * consumer integrations that want to use the handler on raw Anthropic
39
+ * chunks directly (e.g., custom transports).
40
+ */
41
+ function isAnthropicContentArray(raw) {
42
+ return Array.isArray(raw);
43
+ }
44
+ function isThinkingBlock(b) {
45
+ return b.type === 'thinking';
46
+ }
47
+ function isRedactedThinkingBlock(b) {
48
+ return b.type === 'redacted_thinking';
49
+ }
50
+ function isAnthropicChunk(chunk) {
51
+ return typeof chunk === 'object' && chunk !== null;
52
+ }
53
+ export const anthropicThinkingHandler = {
54
+ id: 'anthropic',
55
+ // 'browser-anthropic' shares the same response shape (raw Anthropic
56
+ // wire format) — both providers route through fromAnthropicResponse
57
+ // which sets `rawThinking` to `message.content`. Bedrock Claude
58
+ // would also fit here but ships as a separate handler if/when its
59
+ // shape diverges.
60
+ providerNames: ['anthropic', 'browser-anthropic'],
61
+ normalize(raw) {
62
+ if (!isAnthropicContentArray(raw))
63
+ return [];
64
+ const out = [];
65
+ for (const block of raw) {
66
+ if (isThinkingBlock(block)) {
67
+ // Byte-exact signature preservation: pass through as-is.
68
+ // No String() coercion that could normalize encoding; if
69
+ // Anthropic ever emits a non-string signature it would be a
70
+ // wire-protocol violation we want to surface, not silently
71
+ // coerce.
72
+ out.push({
73
+ type: 'thinking',
74
+ // Don't touch content — pass through. Anthropic guarantees
75
+ // it's a string when the field is present.
76
+ content: block.thinking,
77
+ ...(block.signature !== undefined && { signature: block.signature }),
78
+ });
79
+ }
80
+ else if (isRedactedThinkingBlock(block)) {
81
+ // Redacted blocks have no readable content but the signature
82
+ // is still REQUIRED for round-trip. Empty content is the
83
+ // contract (per Phase 1 ThinkingBlock JSDoc).
84
+ out.push({
85
+ type: 'redacted_thinking',
86
+ content: '',
87
+ ...(block.signature !== undefined && { signature: block.signature }),
88
+ });
89
+ }
90
+ // Other block types (text, tool_use, etc.) flow through the
91
+ // existing LLMResponse paths — ignore here.
92
+ }
93
+ return out;
94
+ },
95
+ parseChunk(chunk) {
96
+ // Optional escape hatch — framework path doesn't call this
97
+ // (AnthropicProvider populates LLMChunk.thinkingDelta directly).
98
+ // Provided for consumer integrations using the handler on raw
99
+ // Anthropic chunks directly.
100
+ if (!isAnthropicChunk(chunk))
101
+ return {};
102
+ const delta = chunk.delta;
103
+ if (!delta)
104
+ return {};
105
+ if (delta.type === 'thinking_delta' && typeof delta.thinking === 'string') {
106
+ return { thinkingDelta: delta.thinking };
107
+ }
108
+ return {};
109
+ },
110
+ };
111
+ //# sourceMappingURL=AnthropicThinkingHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnthropicThinkingHandler.js","sourceRoot":"","sources":["../../../src/thinking/AnthropicThinkingHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAuCH,SAAS,uBAAuB,CAAC,GAAY;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,eAAe,CAAC,CAAwB;IAC/C,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC;AAC/B,CAAC;AAED,SAAS,uBAAuB,CAAC,CAAwB;IACvD,OAAO,CAAC,CAAC,IAAI,KAAK,mBAAmB,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAoB;IACvD,EAAE,EAAE,WAAW;IACf,oEAAoE;IACpE,oEAAoE;IACpE,gEAAgE;IAChE,kEAAkE;IAClE,kBAAkB;IAClB,aAAa,EAAE,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAEjD,SAAS,CAAC,GAAY;QACpB,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAE7C,MAAM,GAAG,GAAoB,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;YACxB,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,yDAAyD;gBACzD,yDAAyD;gBACzD,4DAA4D;gBAC5D,2DAA2D;gBAC3D,UAAU;gBACV,GAAG,CAAC,IAAI,CAAC;oBACP,IAAI,EAAE,UAAU;oBAChB,2DAA2D;oBAC3D,2CAA2C;oBAC3C,OAAO,EAAE,KAAK,CAAC,QAAQ;oBACvB,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;iBACrE,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1C,6DAA6D;gBAC7D,yDAAyD;gBACzD,8CAA8C;gBAC9C,GAAG,CAAC,IAAI,CAAC;oBACP,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,EAAE;oBACX,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC;iBACrE,CAAC,CAAC;YACL,CAAC;YACD,4DAA4D;YAC5D,4CAA4C;QAC9C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,UAAU,CAAC,KAAc;QACvB,2DAA2D;QAC3D,iEAAiE;QACjE,8DAA8D;QAC9D,6BAA6B;QAC7B,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAC;QACtB,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1E,OAAO,EAAE,aAAa,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;CACF,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * MockThinkingHandler — canonical example for the v2.14 ThinkingHandler
3
+ * contract. Used by:
4
+ *
5
+ * 1. Tests — drives the shared contract test (every shipped handler
6
+ * MUST satisfy the same invariants this mock demonstrates).
7
+ * 2. Future provider authors — reference implementation showing how
8
+ * to handle BOTH Anthropic-shape inputs (signed blocks, possibly
9
+ * redacted) and OpenAI-shape inputs (multi-block summary). The
10
+ * pattern of "discriminate by shape, normalize each branch" is
11
+ * reusable across providers.
12
+ * 3. The MockProvider for end-to-end tests of the framework wiring
13
+ * without depending on a real LLM SDK.
14
+ *
15
+ * Defaults are deliberately sensitive-data-free — no fake PII, no
16
+ * fake-signature material that could be confused for real cryptography,
17
+ * no internal-looking IDs. Sets the example for consumer-authored
18
+ * handlers.
19
+ */
20
+ function isMockRaw(raw) {
21
+ if (typeof raw !== 'object' || raw === null)
22
+ return false;
23
+ const r = raw;
24
+ // Accept only well-formed shapes — protects against {kind: 'anthropic'}
25
+ // missing blocks (would crash .map). The framework's failure-isolation
26
+ // would catch the throw, but defending here keeps the contract
27
+ // "normalize never throws on garbage" tighter.
28
+ if (r.kind === 'anthropic')
29
+ return Array.isArray(r.blocks);
30
+ if (r.kind === 'openai')
31
+ return Array.isArray(r.summarySteps);
32
+ return false;
33
+ }
34
+ /**
35
+ * Build an Anthropic-style raw input for tests. Signature is a marker
36
+ * string — real Anthropic signatures are opaque base64.
37
+ */
38
+ export function mockAnthropicRaw(blocks) {
39
+ return {
40
+ kind: 'anthropic',
41
+ blocks: blocks.map((b) => ({
42
+ type: b.redacted ? 'redacted_thinking' : 'thinking',
43
+ ...(b.redacted ? {} : { thinking: b.content }),
44
+ ...(b.signature !== undefined && { signature: b.signature }),
45
+ })),
46
+ };
47
+ }
48
+ /**
49
+ * Build an OpenAI-style raw input for tests — one summary step per
50
+ * string. Each step becomes a separate ThinkingBlock with `summary: true`.
51
+ */
52
+ export function mockOpenAIRaw(summarySteps) {
53
+ return { kind: 'openai', summarySteps };
54
+ }
55
+ export const mockThinkingHandler = {
56
+ id: 'mock',
57
+ // Matches the MockProvider's name; framework auto-wires when
58
+ // Agent uses MockProvider in tests.
59
+ providerNames: ['mock'],
60
+ normalize(raw) {
61
+ if (!isMockRaw(raw))
62
+ return [];
63
+ if (raw.kind === 'anthropic') {
64
+ return raw.blocks.map((b) => {
65
+ if (b.type === 'redacted_thinking') {
66
+ return {
67
+ type: 'redacted_thinking',
68
+ content: '',
69
+ ...(b.signature !== undefined && { signature: b.signature }),
70
+ };
71
+ }
72
+ return {
73
+ type: 'thinking',
74
+ content: b.thinking ?? '',
75
+ ...(b.signature !== undefined && { signature: b.signature }),
76
+ };
77
+ });
78
+ }
79
+ // OpenAI-style: one block per summary step, all marked summary: true.
80
+ return raw.summarySteps.map((content) => ({
81
+ type: 'thinking',
82
+ content,
83
+ summary: true,
84
+ }));
85
+ },
86
+ parseChunk(chunk) {
87
+ // Mock streams thinking via { thinkingDelta: '...' } shape.
88
+ if (typeof chunk !== 'object' || chunk === null)
89
+ return {};
90
+ const c = chunk;
91
+ return typeof c.thinkingDelta === 'string' ? { thinkingDelta: c.thinkingDelta } : {};
92
+ },
93
+ };
94
+ //# sourceMappingURL=MockThinkingHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockThinkingHandler.js","sourceRoot":"","sources":["../../../src/thinking/MockThinkingHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * OpenAIThinkingHandler — normalizes OpenAI's o1/o3 reasoning_summary
3
+ * structured output into the framework's `ThinkingBlock[]` contract.
4
+ *
5
+ * OpenAI's reasoning_summary shape varies by model + API version:
6
+ *
7
+ * 1. Older o1 format — simple string:
8
+ * "I worked through the problem by first..."
9
+ *
10
+ * 2. Newer o3+ structured — array of summary items:
11
+ * [
12
+ * { type: 'summary_text', text: 'Identify the user request' },
13
+ * { type: 'summary_text', text: 'Choose appropriate tool' },
14
+ * ]
15
+ *
16
+ * 3. Missing entirely — most calls (gpt-4o, or o1/o3 without
17
+ * reasoning_summary param requested) → undefined raw input
18
+ *
19
+ * Handler dispatches on shape; output is `ThinkingBlock[]` with
20
+ * `summary: true` per Phase 1 contract — distinguishes structured-
21
+ * summary blocks from raw thinking content (Anthropic's shape).
22
+ *
23
+ * **No signature** — OpenAI doesn't sign reasoning. The output's
24
+ * `signature` field stays undefined. No round-trip integrity invariant
25
+ * (unlike Anthropic).
26
+ *
27
+ * **No `parseChunk`** — OpenAI doesn't stream reasoning content as of
28
+ * early 2026. Reasoning arrives only on the terminal response. Per
29
+ * Phase 1 design, `parseChunk` is optional; we omit entirely.
30
+ *
31
+ * **No `usage.thinking` computation** — reasoning_tokens lives on
32
+ * `response.usage.completion_tokens_details.reasoning_tokens` and is
33
+ * the OpenAIProvider's job to surface (deferred). Handler doesn't
34
+ * compute token counts.
35
+ */
36
+ function isOpenAIStructuredArray(raw) {
37
+ return Array.isArray(raw);
38
+ }
39
+ export const openAIThinkingHandler = {
40
+ id: 'openai',
41
+ providerNames: ['openai'],
42
+ normalize(raw) {
43
+ if (raw === undefined || raw === null)
44
+ return [];
45
+ // Shape 1: simple string (older o1 format).
46
+ if (typeof raw === 'string') {
47
+ return raw.length > 0 ? [{ type: 'thinking', content: raw, summary: true }] : [];
48
+ }
49
+ // Shape 2: structured array of summary items (newer o3+ format).
50
+ if (isOpenAIStructuredArray(raw)) {
51
+ const out = [];
52
+ for (const item of raw) {
53
+ // Tolerate items missing `text` (defensive — wire format may
54
+ // evolve). Skip entries without usable content.
55
+ if (typeof item.text === 'string' && item.text.length > 0) {
56
+ out.push({
57
+ type: 'thinking',
58
+ content: item.text,
59
+ summary: true,
60
+ });
61
+ }
62
+ }
63
+ return out;
64
+ }
65
+ // Unknown shape — return empty rather than throw. The framework
66
+ // catches throws and emits parse_failed; here we choose graceful
67
+ // empty for unknown OpenAI evolutions (forward-compat).
68
+ return [];
69
+ },
70
+ // No parseChunk — OpenAI doesn't stream reasoning content.
71
+ };
72
+ //# sourceMappingURL=OpenAIThinkingHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenAIThinkingHandler.js","sourceRoot":"","sources":["../../../src/thinking/OpenAIThinkingHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAYH,SAAS,uBAAuB,CAAC,GAAY;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAoB;IACpD,EAAE,EAAE,QAAQ;IACZ,aAAa,EAAE,CAAC,QAAQ,CAAC;IAEzB,SAAS,CAAC,GAAY;QACpB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QAEjD,4CAA4C;QAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,CAAC;QAED,iEAAiE;QACjE,IAAI,uBAAuB,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,GAAG,GAAoB,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;gBACvB,6DAA6D;gBAC7D,gDAAgD;gBAChD,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1D,GAAG,CAAC,IAAI,CAAC;wBACP,IAAI,EAAE,UAAU;wBAChB,OAAO,EAAE,IAAI,CAAC,IAAI;wBAClB,OAAO,EAAE,IAAI;qBACd,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QAED,gEAAgE;QAChE,iEAAiE;QACjE,wDAAwD;QACxD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,2DAA2D;CAC5D,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * agentfootprint/thinking — extended-thinking subsystem (v2.14+).
3
+ *
4
+ * **Two-layer architecture:**
5
+ *
6
+ * • CONSUMER-FACING: `ThinkingHandler` — simple function-pair
7
+ * implemented by provider authors.
8
+ * • FRAMEWORK-INTERNAL: each handler is auto-wrapped in a real
9
+ * footprintjs subflow at chart build time;
10
+ * shows in trace as own runtimeStageId.
11
+ *
12
+ * **Auto-wire by provider name:**
13
+ *
14
+ * ```ts
15
+ * import { Agent } from 'agentfootprint';
16
+ *
17
+ * // Library scans SHIPPED_THINKING_HANDLERS, finds the handler
18
+ * // whose providerNames includes provider.name. Mounted as a
19
+ * // sub-subflow of sf-call-llm.
20
+ * const agent = Agent.create({ provider: anthropic({...}), model: '...' })
21
+ * .build();
22
+ *
23
+ * // Opt out:
24
+ * // .thinkingHandler(undefined)
25
+ * // Override with a custom handler:
26
+ * // .thinkingHandler(myCustomHandler)
27
+ * ```
28
+ *
29
+ * **Custom handlers:**
30
+ *
31
+ * ```ts
32
+ * import { type ThinkingHandler } from 'agentfootprint/thinking';
33
+ *
34
+ * export const geminiThinkingHandler: ThinkingHandler = {
35
+ * id: 'gemini',
36
+ * providerNames: ['gemini'],
37
+ * normalize(raw) { ... },
38
+ * parseChunk(chunk) { ... }, // optional
39
+ * };
40
+ * ```
41
+ *
42
+ * Failure isolation: handler `normalize()` throws are caught by the
43
+ * framework — emit `agentfootprint.agent.thinking_parse_failed`, drop
44
+ * the blocks, continue. Same graceful pattern as v2.11.6
45
+ * `tools.discovery_failed`.
46
+ */
47
+ export { mockThinkingHandler, mockAnthropicRaw, mockOpenAIRaw } from './MockThinkingHandler.js';
48
+ export { anthropicThinkingHandler } from './AnthropicThinkingHandler.js';
49
+ export { openAIThinkingHandler } from './OpenAIThinkingHandler.js';
50
+ export { SHIPPED_THINKING_HANDLERS, findThinkingHandler } from './registry.js';
51
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/thinking/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAIH,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEhG,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Registry — single source of truth for the framework's auto-wire
3
+ * logic AND the shared contract test.
4
+ *
5
+ * Phase 3 wiring scans this array at chart build time and selects the
6
+ * first handler whose `providerNames` includes the active
7
+ * `provider.name`. Phase 4a adds AnthropicThinkingHandler; Phase 5
8
+ * adds OpenAIThinkingHandler — append-only as new providers ship.
9
+ *
10
+ * Future provider authors:
11
+ * • Implement `ThinkingHandler` for your provider
12
+ * • Append to this array
13
+ * • The shared contract test in `test/thinking/contract.test.ts`
14
+ * verifies your handler honors the framework's invariants
15
+ */
16
+ import { anthropicThinkingHandler } from './AnthropicThinkingHandler.js';
17
+ import { mockThinkingHandler } from './MockThinkingHandler.js';
18
+ import { openAIThinkingHandler } from './OpenAIThinkingHandler.js';
19
+ /**
20
+ * All thinking handlers shipped with the library. Append in alphabetical
21
+ * order (by `id`) so diffs stay readable as new handlers land.
22
+ */
23
+ export const SHIPPED_THINKING_HANDLERS = [
24
+ anthropicThinkingHandler,
25
+ mockThinkingHandler,
26
+ openAIThinkingHandler,
27
+ ];
28
+ /**
29
+ * Look up a handler by `provider.name`. Returns the first match in
30
+ * `SHIPPED_THINKING_HANDLERS`. Returns `undefined` when no handler
31
+ * matches — framework treats this as "no thinking support for this
32
+ * provider", which is the correct default for providers that don't
33
+ * emit thinking content (gpt-3.5, mistral, etc.).
34
+ *
35
+ * Used by:
36
+ * • Phase 3 framework auto-wire (chart build time)
37
+ * • Tests verifying registry lookup
38
+ */
39
+ export function findThinkingHandler(providerName) {
40
+ for (const handler of SHIPPED_THINKING_HANDLERS) {
41
+ if (handler.providerNames.includes(providerName))
42
+ return handler;
43
+ }
44
+ return undefined;
45
+ }
46
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/thinking/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGnE;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAA+B;IACnE,wBAAwB;IACxB,mBAAmB;IACnB,qBAAqB;CACtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,KAAK,MAAM,OAAO,IAAI,yBAAyB,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,OAAO,CAAC;IACnE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Thinking — public types for the v2.14 extended-thinking subsystem.
3
+ *
4
+ * Mental model — TWO-LAYER architecture:
5
+ *
6
+ * • CONSUMER-FACING: `ThinkingHandler` — a simple function-pair
7
+ * (id, providerNames, normalize, parseChunk?).
8
+ * Provider authors and custom-LLM consumers
9
+ * implement THIS shape.
10
+ *
11
+ * • FRAMEWORK-INTERNAL: each `ThinkingHandler` is auto-wrapped in a
12
+ * real footprintjs subflow at chart build time.
13
+ * The subflow gets its own `runtimeStageId`,
14
+ * narrative entry, and InOutRecorder boundary
15
+ * — full trace observability for free without
16
+ * the consumer writing flowchart code.
17
+ *
18
+ * Same pattern as how consumers write a `Tool` and the framework wraps
19
+ * dispatch in a tool-call subflow, or how consumers write a
20
+ * `ToolProvider` and the framework wraps `list()` in the Tools slot
21
+ * subflow.
22
+ *
23
+ * @see SHIPPED_THINKING_HANDLERS for the registry the framework uses
24
+ * to auto-wire by `provider.name` (Phase 3 wiring).
25
+ * @see MockThinkingHandler for the canonical example demonstrating
26
+ * both Anthropic-shape (signed blocks) and OpenAI-shape (multi-
27
+ * block summary) inputs.
28
+ */
29
+ export {};
30
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/thinking/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG"}
@@ -38,6 +38,7 @@ exports.EVENT_NAMES = {
38
38
  routeDecided: 'agentfootprint.agent.route_decided',
39
39
  handoff: 'agentfootprint.agent.handoff',
40
40
  outputSchemaValidationFailed: 'agentfootprint.agent.output_schema_validation_failed',
41
+ thinkingParseFailed: 'agentfootprint.agent.thinking_parse_failed',
41
42
  },
42
43
  stream: {
43
44
  llmStart: 'agentfootprint.stream.llm_start',
@@ -45,6 +46,8 @@ exports.EVENT_NAMES = {
45
46
  token: 'agentfootprint.stream.token',
46
47
  toolStart: 'agentfootprint.stream.tool_start',
47
48
  toolEnd: 'agentfootprint.stream.tool_end',
49
+ thinkingDelta: 'agentfootprint.stream.thinking_delta',
50
+ thinkingEnd: 'agentfootprint.stream.thinking_end',
48
51
  },
49
52
  context: {
50
53
  injected: 'agentfootprint.context.injected',
@@ -123,11 +126,14 @@ exports.ALL_EVENT_TYPES = [
123
126
  'agentfootprint.agent.route_decided',
124
127
  'agentfootprint.agent.handoff',
125
128
  'agentfootprint.agent.output_schema_validation_failed',
129
+ 'agentfootprint.agent.thinking_parse_failed',
126
130
  'agentfootprint.stream.llm_start',
127
131
  'agentfootprint.stream.llm_end',
128
132
  'agentfootprint.stream.token',
129
133
  'agentfootprint.stream.tool_start',
130
134
  'agentfootprint.stream.tool_end',
135
+ 'agentfootprint.stream.thinking_delta',
136
+ 'agentfootprint.stream.thinking_end',
131
137
  'agentfootprint.context.injected',
132
138
  'agentfootprint.context.evicted',
133
139
  'agentfootprint.context.slot_composed',
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/events/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/events/registry.ts"],"names":[],"mappings":"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"}
@@ -36,7 +36,7 @@
36
36
  * const agent = Agent.create({ provider, model, permissionChecker: policy }).build();
37
37
  */
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.SYNTHETIC_DENY_PREFIX = exports.extractSequence = exports.PolicyHaltError = exports.PermissionPolicy = void 0;
39
+ exports.REDACTED_PLACEHOLDER = exports.redactThinkingBlocks = exports.SYNTHETIC_DENY_PREFIX = exports.extractSequence = exports.PolicyHaltError = exports.PermissionPolicy = void 0;
40
40
  var PermissionPolicy_js_1 = require("./PermissionPolicy.js");
41
41
  Object.defineProperty(exports, "PermissionPolicy", { enumerable: true, get: function () { return PermissionPolicy_js_1.PermissionPolicy; } });
42
42
  var PolicyHaltError_js_1 = require("./PolicyHaltError.js");
@@ -44,4 +44,7 @@ Object.defineProperty(exports, "PolicyHaltError", { enumerable: true, get: funct
44
44
  var extractSequence_js_1 = require("./extractSequence.js");
45
45
  Object.defineProperty(exports, "extractSequence", { enumerable: true, get: function () { return extractSequence_js_1.extractSequence; } });
46
46
  Object.defineProperty(exports, "SYNTHETIC_DENY_PREFIX", { enumerable: true, get: function () { return extractSequence_js_1.SYNTHETIC_DENY_PREFIX; } });
47
+ var thinkingRedaction_js_1 = require("./thinkingRedaction.js");
48
+ Object.defineProperty(exports, "redactThinkingBlocks", { enumerable: true, get: function () { return thinkingRedaction_js_1.redactThinkingBlocks; } });
49
+ Object.defineProperty(exports, "REDACTED_PLACEHOLDER", { enumerable: true, get: function () { return thinkingRedaction_js_1.REDACTED_PLACEHOLDER; } });
47
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;;;AAEH,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AAGzB,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AAGxB,2DAA8E;AAArE,qHAAA,eAAe,OAAA;AAAE,2HAAA,qBAAqB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;;;AAEH,6DAAyD;AAAhD,uHAAA,gBAAgB,OAAA;AAGzB,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AAGxB,2DAA8E;AAArE,qHAAA,eAAe,OAAA;AAAE,2HAAA,qBAAqB,OAAA;AAG/C,+DAAoF;AAA3E,4HAAA,oBAAoB,OAAA;AAAE,4HAAA,oBAAoB,OAAA"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * thinkingRedaction — content scrubbing for ThinkingBlock[] before
4
+ * persistence + audit-log adapters fire.
5
+ *
6
+ * Pattern: Pure function. Same shape as the v2.4 RedactionPolicy.scope-
7
+ * patterns / emit-patterns helpers — regex match + replace.
8
+ *
9
+ * Mental model — TWO-LAYER persistence:
10
+ * - LLMMessage.thinkingBlocks IS persisted to scope.history (required
11
+ * for Anthropic signature round-trip).
12
+ * - Audit-log adapters (CloudWatch, Datadog OTel, etc.) read from
13
+ * scope.history. Sensitive reasoning (PII in chain-of-thought,
14
+ * internal IDs the model worked through) lands there too.
15
+ * - This helper scrubs content patterns BEFORE the assistant message
16
+ * pushes to scope.history, so the audit-log surface only sees
17
+ * redacted content while the LLM still sees the unredacted reasoning
18
+ * for round-trip integrity.
19
+ *
20
+ * The signature field is NEVER touched by redaction — Anthropic's
21
+ * server-side signature is bound to the original content; modifying
22
+ * content here would invalidate the signature. Resolution: signature
23
+ * survives byte-exact, content gets scrubbed. This means the Anthropic
24
+ * API will reject the next turn IF the consumer wired thinkingPatterns
25
+ * AND uses Anthropic with extended-thinking-plus-tools. Document.
26
+ *
27
+ * Recommended use:
28
+ * - DON'T wire thinkingPatterns when using Anthropic extended thinking
29
+ * + tool calls (signature breaks).
30
+ * - DO wire thinkingPatterns when using OpenAI o1/o3 (no signature,
31
+ * no round-trip requirement) or for offline log scrubbing.
32
+ * - For Anthropic + sensitive reasoning, prefer audit-log-side
33
+ * redaction (filter in your CloudWatch / Datadog adapter rather
34
+ * than the framework's persistence point).
35
+ */
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.redactThinkingBlocks = exports.REDACTED_PLACEHOLDER = void 0;
38
+ /** Sentinel string used in place of redacted content. */
39
+ exports.REDACTED_PLACEHOLDER = '[REDACTED]';
40
+ /**
41
+ * Return a copy of `blocks` with each block's `content` field scrubbed
42
+ * by every pattern in `patterns`. Returns the input array unchanged
43
+ * when `patterns` is undefined, empty, or no block content matches.
44
+ *
45
+ * Signature + summary + providerMeta fields are preserved BYTE-EXACT
46
+ * — only `content` is touched.
47
+ *
48
+ * Anthropic signature warning: scrubbing content invalidates the
49
+ * Anthropic server-side signature. Round-trip will fail with HTTP 400
50
+ * on the next turn. Document this in the consumer recipe.
51
+ */
52
+ function redactThinkingBlocks(blocks, patterns) {
53
+ if (!patterns || patterns.length === 0)
54
+ return blocks;
55
+ if (blocks.length === 0)
56
+ return blocks;
57
+ let anyChanged = false;
58
+ const out = blocks.map((b) => {
59
+ const scrubbed = patterns.reduce((c, re) => c.replace(re, exports.REDACTED_PLACEHOLDER), b.content);
60
+ if (scrubbed === b.content)
61
+ return b;
62
+ anyChanged = true;
63
+ return { ...b, content: scrubbed };
64
+ });
65
+ // Return the original array reference when nothing changed —
66
+ // downstream reference-equality checks (cache markers) stay stable.
67
+ return anyChanged ? out : blocks;
68
+ }
69
+ exports.redactThinkingBlocks = redactThinkingBlocks;
70
+ //# sourceMappingURL=thinkingRedaction.js.map