agentfootprint 7.22.1 → 7.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +34 -0
  2. package/ai-instructions/claude-code/SKILL.md +2 -1
  3. package/dist/core/agent/AgentBuilder.js +117 -1
  4. package/dist/core/agent/AgentBuilder.js.map +1 -1
  5. package/dist/core/agent/act.js +143 -0
  6. package/dist/core/agent/act.js.map +1 -0
  7. package/dist/core/agent/middleware/index.js +5 -0
  8. package/dist/core/agent/middleware/index.js.map +1 -1
  9. package/dist/core/agent/middleware/ledger.js +7 -0
  10. package/dist/core/agent/middleware/ledger.js.map +1 -1
  11. package/dist/core/agent/middleware/outcomes.js +9 -2
  12. package/dist/core/agent/middleware/outcomes.js.map +1 -1
  13. package/dist/core/agent/middleware/runChain.js +101 -3
  14. package/dist/core/agent/middleware/runChain.js.map +1 -1
  15. package/dist/core/agent/middleware/types.js +30 -0
  16. package/dist/core/agent/middleware/types.js.map +1 -1
  17. package/dist/core/agent/moments.js +53 -0
  18. package/dist/core/agent/moments.js.map +1 -0
  19. package/dist/core/agent/stages/toolCalls.js +139 -8
  20. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  21. package/dist/core/tools.js.map +1 -1
  22. package/dist/esm/core/agent/AgentBuilder.d.ts +71 -0
  23. package/dist/esm/core/agent/AgentBuilder.js +117 -1
  24. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  25. package/dist/esm/core/agent/act.d.ts +69 -0
  26. package/dist/esm/core/agent/act.js +139 -0
  27. package/dist/esm/core/agent/act.js.map +1 -0
  28. package/dist/esm/core/agent/middleware/index.d.ts +6 -1
  29. package/dist/esm/core/agent/middleware/index.js +5 -0
  30. package/dist/esm/core/agent/middleware/index.js.map +1 -1
  31. package/dist/esm/core/agent/middleware/ledger.d.ts +6 -0
  32. package/dist/esm/core/agent/middleware/ledger.js +7 -0
  33. package/dist/esm/core/agent/middleware/ledger.js.map +1 -1
  34. package/dist/esm/core/agent/middleware/outcomes.d.ts +15 -0
  35. package/dist/esm/core/agent/middleware/outcomes.js +9 -2
  36. package/dist/esm/core/agent/middleware/outcomes.js.map +1 -1
  37. package/dist/esm/core/agent/middleware/runChain.d.ts +49 -0
  38. package/dist/esm/core/agent/middleware/runChain.js +99 -2
  39. package/dist/esm/core/agent/middleware/runChain.js.map +1 -1
  40. package/dist/esm/core/agent/middleware/types.d.ts +144 -10
  41. package/dist/esm/core/agent/middleware/types.js +30 -0
  42. package/dist/esm/core/agent/middleware/types.js.map +1 -1
  43. package/dist/esm/core/agent/moments.d.ts +55 -0
  44. package/dist/esm/core/agent/moments.js +49 -0
  45. package/dist/esm/core/agent/moments.js.map +1 -0
  46. package/dist/esm/core/agent/stages/toolCalls.d.ts +6 -1
  47. package/dist/esm/core/agent/stages/toolCalls.js +140 -9
  48. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  49. package/dist/esm/core/tools.d.ts +18 -0
  50. package/dist/esm/core/tools.js.map +1 -1
  51. package/dist/esm/events/payloads.d.ts +4 -0
  52. package/dist/esm/index.d.ts +3 -1
  53. package/dist/esm/index.js +7 -0
  54. package/dist/esm/index.js.map +1 -1
  55. package/dist/esm/lib/mcp/index.d.ts +1 -1
  56. package/dist/esm/lib/mcp/mcpClient.js +104 -11
  57. package/dist/esm/lib/mcp/mcpClient.js.map +1 -1
  58. package/dist/esm/lib/mcp/mcpServe.js +31 -1
  59. package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
  60. package/dist/esm/lib/mcp/mockMcpClient.js +4 -0
  61. package/dist/esm/lib/mcp/mockMcpClient.js.map +1 -1
  62. package/dist/esm/lib/mcp/types.d.ts +71 -7
  63. package/dist/esm/tool-providers/index.d.ts +1 -1
  64. package/dist/index.js +12 -2
  65. package/dist/index.js.map +1 -1
  66. package/dist/lib/mcp/mcpClient.js +104 -11
  67. package/dist/lib/mcp/mcpClient.js.map +1 -1
  68. package/dist/lib/mcp/mcpServe.js +30 -0
  69. package/dist/lib/mcp/mcpServe.js.map +1 -1
  70. package/dist/lib/mcp/mockMcpClient.js +4 -0
  71. package/dist/lib/mcp/mockMcpClient.js.map +1 -1
  72. package/dist/types/core/agent/AgentBuilder.d.ts +71 -0
  73. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  74. package/dist/types/core/agent/act.d.ts +70 -0
  75. package/dist/types/core/agent/act.d.ts.map +1 -0
  76. package/dist/types/core/agent/middleware/index.d.ts +6 -1
  77. package/dist/types/core/agent/middleware/index.d.ts.map +1 -1
  78. package/dist/types/core/agent/middleware/ledger.d.ts +6 -0
  79. package/dist/types/core/agent/middleware/ledger.d.ts.map +1 -1
  80. package/dist/types/core/agent/middleware/outcomes.d.ts +15 -0
  81. package/dist/types/core/agent/middleware/outcomes.d.ts.map +1 -1
  82. package/dist/types/core/agent/middleware/runChain.d.ts +49 -0
  83. package/dist/types/core/agent/middleware/runChain.d.ts.map +1 -1
  84. package/dist/types/core/agent/middleware/types.d.ts +144 -10
  85. package/dist/types/core/agent/middleware/types.d.ts.map +1 -1
  86. package/dist/types/core/agent/moments.d.ts +56 -0
  87. package/dist/types/core/agent/moments.d.ts.map +1 -0
  88. package/dist/types/core/agent/stages/toolCalls.d.ts +6 -1
  89. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  90. package/dist/types/core/tools.d.ts +18 -0
  91. package/dist/types/core/tools.d.ts.map +1 -1
  92. package/dist/types/events/payloads.d.ts +4 -0
  93. package/dist/types/events/payloads.d.ts.map +1 -1
  94. package/dist/types/index.d.ts +3 -1
  95. package/dist/types/index.d.ts.map +1 -1
  96. package/dist/types/lib/mcp/index.d.ts +1 -1
  97. package/dist/types/lib/mcp/index.d.ts.map +1 -1
  98. package/dist/types/lib/mcp/mcpClient.d.ts.map +1 -1
  99. package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
  100. package/dist/types/lib/mcp/types.d.ts +71 -7
  101. package/dist/types/lib/mcp/types.d.ts.map +1 -1
  102. package/dist/types/tool-providers/index.d.ts +1 -1
  103. package/dist/types/tool-providers/index.d.ts.map +1 -1
  104. package/package.json +1 -1
@@ -26,9 +26,19 @@
26
26
  * permission gate has always applied to a checker that throws: a
27
27
  * governance layer whose failure mode is "allow" is not a governance
28
28
  * layer.
29
+ *
30
+ * **The result comes back through the onion.** `runToolAfterChain` walks the
31
+ * SAME list in reverse, so the first-declared link gets the first word about
32
+ * the call and the last word about the result. An outer rule is the one that
33
+ * sees what every inner rule already did — which is the only order in which
34
+ * "wrap" means anything.
35
+ *
36
+ * **A link that has no hook for a moment files no row.** It did not decide;
37
+ * saying it allowed would be inventing a decision, and the ledger's whole
38
+ * value is that a row means somebody looked.
29
39
  */
30
40
  Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.runMessageChain = exports.runToolChain = void 0;
41
+ exports.runMessageChain = exports.runToolAfterChain = exports.runToolChain = void 0;
32
42
  /** Walk the tool chain. Never throws — a throwing link becomes a denial. */
33
43
  async function runToolChain(chain, input) {
34
44
  const decisions = [];
@@ -36,8 +46,13 @@ async function runToolChain(chain, input) {
36
46
  let args = input.args;
37
47
  for (let i = input.startIndex ?? 0; i < chain.length; i++) {
38
48
  const mw = chain[i];
49
+ // A result-only link takes no part in dispatch — and files no row here,
50
+ // because it did not decide anything about this call.
51
+ if (typeof mw.onToolCall !== 'function')
52
+ continue;
39
53
  const row = (extra) => ({
40
54
  middleware: mw.name,
55
+ moment: 'before-tool',
41
56
  at: 'tool',
42
57
  toolName: input.toolName,
43
58
  toolCallId: input.toolCallId,
@@ -50,6 +65,10 @@ async function runToolChain(chain, input) {
50
65
  try {
51
66
  outcome = await mw.onToolCall({
52
67
  toolName: input.toolName,
68
+ // Present only when the tool HAS a source. An `undefined` key is not
69
+ // the same fact as an absent one to a middleware that spells its rule
70
+ // `'toolSource' in call`, and "the agent's own" is an absence.
71
+ ...(input.toolSource !== undefined && { toolSource: input.toolSource }),
53
72
  toolCallId: input.toolCallId,
54
73
  iteration: input.iteration,
55
74
  args,
@@ -90,12 +109,90 @@ async function runToolChain(chain, input) {
90
109
  decisions.push(row({ changed: true, ...(outcome.why && { why: outcome.why }), before, after: args }));
91
110
  }
92
111
  else {
93
- decisions.push(row({}));
112
+ // `allow(undefined, why)` — nothing moved, and the link said why it was
113
+ // comfortable. The reason belongs on the row of the call it permitted.
114
+ decisions.push(row(outcome.why ? { why: outcome.why } : {}));
94
115
  }
95
116
  }
96
117
  return { kind: 'allow', args, decisions };
97
118
  }
98
119
  exports.runToolChain = runToolChain;
120
+ /**
121
+ * Walk the chain BACKWARDS over a finished call. Never throws — a throwing
122
+ * link becomes a denial, which at this moment means the model reads the
123
+ * reason instead of the result.
124
+ *
125
+ * Only called for a call that actually executed. A call the chain denied, or
126
+ * one still waiting on a person, has no result to decide about, and asking a
127
+ * rule about a result that does not exist would be the same fabrication the
128
+ * outcome union exists to prevent.
129
+ */
130
+ async function runToolAfterChain(chain, input) {
131
+ const decisions = [];
132
+ const real = input.result;
133
+ let result = real;
134
+ // Reverse: first-declared saw the call first, so it sees the result last.
135
+ for (let i = chain.length - 1; i >= 0; i--) {
136
+ const mw = chain[i];
137
+ const hook = mw.onToolResult;
138
+ if (typeof hook !== 'function')
139
+ continue;
140
+ const row = (extra) => ({
141
+ middleware: mw.name,
142
+ moment: 'after-tool',
143
+ at: 'tool',
144
+ toolName: input.toolName,
145
+ toolCallId: input.toolCallId,
146
+ iteration: input.iteration,
147
+ outcome: 'allow',
148
+ changed: false,
149
+ ...extra,
150
+ });
151
+ let outcome;
152
+ try {
153
+ outcome = await hook.call(mw, {
154
+ toolName: input.toolName,
155
+ ...(input.toolSource !== undefined && { toolSource: input.toolSource }),
156
+ toolCallId: input.toolCallId,
157
+ iteration: input.iteration,
158
+ args: input.args,
159
+ result,
160
+ ...(input.error === true && { error: true }),
161
+ history: input.history,
162
+ ...(input.identity && { identity: input.identity }),
163
+ ...(input.signal && { signal: input.signal }),
164
+ });
165
+ }
166
+ catch (err) {
167
+ const reason = `middleware '${mw.name}' threw: ${err instanceof Error ? err.message : String(err)}`;
168
+ decisions.push(row({ outcome: 'deny', changed: true, why: reason, before: result, after: reason }));
169
+ return { kind: 'deny', reason, middleware: mw.name, result: real, decisions };
170
+ }
171
+ if (outcome.kind === 'deny') {
172
+ // `changed: true` on purpose: unlike a refusal before dispatch, this one
173
+ // DOES replace something. The real result rides `before` — often the
174
+ // only copy of it in the run.
175
+ decisions.push(row({
176
+ outcome: 'deny',
177
+ changed: true,
178
+ why: outcome.reason,
179
+ before: result,
180
+ after: outcome.reason,
181
+ }));
182
+ return { kind: 'deny', reason: outcome.reason, middleware: mw.name, result: real, decisions };
183
+ }
184
+ if (outcome.value !== undefined) {
185
+ const before = result;
186
+ result = outcome.value;
187
+ decisions.push(row({ changed: true, ...(outcome.why && { why: outcome.why }), before, after: result }));
188
+ }
189
+ else {
190
+ decisions.push(row(outcome.why ? { why: outcome.why } : {}));
191
+ }
192
+ }
193
+ return { kind: 'allow', result, decisions };
194
+ }
195
+ exports.runToolAfterChain = runToolAfterChain;
99
196
  /** Walk the message chain. Never throws — a throwing link becomes a denial. */
100
197
  async function runMessageChain(chain, input) {
101
198
  const decisions = [];
@@ -103,6 +200,7 @@ async function runMessageChain(chain, input) {
103
200
  for (const mw of chain) {
104
201
  const row = (extra) => ({
105
202
  middleware: mw.name,
203
+ moment: input.phase,
106
204
  at: 'message',
107
205
  phase: input.phase,
108
206
  iteration: input.iteration,
@@ -135,7 +233,7 @@ async function runMessageChain(chain, input) {
135
233
  decisions.push(row({ changed: true, ...(outcome.why && { why: outcome.why }), before, after: content }));
136
234
  }
137
235
  else {
138
- decisions.push(row({}));
236
+ decisions.push(row(outcome.why ? { why: outcome.why } : {}));
139
237
  }
140
238
  }
141
239
  return { kind: 'allow', content, decisions };
@@ -1 +1 @@
1
- {"version":3,"file":"runChain.js","sourceRoot":"","sources":["../../../../src/core/agent/middleware/runChain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runChain.js","sourceRoot":"","sources":["../../../../src/core/agent/middleware/runChain.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,36 @@
36
36
  * `checkIn` and `askHuman` already go through. `MessageOutcome` does not,
37
37
  * because the message boundary is a plain stage, and inventing a second
38
38
  * pause to give it one would be a worse answer than not offering it.
39
+ * `ToolResultOutcome` does not either — see below.
40
+ *
41
+ * ## The two moments of a tool call
42
+ *
43
+ * A tool middleware may speak twice about one call:
44
+ *
45
+ * `onToolCall` BEFORE dispatch — about the call. Three verbs.
46
+ * `onToolResult` AFTER the tool ran, before its result enters the history
47
+ * or reaches the model — about the result. Two verbs.
48
+ *
49
+ * Each hook is named for what it RECEIVES; the moments they sit at are named
50
+ * `'before-tool'` and `'after-tool'` (and `.act()`'s keys after those).
51
+ *
52
+ * Either hook alone is a whole middleware; a link with only `onToolResult`
53
+ * does not take part in dispatch at all. The chain walks the two moments in **onion
54
+ * order**: the first-declared link sees the CALL first and the RESULT last —
55
+ * first word going in, last word coming out — which is the order that lets an
56
+ * outer rule inspect what every inner rule already did.
57
+ *
58
+ * **There is no `ask` at the after-tool moment.** Not because the machinery is missing —
59
+ * the dispatch loop pauses perfectly well — but because the tool has ALREADY
60
+ * RUN. A person woken to answer a question about a side effect that already
61
+ * happened cannot prevent it; the honest verbs there are "let the result
62
+ * through" and "do not let the model see it", and both are available now. The
63
+ * business cases this was measured against — authorize before, hide from the
64
+ * model, annotate the result, attach a fact through a context trigger — none
65
+ * of them needed a person at that moment. This is a refusal, not an oversight,
66
+ * and it is written here so evidence can promote it later: bring a case that
67
+ * genuinely needs a human at the after-tool moment and the arm can be added, on the
68
+ * pause machinery that already exists.
39
69
  */
40
70
  Object.defineProperty(exports, "__esModule", { value: true });
41
71
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/agent/middleware/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/agent/middleware/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /**
3
+ * moments — PUBLIC. The five places in the loop where a rule may speak.
4
+ *
5
+ * Pattern: Closed enumeration + a mechanical name mapping, with the mapping
6
+ * pinned by the compiler rather than by memory.
7
+ * Role: core/ layer. `LoopMoment` is the vocabulary `.act()` is keyed on
8
+ * and the vocabulary every ledger row now stamps itself with, so a
9
+ * person asking "where in the loop did this happen?" and a person
10
+ * asking "where in the loop can I intervene?" are reading the same
11
+ * five words.
12
+ * Emits: N/A (types + one pure function).
13
+ *
14
+ * ## Why the list is here and not inside `.act()`
15
+ *
16
+ * A bundle whose keys ARE the moments is only honest while the two sets
17
+ * agree. Keep the list of moments in the options type and the sixth moment
18
+ * ships with no key and nothing notices; keep it here, derive the key names
19
+ * from it, and the day a moment is added the build fails inside `act.ts`
20
+ * naming the key nobody wrote. That is the same trick `conformSource` plays
21
+ * on the outside world, turned inward on ourselves.
22
+ *
23
+ * The mapping between the two spellings is mechanical — kebab in the record
24
+ * (`'before-tool'`, which reads as a phase), camel in the bundle
25
+ * (`beforeTool`, which reads as a property) — and `actKeyFor` is its runtime
26
+ * twin, so the validator that decides which keys `.act()` accepts is
27
+ * DERIVED from this list rather than typed out beside it.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.actKeyFor = exports.LOOP_MOMENTS = void 0;
31
+ /**
32
+ * Every moment of one agent turn where a rule may act, in the order the loop
33
+ * reaches them.
34
+ *
35
+ * ```
36
+ * input → [ window → … LLM … → before-tool → tool → after-tool ]* → output
37
+ * ```
38
+ *
39
+ * `watch` attends all five and more; `act` attends exactly these. The
40
+ * difference is what a rule may DO there — an observer reports, a rule
41
+ * changes what happens next.
42
+ */
43
+ exports.LOOP_MOMENTS = ['input', 'before-tool', 'after-tool', 'window', 'output'];
44
+ /**
45
+ * The runtime twin of {@link ActKey}. `.act()`'s accepted key set is built
46
+ * from this over `LOOP_MOMENTS`, so an unknown key is refused by a rule that
47
+ * cannot fall behind the list it is derived from.
48
+ */
49
+ function actKeyFor(moment) {
50
+ return moment.replace(/-(.)/g, (_match, c) => c.toUpperCase());
51
+ }
52
+ exports.actKeyFor = actKeyFor;
53
+ //# sourceMappingURL=moments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moments.js","sourceRoot":"","sources":["../../../src/core/agent/moments.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;;AAEH;;;;;;;;;;;GAWG;AACU,QAAA,YAAY,GAAG,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAehG;;;;GAIG;AACH,SAAgB,SAAS,CAAC,MAAkB;IAC1C,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAW,CAAC;AACnF,CAAC;AAFD,8BAEC"}
@@ -24,7 +24,7 @@
24
24
  * Gate order for one call, and why it is this order:
25
25
  *
26
26
  * permission → MIDDLEWARE CHAIN → arg validation → check-in →
27
- * credentials → execute
27
+ * credentials → execute → THE CHAIN AGAIN, BACKWARDS (`onToolResult`)
28
28
  *
29
29
  * The chain sits after the permission gate so an existing checker still
30
30
  * decides first (a denial there means no middleware runs), and before arg
@@ -34,6 +34,11 @@
34
34
  * pauses on the SAME wire `checkIn` uses; the human's answer is a
35
35
  * decision, not a result, so the chain resumes and the REAL tool runs.
36
36
  *
37
+ * The last step is the same chain walked BACKWARDS over the result, before it
38
+ * becomes history — so the first-declared rule has the first word about the
39
+ * call and the last word about the answer. It runs only for a call that
40
+ * executed: everything the gates above refuse has no result to decide about.
41
+ *
37
42
  * `read_skill` is the auto-attached activation tool — when the LLM
38
43
  * calls it with a valid Skill id, the next InjectionEngine pass
39
44
  * activates that Skill (lifetime: turn).
@@ -73,6 +78,45 @@ function buildToolCallsHandler(deps) {
73
78
  const cached = providerToolCache?.current ?? [];
74
79
  return cached.find((t) => t.schema.name === toolName);
75
80
  };
81
+ /**
82
+ * The after-tool moment: the chain's last word, on a call that RAN.
83
+ *
84
+ * Called from all three dispatch sites (the loop, an approved ask, an
85
+ * approved check-in) and from nowhere else — every one of them has just
86
+ * executed a tool, which is the entire precondition. A call the chain
87
+ * denied, a call whose args were rejected, a call whose credential never
88
+ * issued and a call still waiting on a person have no result, and asking a
89
+ * rule about a result that does not exist would be the same fabrication the
90
+ * outcome union removes.
91
+ *
92
+ * Returns what the MODEL reads. The real result stays with the caller for
93
+ * `stream.tool_end`, so an event stream keeps reporting what the tool
94
+ * returned while the history carries what the rules allowed through — and
95
+ * the ledger row beside them says which is which.
96
+ */
97
+ const afterMoment = async (scope, call) => {
98
+ const chain = deps.toolMiddleware ?? [];
99
+ // No `onToolResult` hook anywhere in the chain → no walk, no rows, no await
100
+ // beyond the ones this dispatch already made. An agent whose middleware
101
+ // only governs calls is byte-identical to one built before this moment
102
+ // existed.
103
+ if (!chain.some((mw) => typeof mw.onToolResult === 'function'))
104
+ return call.result;
105
+ const verdict = await (0, runChain_js_1.runToolAfterChain)(chain, {
106
+ toolName: call.toolName,
107
+ ...(call.tool?.source !== undefined && { toolSource: call.tool.source }),
108
+ toolCallId: call.toolCallId,
109
+ iteration: call.iteration,
110
+ args: call.args,
111
+ result: call.result,
112
+ ...(call.error === true && { error: true }),
113
+ history: call.history,
114
+ ...(call.identity && { identity: call.identity }),
115
+ ...(call.signal && { signal: call.signal }),
116
+ });
117
+ (0, ledger_js_1.recordDecisions)(scope, verdict.decisions);
118
+ return verdict.kind === 'deny' ? verdict.reason : verdict.result;
119
+ };
76
120
  // Resolve a tool's declared credential (declare-and-push) and execute it,
77
121
  // emitting the same credential.* events as the main loop. Used by the
78
122
  // check-in RESUME path when a human APPROVES — the tool never ran at pause
@@ -137,16 +181,24 @@ function buildToolCallsHandler(deps) {
137
181
  hasCredentials,
138
182
  ...(resolvedCredential && { credential: resolvedCredential }),
139
183
  });
140
- return { result };
184
+ return { result, executed: true };
141
185
  }
142
186
  catch (err) {
143
187
  if ((0, pause_js_1.isPauseRequest)(err)) {
144
188
  return {
145
189
  result: `tool '${toolName}' requested a pause while resuming an approved check-in, which is not supported`,
146
190
  error: true,
191
+ // It ran — a tool that asked to pause had already started work.
192
+ executed: true,
147
193
  };
148
194
  }
149
- return { result: err instanceof Error ? err.message : String(err), error: true };
195
+ // A tool that threw still RAN, and may have done half its work; the
196
+ // after-tool moment exists precisely for the rules that care about that.
197
+ return {
198
+ result: err instanceof Error ? err.message : String(err),
199
+ error: true,
200
+ executed: true,
201
+ };
150
202
  }
151
203
  };
152
204
  return {
@@ -234,6 +286,8 @@ function buildToolCallsHandler(deps) {
234
286
  // answer to "what did this call really run with".
235
287
  let callArgs = tc.args;
236
288
  let denied = false;
289
+ /** True once `tool.execute` has been entered — see `afterMoment`. */
290
+ let executed = false;
237
291
  let haltContext;
238
292
  if (permissionChecker) {
239
293
  try {
@@ -309,6 +363,9 @@ function buildToolCallsHandler(deps) {
309
363
  if (!denied && deps.toolMiddleware && deps.toolMiddleware.length > 0) {
310
364
  const chain = await (0, runChain_js_1.runToolChain)(deps.toolMiddleware, {
311
365
  toolName: tc.name,
366
+ // Provenance from the tool that is about to run, so a policy can
367
+ // scope to the server that served it. Absent for our own tools.
368
+ ...(tool?.source !== undefined && { toolSource: tool.source }),
312
369
  toolCallId: tc.id,
313
370
  iteration,
314
371
  args: callArgs,
@@ -497,6 +554,10 @@ function buildToolCallsHandler(deps) {
497
554
  try {
498
555
  if (!tool)
499
556
  throw new Error(`Unknown tool: ${tc.name}`);
557
+ // Set BEFORE the await: a tool that throws has still run, and a
558
+ // tool that does not exist has not. This flag is the entire
559
+ // precondition of the after-tool moment below.
560
+ executed = true;
500
561
  result = await tool.execute(callArgs, {
501
562
  toolCallId: tc.id,
502
563
  iteration,
@@ -556,6 +617,24 @@ function buildToolCallsHandler(deps) {
556
617
  }
557
618
  }
558
619
  }
620
+ // ── The after-tool moment ────────────────────────────────────────
621
+ // Last thing before the result becomes history, and only for a call
622
+ // that ran. `modelResult` is what the model reads; `result` stays the
623
+ // truth about the tool and is what `stream.tool_end` reports.
624
+ const modelResult = executed
625
+ ? await afterMoment(scope, {
626
+ ...(tool && { tool }),
627
+ toolName: tc.name,
628
+ toolCallId: tc.id,
629
+ iteration,
630
+ args: callArgs,
631
+ result,
632
+ ...(error === true && { error: true }),
633
+ history: newHistory,
634
+ ...(runIdentity && { identity: runIdentity }),
635
+ ...(env.signal && { signal: env.signal }),
636
+ })
637
+ : result;
559
638
  const durationMs = Date.now() - startMs;
560
639
  (0, typedEmit_js_1.typedEmit)(scope, 'agentfootprint.stream.tool_end', {
561
640
  toolCallId: tc.id,
@@ -563,7 +642,7 @@ function buildToolCallsHandler(deps) {
563
642
  durationMs,
564
643
  ...(error === true && { error: true }),
565
644
  });
566
- const resultStr = typeof result === 'string' ? result : (0, validators_js_1.safeStringify)(result);
645
+ const resultStr = typeof modelResult === 'string' ? modelResult : (0, validators_js_1.safeStringify)(modelResult);
567
646
  newHistory.push({
568
647
  role: 'tool',
569
648
  content: resultStr,
@@ -670,12 +749,16 @@ function buildToolCallsHandler(deps) {
670
749
  ? input
671
750
  : (0, checkin_js_1.checkInDeclined)({ by: 'unknown', note: 'resume input was not a CheckInDecision' });
672
751
  let result;
752
+ /** What the model reads. Differs from `result` only when a rule at the
753
+ * after-tool moment transformed or withheld it. */
754
+ let modelResult;
673
755
  let error;
674
756
  if (!decision.approved) {
675
757
  result = decision.note ? `declined by human: ${decision.note}` : 'declined by human';
676
758
  (0, ledger_js_1.recordDecisions)(scope, [
677
759
  {
678
760
  middleware: askedBy,
761
+ moment: 'before-tool',
679
762
  at: 'tool',
680
763
  toolName,
681
764
  toolCallId,
@@ -690,6 +773,7 @@ function buildToolCallsHandler(deps) {
690
773
  (0, ledger_js_1.recordDecisions)(scope, [
691
774
  {
692
775
  middleware: askedBy,
776
+ moment: 'before-tool',
693
777
  at: 'tool',
694
778
  toolName,
695
779
  toolCallId,
@@ -709,8 +793,14 @@ function buildToolCallsHandler(deps) {
709
793
  // model-visible refusal and the tool does NOT run. That is the same
710
794
  // rule already applied to a tool that tries to pause during an
711
795
  // approved check-in resume: at most one human question per resume.
796
+ // Resolved BEFORE the chain runs, not after, because the links that
797
+ // continue here must see the same `toolSource` the links before the
798
+ // ask saw. A chain that changed its mind about where a tool came from
799
+ // halfway through one dispatch would be worse than not knowing.
800
+ const tool = lookupTool(toolName);
712
801
  const rest = await (0, runChain_js_1.runToolChain)(deps.toolMiddleware ?? [], {
713
802
  toolName,
803
+ ...(tool?.source !== undefined && { toolSource: tool.source }),
714
804
  toolCallId,
715
805
  iteration,
716
806
  args,
@@ -719,7 +809,6 @@ function buildToolCallsHandler(deps) {
719
809
  askPolicy: 'refuse',
720
810
  });
721
811
  (0, ledger_js_1.recordDecisions)(scope, rest.decisions);
722
- const tool = lookupTool(toolName);
723
812
  if (rest.kind === 'deny') {
724
813
  result = rest.reason;
725
814
  }
@@ -739,9 +828,30 @@ function buildToolCallsHandler(deps) {
739
828
  const dispatched = await resolveCredentialAndExecute(scope, tool, toolName, rest.args, toolCallId, iteration, env);
740
829
  result = dispatched.result;
741
830
  error = dispatched.error;
831
+ // The tool ran on this side of the pause, so the chain gets its
832
+ // last word here too — a rule about results cannot be skipped by
833
+ // routing a call through a human.
834
+ if (dispatched.executed === true) {
835
+ modelResult = await afterMoment(scope, {
836
+ ...(tool && { tool }),
837
+ toolName,
838
+ toolCallId,
839
+ iteration,
840
+ args: rest.args,
841
+ result,
842
+ ...(error === true && { error: true }),
843
+ history: [...scope.history],
844
+ ...(scope.runIdentity && { identity: scope.runIdentity }),
845
+ ...(env.signal && { signal: env.signal }),
846
+ });
847
+ }
742
848
  }
743
849
  }
744
- const askResultStr = typeof result === 'string' ? result : (0, validators_js_1.safeStringify)(result);
850
+ // `modelResult` is only set where the after-tool moment ran; everywhere
851
+ // else the two are the same value.
852
+ if (modelResult === undefined)
853
+ modelResult = result;
854
+ const askResultStr = typeof modelResult === 'string' ? modelResult : (0, validators_js_1.safeStringify)(modelResult);
745
855
  const askHistory = [
746
856
  ...scope.history,
747
857
  { role: 'tool', content: askResultStr, toolCallId, toolName },
@@ -795,17 +905,38 @@ function buildToolCallsHandler(deps) {
795
905
  ...(decision.note !== undefined && { note: decision.note }),
796
906
  });
797
907
  let result;
908
+ /** What the model reads — see the ask path above. */
909
+ let modelResult;
798
910
  let error;
799
911
  if (decision.approved) {
800
912
  const env = scope.$getEnv();
801
- const dispatched = await resolveCredentialAndExecute(scope, lookupTool(toolName), toolName, args, toolCallId, iteration, env);
913
+ const tool = lookupTool(toolName);
914
+ const dispatched = await resolveCredentialAndExecute(scope, tool, toolName, args, toolCallId, iteration, env);
802
915
  result = dispatched.result;
803
916
  error = dispatched.error;
917
+ // Consent moved the execution to this side of the pause; the rules
918
+ // about results move with it.
919
+ if (dispatched.executed === true) {
920
+ modelResult = await afterMoment(scope, {
921
+ ...(tool && { tool }),
922
+ toolName,
923
+ toolCallId,
924
+ iteration,
925
+ args,
926
+ result,
927
+ ...(error === true && { error: true }),
928
+ history: [...scope.history],
929
+ ...(scope.runIdentity && { identity: scope.runIdentity }),
930
+ ...(env.signal && { signal: env.signal }),
931
+ });
932
+ }
804
933
  }
805
934
  else {
806
935
  result = decision.note ? `declined by human: ${decision.note}` : 'declined by human';
807
936
  }
808
- const decisionResultStr = typeof result === 'string' ? result : (0, validators_js_1.safeStringify)(result);
937
+ if (modelResult === undefined)
938
+ modelResult = result;
939
+ const decisionResultStr = typeof modelResult === 'string' ? modelResult : (0, validators_js_1.safeStringify)(modelResult);
809
940
  const decisionHistory = [
810
941
  ...scope.history,
811
942
  { role: 'tool', content: decisionResultStr, toolCallId, toolName },