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.
- package/README.md +34 -0
- package/ai-instructions/claude-code/SKILL.md +2 -1
- package/dist/core/agent/AgentBuilder.js +117 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/act.js +143 -0
- package/dist/core/agent/act.js.map +1 -0
- package/dist/core/agent/middleware/index.js +5 -0
- package/dist/core/agent/middleware/index.js.map +1 -1
- package/dist/core/agent/middleware/ledger.js +7 -0
- package/dist/core/agent/middleware/ledger.js.map +1 -1
- package/dist/core/agent/middleware/outcomes.js +9 -2
- package/dist/core/agent/middleware/outcomes.js.map +1 -1
- package/dist/core/agent/middleware/runChain.js +101 -3
- package/dist/core/agent/middleware/runChain.js.map +1 -1
- package/dist/core/agent/middleware/types.js +30 -0
- package/dist/core/agent/middleware/types.js.map +1 -1
- package/dist/core/agent/moments.js +53 -0
- package/dist/core/agent/moments.js.map +1 -0
- package/dist/core/agent/stages/toolCalls.js +139 -8
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/tools.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +71 -0
- package/dist/esm/core/agent/AgentBuilder.js +117 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/act.d.ts +69 -0
- package/dist/esm/core/agent/act.js +139 -0
- package/dist/esm/core/agent/act.js.map +1 -0
- package/dist/esm/core/agent/middleware/index.d.ts +6 -1
- package/dist/esm/core/agent/middleware/index.js +5 -0
- package/dist/esm/core/agent/middleware/index.js.map +1 -1
- package/dist/esm/core/agent/middleware/ledger.d.ts +6 -0
- package/dist/esm/core/agent/middleware/ledger.js +7 -0
- package/dist/esm/core/agent/middleware/ledger.js.map +1 -1
- package/dist/esm/core/agent/middleware/outcomes.d.ts +15 -0
- package/dist/esm/core/agent/middleware/outcomes.js +9 -2
- package/dist/esm/core/agent/middleware/outcomes.js.map +1 -1
- package/dist/esm/core/agent/middleware/runChain.d.ts +49 -0
- package/dist/esm/core/agent/middleware/runChain.js +99 -2
- package/dist/esm/core/agent/middleware/runChain.js.map +1 -1
- package/dist/esm/core/agent/middleware/types.d.ts +144 -10
- package/dist/esm/core/agent/middleware/types.js +30 -0
- package/dist/esm/core/agent/middleware/types.js.map +1 -1
- package/dist/esm/core/agent/moments.d.ts +55 -0
- package/dist/esm/core/agent/moments.js +49 -0
- package/dist/esm/core/agent/moments.js.map +1 -0
- package/dist/esm/core/agent/stages/toolCalls.d.ts +6 -1
- package/dist/esm/core/agent/stages/toolCalls.js +140 -9
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/tools.d.ts +18 -0
- package/dist/esm/core/tools.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +4 -0
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/mcp/index.d.ts +1 -1
- package/dist/esm/lib/mcp/mcpClient.js +104 -11
- package/dist/esm/lib/mcp/mcpClient.js.map +1 -1
- package/dist/esm/lib/mcp/mcpServe.js +31 -1
- package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
- package/dist/esm/lib/mcp/mockMcpClient.js +4 -0
- package/dist/esm/lib/mcp/mockMcpClient.js.map +1 -1
- package/dist/esm/lib/mcp/types.d.ts +71 -7
- package/dist/esm/tool-providers/index.d.ts +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/mcp/mcpClient.js +104 -11
- package/dist/lib/mcp/mcpClient.js.map +1 -1
- package/dist/lib/mcp/mcpServe.js +30 -0
- package/dist/lib/mcp/mcpServe.js.map +1 -1
- package/dist/lib/mcp/mockMcpClient.js +4 -0
- package/dist/lib/mcp/mockMcpClient.js.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +71 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/act.d.ts +70 -0
- package/dist/types/core/agent/act.d.ts.map +1 -0
- package/dist/types/core/agent/middleware/index.d.ts +6 -1
- package/dist/types/core/agent/middleware/index.d.ts.map +1 -1
- package/dist/types/core/agent/middleware/ledger.d.ts +6 -0
- package/dist/types/core/agent/middleware/ledger.d.ts.map +1 -1
- package/dist/types/core/agent/middleware/outcomes.d.ts +15 -0
- package/dist/types/core/agent/middleware/outcomes.d.ts.map +1 -1
- package/dist/types/core/agent/middleware/runChain.d.ts +49 -0
- package/dist/types/core/agent/middleware/runChain.d.ts.map +1 -1
- package/dist/types/core/agent/middleware/types.d.ts +144 -10
- package/dist/types/core/agent/middleware/types.d.ts.map +1 -1
- package/dist/types/core/agent/moments.d.ts +56 -0
- package/dist/types/core/agent/moments.d.ts.map +1 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts +6 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/tools.d.ts +18 -0
- package/dist/types/core/tools.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +4 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/mcp/index.d.ts +1 -1
- package/dist/types/lib/mcp/index.d.ts.map +1 -1
- package/dist/types/lib/mcp/mcpClient.d.ts.map +1 -1
- package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
- package/dist/types/lib/mcp/types.d.ts +71 -7
- package/dist/types/lib/mcp/types.d.ts.map +1 -1
- package/dist/types/tool-providers/index.d.ts +1 -1
- package/dist/types/tool-providers/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* act — PUBLIC. One bundle for every place a rule may speak.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Facade over five doors, with the facade's KEYS type-locked to the
|
|
5
|
+
* list of moments they cover.
|
|
6
|
+
* Role: core/ layer. `.act()` builds nothing new: it validates a bundle
|
|
7
|
+
* and calls `.messageMiddleware()`, `.toolMiddleware()` and
|
|
8
|
+
* `.window()` with exactly what a person would have passed by hand.
|
|
9
|
+
* Everything about a run is decided by those doors, here and there
|
|
10
|
+
* alike.
|
|
11
|
+
* Emits: N/A.
|
|
12
|
+
*
|
|
13
|
+
* ## Why a bundle at all, when the doors already exist
|
|
14
|
+
*
|
|
15
|
+
* Because the doors are findable one at a time and the POSTURE is not. An
|
|
16
|
+
* agent's governance currently reads as four unrelated calls scattered
|
|
17
|
+
* through a builder chain, and the question a reviewer actually has —
|
|
18
|
+
* "what does this agent do at each point in its loop?" — has no place to be
|
|
19
|
+
* answered. `.act({ … })` is that place: five optional keys, named for the
|
|
20
|
+
* five moments, so autocomplete on an empty object teaches the loop.
|
|
21
|
+
*
|
|
22
|
+
* ## The completeness lock
|
|
23
|
+
*
|
|
24
|
+
* The keys of {@link ActOptions} are pinned, at compile time, against
|
|
25
|
+
* `ActKey<LoopMoment>` — the moment list, camel-cased. Add a sixth moment to
|
|
26
|
+
* `LOOP_MOMENTS` and this file stops compiling until the bundle grows the key
|
|
27
|
+
* for it; delete a key and the same. A surface that claims to be complete has
|
|
28
|
+
* to be made unable to fall behind, or the claim is just a sentence in a doc.
|
|
29
|
+
*
|
|
30
|
+
* The runtime half is derived from the same list: the accepted key set is
|
|
31
|
+
* `LOOP_MOMENTS.map(actKeyFor)`, so a typo'd key is refused by a validator
|
|
32
|
+
* that cannot drift from the type it is validating.
|
|
33
|
+
*/
|
|
34
|
+
import { allow } from './middleware/outcomes.js';
|
|
35
|
+
import { actKeyFor, LOOP_MOMENTS } from './moments.js';
|
|
36
|
+
const _keysAreExactlyTheMoments = true;
|
|
37
|
+
void _keysAreExactlyTheMoments;
|
|
38
|
+
/** The keys `.act()` accepts, derived from the moment list rather than typed. */
|
|
39
|
+
export const ACT_KEYS = LOOP_MOMENTS.map(actKeyFor);
|
|
40
|
+
/**
|
|
41
|
+
* Restrict a message middleware to ONE phase.
|
|
42
|
+
*
|
|
43
|
+
* `.messageMiddleware()` attaches a link to both halves of the boundary and
|
|
44
|
+
* lets it read `msg.phase`; the bundle names the phases instead, so an entry
|
|
45
|
+
* written for one of them is wrapped in exactly the guard a person writes by
|
|
46
|
+
* hand today. The pass-through at the other phase is a real walk with a real
|
|
47
|
+
* row, because it is a real link in the chain — the same run, the same
|
|
48
|
+
* record, whichever spelling put it there.
|
|
49
|
+
*/
|
|
50
|
+
function onlyAt(phase, mw) {
|
|
51
|
+
return {
|
|
52
|
+
name: mw.name,
|
|
53
|
+
onMessage: (msg) => (msg.phase === phase ? mw.onMessage(msg) : allow()),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function assertList(value, key) {
|
|
57
|
+
if (!Array.isArray(value)) {
|
|
58
|
+
throw new Error(`AgentBuilder.act: '${key}' expects an array of middleware, got ${typeof value}. ` +
|
|
59
|
+
`Wrap a single rule in an array — the bundle is a list per moment.`);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
function assertNamedHook(mw, key, hook) {
|
|
64
|
+
if (mw === null ||
|
|
65
|
+
typeof mw !== 'object' ||
|
|
66
|
+
typeof mw.name !== 'string' ||
|
|
67
|
+
mw.name.length === 0 ||
|
|
68
|
+
typeof mw[hook] !== 'function') {
|
|
69
|
+
throw new Error(`AgentBuilder.act: every '${key}' entry needs a non-empty \`name\` and a \`${hook}(...)\` ` +
|
|
70
|
+
`method. The name is what every ledger row and event says decided the call, so it ` +
|
|
71
|
+
`cannot be blank` +
|
|
72
|
+
(hook === 'onToolCall'
|
|
73
|
+
? `; a rule that only has \`onToolResult\` belongs under 'afterTool'.`
|
|
74
|
+
: hook === 'onToolResult'
|
|
75
|
+
? `; a rule that only has \`onToolCall\` belongs under 'beforeTool'.`
|
|
76
|
+
: `.`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validate a bundle and turn it into the arguments the five doors take.
|
|
81
|
+
*
|
|
82
|
+
* Pure — it throws or it returns; it touches no builder state. `.act()` is
|
|
83
|
+
* the caller that hands the result to the doors, which is what makes the
|
|
84
|
+
* sugar provably the same agent.
|
|
85
|
+
*/
|
|
86
|
+
export function resolveAct(options) {
|
|
87
|
+
if (options === null || typeof options !== 'object' || Array.isArray(options)) {
|
|
88
|
+
throw new Error(`AgentBuilder.act: expected an options object, got ${Array.isArray(options) ? 'an array' : typeof options}. The keys are ${ACT_KEYS.join(', ')}.`);
|
|
89
|
+
}
|
|
90
|
+
for (const key of Object.keys(options)) {
|
|
91
|
+
if (!ACT_KEYS.includes(key)) {
|
|
92
|
+
throw new Error(`AgentBuilder.act: unknown key '${key}'. The loop has ${LOOP_MOMENTS.length} moments and ` +
|
|
93
|
+
`this bundle has one key for each: ${ACT_KEYS.join(', ')}. A key nobody reads is a ` +
|
|
94
|
+
`governance rule that silently never runs, so it is refused here rather than ignored.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ── The message halves ──────────────────────────────────────────────
|
|
98
|
+
// A link named at BOTH phases is attached once, unguarded — which is the
|
|
99
|
+
// plain `.messageMiddleware(mw)` spelling, and the one that files one row
|
|
100
|
+
// per phase instead of two.
|
|
101
|
+
const input = assertList(options.input ?? [], 'input');
|
|
102
|
+
const output = assertList(options.output ?? [], 'output');
|
|
103
|
+
for (const mw of input)
|
|
104
|
+
assertNamedHook(mw, 'input', 'onMessage');
|
|
105
|
+
for (const mw of output)
|
|
106
|
+
assertNamedHook(mw, 'output', 'onMessage');
|
|
107
|
+
const message = [];
|
|
108
|
+
for (const mw of input) {
|
|
109
|
+
message.push(output.includes(mw) ? mw : onlyAt('input', mw));
|
|
110
|
+
}
|
|
111
|
+
for (const mw of output) {
|
|
112
|
+
if (!input.includes(mw))
|
|
113
|
+
message.push(onlyAt('output', mw));
|
|
114
|
+
}
|
|
115
|
+
// ── The tool moments ────────────────────────────────────────────────
|
|
116
|
+
// One list, walked forwards for calls and backwards for results. The
|
|
117
|
+
// buckets are named for the MOMENTS (`afterTool` ⇄ `'after-tool'`); the
|
|
118
|
+
// hooks are named for what they RECEIVE (`onToolResult`). The bucket says
|
|
119
|
+
// where a rule is MEANT to speak and is checked for the hook it names; what
|
|
120
|
+
// it actually does is decided by the hooks it has, so a rule can never
|
|
121
|
+
// silently fail to run because it was written in the other bucket.
|
|
122
|
+
const beforeTool = assertList(options.beforeTool ?? [], 'beforeTool');
|
|
123
|
+
const afterTool = assertList(options.afterTool ?? [], 'afterTool');
|
|
124
|
+
for (const mw of beforeTool)
|
|
125
|
+
assertNamedHook(mw, 'beforeTool', 'onToolCall');
|
|
126
|
+
for (const mw of afterTool)
|
|
127
|
+
assertNamedHook(mw, 'afterTool', 'onToolResult');
|
|
128
|
+
const tool = [...beforeTool];
|
|
129
|
+
for (const mw of afterTool) {
|
|
130
|
+
if (!tool.includes(mw))
|
|
131
|
+
tool.push(mw);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
message,
|
|
135
|
+
tool,
|
|
136
|
+
...(options.window !== undefined && { window: options.window }),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=act.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"act.js","sourceRoot":"","sources":["../../../../src/core/agent/act.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Three verbs: `allow`, `deny`, `ask`. There is no fourth, and in
|
|
12
12
|
* particular there is no way to return a result — see `types.ts`.
|
|
13
|
+
*
|
|
14
|
+
* A tool link may speak twice: `onToolCall` about the call, `onToolResult`
|
|
15
|
+
* about the result. The chain is walked forwards for the first and backwards for the
|
|
16
|
+
* second, so the first-declared link has the first word going in and the last
|
|
17
|
+
* word coming out.
|
|
13
18
|
*/
|
|
14
19
|
export { allow, ask, deny } from './outcomes.js';
|
|
15
20
|
export { MessageDeniedError, type MessageDeniedContext } from './errors.js';
|
|
16
|
-
export type { AllowOutcome, AskOutcome, AskPayload, DenyOutcome, MessageMiddleware, MessageMiddlewareContext, MessageOutcome, MiddlewareDecision, ToolMiddleware, ToolMiddlewareContext, ToolOutcome, } from './types.js';
|
|
21
|
+
export type { AllowOutcome, AskOutcome, AskPayload, DenyOutcome, MessageMiddleware, MessageMiddlewareContext, MessageOutcome, MiddlewareDecision, ToolCallMiddleware, ToolMiddleware, ToolMiddlewareContext, ToolOutcome, ToolResultContext, ToolResultMiddleware, ToolResultOutcome, } from './types.js';
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Three verbs: `allow`, `deny`, `ask`. There is no fourth, and in
|
|
12
12
|
* particular there is no way to return a result — see `types.ts`.
|
|
13
|
+
*
|
|
14
|
+
* A tool link may speak twice: `onToolCall` about the call, `onToolResult`
|
|
15
|
+
* about the result. The chain is walked forwards for the first and backwards for the
|
|
16
|
+
* second, so the first-declared link has the first word going in and the last
|
|
17
|
+
* word coming out.
|
|
13
18
|
*/
|
|
14
19
|
export { allow, ask, deny } from './outcomes.js';
|
|
15
20
|
export { MessageDeniedError } from './errors.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAA6B,MAAM,aAAa,CAAC"}
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* disagreement from a lie into a record. Every slice taken afterwards can
|
|
17
17
|
* then find the moment the value changed and who changed it.
|
|
18
18
|
*
|
|
19
|
+
* The same reasoning covers the `'after-tool'` moment from the other side. A
|
|
20
|
+
* result the model was not allowed to read still HAPPENED — the tool ran, the
|
|
21
|
+
* side effect landed — so the refusal row carries the real result. A run that
|
|
22
|
+
* dropped it would record an agent that called a tool and got nothing back,
|
|
23
|
+
* which is not what occurred.
|
|
24
|
+
*
|
|
19
25
|
* This is not a redaction layer, and it is not trying to be one. For the
|
|
20
26
|
* `'input'` phase in particular, the ledger row is the ONLY copy of the
|
|
21
27
|
* pre-scrub text anywhere in the run — the seed stage commits the
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* disagreement from a lie into a record. Every slice taken afterwards can
|
|
17
17
|
* then find the moment the value changed and who changed it.
|
|
18
18
|
*
|
|
19
|
+
* The same reasoning covers the `'after-tool'` moment from the other side. A
|
|
20
|
+
* result the model was not allowed to read still HAPPENED — the tool ran, the
|
|
21
|
+
* side effect landed — so the refusal row carries the real result. A run that
|
|
22
|
+
* dropped it would record an agent that called a tool and got nothing back,
|
|
23
|
+
* which is not what occurred.
|
|
24
|
+
*
|
|
19
25
|
* This is not a redaction layer, and it is not trying to be one. For the
|
|
20
26
|
* `'input'` phase in particular, the ledger row is the ONLY copy of the
|
|
21
27
|
* pre-scrub text anywhere in the run — the seed stage commits the
|
|
@@ -43,6 +49,7 @@ export function recordDecisions(scope, rows) {
|
|
|
43
49
|
for (const row of rows) {
|
|
44
50
|
typedEmit(scope, 'agentfootprint.middleware.decision', {
|
|
45
51
|
middleware: row.middleware,
|
|
52
|
+
moment: row.moment,
|
|
46
53
|
at: row.at,
|
|
47
54
|
...(row.phase !== undefined && { phase: row.phase }),
|
|
48
55
|
...(row.toolName !== undefined && { toolName: row.toolName }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/ledger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AASjE;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB,EAAE,IAAmC;IACrF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9B,MAAM,IAAI,GAAI,KAAK,CAAC,mBAAiE,IAAI,EAAE,CAAC;IAC5F,2EAA2E;IAC3E,4EAA4E;IAC5E,yEAAyE;IACzE,KAAK,CAAC,mBAAmB,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,SAAS,CAAC,KAAK,EAAE,oCAAoC,EAAE;YACrD,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC7D,GAAG,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;YACnE,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,SAAS,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -17,6 +17,15 @@
|
|
|
17
17
|
import type { AllowOutcome, AskOutcome, AskPayload, DenyOutcome } from './types.js';
|
|
18
18
|
/** Pass the value through untouched. */
|
|
19
19
|
export declare function allow(): AllowOutcome<never>;
|
|
20
|
+
/**
|
|
21
|
+
* Pass the value through untouched, and say why you were comfortable.
|
|
22
|
+
*
|
|
23
|
+
* The row still reads `changed: false` — nothing moved — but it carries the
|
|
24
|
+
* reason, which is what a rule that remembers an earlier decision needs:
|
|
25
|
+
* "approved by dana@ops at 14:02" belongs in the record of the call it
|
|
26
|
+
* silently permitted, not only in the record of the call that asked.
|
|
27
|
+
*/
|
|
28
|
+
export declare function allow(value: undefined, why: string): AllowOutcome<never>;
|
|
20
29
|
/**
|
|
21
30
|
* Replace the value and say why.
|
|
22
31
|
*
|
|
@@ -31,6 +40,12 @@ export declare function allow<T>(value: T, why: string): AllowOutcome<T>;
|
|
|
31
40
|
* For a tool the reason reaches the model verbatim, as the tool's result,
|
|
32
41
|
* and the loop continues — the agent gets to adapt. For a message it
|
|
33
42
|
* surfaces as a `MessageDeniedError`.
|
|
43
|
+
*
|
|
44
|
+
* At the after-tool moment it means "the model does not get to read this" — the
|
|
45
|
+
* tool has already run, so the refusal replaces what the model reads while
|
|
46
|
+
* the run keeps the real result in the ledger. Refusing there hides an answer
|
|
47
|
+
* from the model; it cannot un-happen a side effect, and it does not pretend
|
|
48
|
+
* to.
|
|
34
49
|
*/
|
|
35
50
|
export declare function deny(reason: string): DenyOutcome;
|
|
36
51
|
/**
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* disagree, so it is the only thing required to say why.
|
|
16
16
|
*/
|
|
17
17
|
export function allow(value, why) {
|
|
18
|
-
if (value === undefined)
|
|
19
|
-
return { kind: 'allow' };
|
|
18
|
+
if (value === undefined) {
|
|
19
|
+
return typeof why === 'string' && why.length > 0 ? { kind: 'allow', why } : { kind: 'allow' };
|
|
20
|
+
}
|
|
20
21
|
if (typeof why !== 'string' || why.length === 0) {
|
|
21
22
|
throw new Error('allow(value, why): a transform must say why. Pass a short reason — it is what the ' +
|
|
22
23
|
'ledger shows next to the before/after pair. To pass the value through unchanged, ' +
|
|
@@ -30,6 +31,12 @@ export function allow(value, why) {
|
|
|
30
31
|
* For a tool the reason reaches the model verbatim, as the tool's result,
|
|
31
32
|
* and the loop continues — the agent gets to adapt. For a message it
|
|
32
33
|
* surfaces as a `MessageDeniedError`.
|
|
34
|
+
*
|
|
35
|
+
* At the after-tool moment it means "the model does not get to read this" — the
|
|
36
|
+
* tool has already run, so the refusal replaces what the model reads while
|
|
37
|
+
* the run keeps the real result in the ledger. Refusing there hides an answer
|
|
38
|
+
* from the model; it cannot un-happen a side effect, and it does not pretend
|
|
39
|
+
* to.
|
|
33
40
|
*/
|
|
34
41
|
export function deny(reason) {
|
|
35
42
|
if (typeof reason !== 'string' || reason.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outcomes.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/outcomes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"outcomes.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/outcomes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAuBH,MAAM,UAAU,KAAK,CAAI,KAAS,EAAE,GAAY;IAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,oFAAoF;YAClF,mFAAmF;YACnF,iCAAiC,CACpC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,IAAI,CAAC,MAAc;IACjC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,mFAAmF;YACjF,qEAAqE,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,CAAC,OAAmB;IACrC,IACE,OAAO,KAAK,IAAI;QAChB,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;QACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAC7B,CAAC;QACD,MAAM,IAAI,KAAK,CACb,uFAAuF;YACrF,gDAAgD,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -25,6 +25,16 @@
|
|
|
25
25
|
* permission gate has always applied to a checker that throws: a
|
|
26
26
|
* governance layer whose failure mode is "allow" is not a governance
|
|
27
27
|
* layer.
|
|
28
|
+
*
|
|
29
|
+
* **The result comes back through the onion.** `runToolAfterChain` walks the
|
|
30
|
+
* SAME list in reverse, so the first-declared link gets the first word about
|
|
31
|
+
* the call and the last word about the result. An outer rule is the one that
|
|
32
|
+
* sees what every inner rule already did — which is the only order in which
|
|
33
|
+
* "wrap" means anything.
|
|
34
|
+
*
|
|
35
|
+
* **A link that has no hook for a moment files no row.** It did not decide;
|
|
36
|
+
* saying it allowed would be inventing a decision, and the ledger's whole
|
|
37
|
+
* value is that a row means somebody looked.
|
|
28
38
|
*/
|
|
29
39
|
import type { LLMMessage } from '../../../adapters/types.js';
|
|
30
40
|
import type { MemoryIdentity } from '../../../memory/identity/types.js';
|
|
@@ -63,6 +73,8 @@ export type ToolChainResult = {
|
|
|
63
73
|
};
|
|
64
74
|
export interface ToolChainInput {
|
|
65
75
|
readonly toolName: string;
|
|
76
|
+
/** `Tool.source` for the tool being dispatched, when it has one. */
|
|
77
|
+
readonly toolSource?: string;
|
|
66
78
|
readonly toolCallId: string;
|
|
67
79
|
readonly iteration: number;
|
|
68
80
|
readonly args: ToolArgs;
|
|
@@ -79,6 +91,43 @@ export interface ToolChainInput {
|
|
|
79
91
|
}
|
|
80
92
|
/** Walk the tool chain. Never throws — a throwing link becomes a denial. */
|
|
81
93
|
export declare function runToolChain(chain: readonly ToolMiddleware[], input: ToolChainInput): Promise<ToolChainResult>;
|
|
94
|
+
export type ToolAfterChainResult = {
|
|
95
|
+
readonly kind: 'allow';
|
|
96
|
+
readonly result: unknown;
|
|
97
|
+
readonly decisions: MiddlewareDecision[];
|
|
98
|
+
} | {
|
|
99
|
+
readonly kind: 'deny';
|
|
100
|
+
readonly reason: string;
|
|
101
|
+
readonly middleware: string;
|
|
102
|
+
/** The tool's REAL result. The side effect happened; the record says so. */
|
|
103
|
+
readonly result: unknown;
|
|
104
|
+
readonly decisions: MiddlewareDecision[];
|
|
105
|
+
};
|
|
106
|
+
export interface ToolAfterChainInput {
|
|
107
|
+
readonly toolName: string;
|
|
108
|
+
readonly toolSource?: string;
|
|
109
|
+
readonly toolCallId: string;
|
|
110
|
+
readonly iteration: number;
|
|
111
|
+
/** The args the tool ACTUALLY ran with — every before-transform applied. */
|
|
112
|
+
readonly args: ToolArgs;
|
|
113
|
+
readonly result: unknown;
|
|
114
|
+
/** `true` when the tool threw and `result` is the error's message. */
|
|
115
|
+
readonly error?: true;
|
|
116
|
+
readonly history: readonly LLMMessage[];
|
|
117
|
+
readonly identity?: MemoryIdentity;
|
|
118
|
+
readonly signal?: AbortSignal;
|
|
119
|
+
}
|
|
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
|
+
export declare function runToolAfterChain(chain: readonly ToolMiddleware[], input: ToolAfterChainInput): Promise<ToolAfterChainResult>;
|
|
82
131
|
export type MessageChainResult = {
|
|
83
132
|
readonly kind: 'allow';
|
|
84
133
|
readonly content: string;
|
|
@@ -25,6 +25,16 @@
|
|
|
25
25
|
* permission gate has always applied to a checker that throws: a
|
|
26
26
|
* governance layer whose failure mode is "allow" is not a governance
|
|
27
27
|
* layer.
|
|
28
|
+
*
|
|
29
|
+
* **The result comes back through the onion.** `runToolAfterChain` walks the
|
|
30
|
+
* SAME list in reverse, so the first-declared link gets the first word about
|
|
31
|
+
* the call and the last word about the result. An outer rule is the one that
|
|
32
|
+
* sees what every inner rule already did — which is the only order in which
|
|
33
|
+
* "wrap" means anything.
|
|
34
|
+
*
|
|
35
|
+
* **A link that has no hook for a moment files no row.** It did not decide;
|
|
36
|
+
* saying it allowed would be inventing a decision, and the ledger's whole
|
|
37
|
+
* value is that a row means somebody looked.
|
|
28
38
|
*/
|
|
29
39
|
/** Walk the tool chain. Never throws — a throwing link becomes a denial. */
|
|
30
40
|
export async function runToolChain(chain, input) {
|
|
@@ -33,8 +43,13 @@ export async function runToolChain(chain, input) {
|
|
|
33
43
|
let args = input.args;
|
|
34
44
|
for (let i = input.startIndex ?? 0; i < chain.length; i++) {
|
|
35
45
|
const mw = chain[i];
|
|
46
|
+
// A result-only link takes no part in dispatch — and files no row here,
|
|
47
|
+
// because it did not decide anything about this call.
|
|
48
|
+
if (typeof mw.onToolCall !== 'function')
|
|
49
|
+
continue;
|
|
36
50
|
const row = (extra) => ({
|
|
37
51
|
middleware: mw.name,
|
|
52
|
+
moment: 'before-tool',
|
|
38
53
|
at: 'tool',
|
|
39
54
|
toolName: input.toolName,
|
|
40
55
|
toolCallId: input.toolCallId,
|
|
@@ -47,6 +62,10 @@ export async function runToolChain(chain, input) {
|
|
|
47
62
|
try {
|
|
48
63
|
outcome = await mw.onToolCall({
|
|
49
64
|
toolName: input.toolName,
|
|
65
|
+
// Present only when the tool HAS a source. An `undefined` key is not
|
|
66
|
+
// the same fact as an absent one to a middleware that spells its rule
|
|
67
|
+
// `'toolSource' in call`, and "the agent's own" is an absence.
|
|
68
|
+
...(input.toolSource !== undefined && { toolSource: input.toolSource }),
|
|
50
69
|
toolCallId: input.toolCallId,
|
|
51
70
|
iteration: input.iteration,
|
|
52
71
|
args,
|
|
@@ -87,11 +106,88 @@ export async function runToolChain(chain, input) {
|
|
|
87
106
|
decisions.push(row({ changed: true, ...(outcome.why && { why: outcome.why }), before, after: args }));
|
|
88
107
|
}
|
|
89
108
|
else {
|
|
90
|
-
|
|
109
|
+
// `allow(undefined, why)` — nothing moved, and the link said why it was
|
|
110
|
+
// comfortable. The reason belongs on the row of the call it permitted.
|
|
111
|
+
decisions.push(row(outcome.why ? { why: outcome.why } : {}));
|
|
91
112
|
}
|
|
92
113
|
}
|
|
93
114
|
return { kind: 'allow', args, decisions };
|
|
94
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Walk the chain BACKWARDS over a finished call. Never throws — a throwing
|
|
118
|
+
* link becomes a denial, which at this moment means the model reads the
|
|
119
|
+
* reason instead of the result.
|
|
120
|
+
*
|
|
121
|
+
* Only called for a call that actually executed. A call the chain denied, or
|
|
122
|
+
* one still waiting on a person, has no result to decide about, and asking a
|
|
123
|
+
* rule about a result that does not exist would be the same fabrication the
|
|
124
|
+
* outcome union exists to prevent.
|
|
125
|
+
*/
|
|
126
|
+
export async function runToolAfterChain(chain, input) {
|
|
127
|
+
const decisions = [];
|
|
128
|
+
const real = input.result;
|
|
129
|
+
let result = real;
|
|
130
|
+
// Reverse: first-declared saw the call first, so it sees the result last.
|
|
131
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
132
|
+
const mw = chain[i];
|
|
133
|
+
const hook = mw.onToolResult;
|
|
134
|
+
if (typeof hook !== 'function')
|
|
135
|
+
continue;
|
|
136
|
+
const row = (extra) => ({
|
|
137
|
+
middleware: mw.name,
|
|
138
|
+
moment: 'after-tool',
|
|
139
|
+
at: 'tool',
|
|
140
|
+
toolName: input.toolName,
|
|
141
|
+
toolCallId: input.toolCallId,
|
|
142
|
+
iteration: input.iteration,
|
|
143
|
+
outcome: 'allow',
|
|
144
|
+
changed: false,
|
|
145
|
+
...extra,
|
|
146
|
+
});
|
|
147
|
+
let outcome;
|
|
148
|
+
try {
|
|
149
|
+
outcome = await hook.call(mw, {
|
|
150
|
+
toolName: input.toolName,
|
|
151
|
+
...(input.toolSource !== undefined && { toolSource: input.toolSource }),
|
|
152
|
+
toolCallId: input.toolCallId,
|
|
153
|
+
iteration: input.iteration,
|
|
154
|
+
args: input.args,
|
|
155
|
+
result,
|
|
156
|
+
...(input.error === true && { error: true }),
|
|
157
|
+
history: input.history,
|
|
158
|
+
...(input.identity && { identity: input.identity }),
|
|
159
|
+
...(input.signal && { signal: input.signal }),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
const reason = `middleware '${mw.name}' threw: ${err instanceof Error ? err.message : String(err)}`;
|
|
164
|
+
decisions.push(row({ outcome: 'deny', changed: true, why: reason, before: result, after: reason }));
|
|
165
|
+
return { kind: 'deny', reason, middleware: mw.name, result: real, decisions };
|
|
166
|
+
}
|
|
167
|
+
if (outcome.kind === 'deny') {
|
|
168
|
+
// `changed: true` on purpose: unlike a refusal before dispatch, this one
|
|
169
|
+
// DOES replace something. The real result rides `before` — often the
|
|
170
|
+
// only copy of it in the run.
|
|
171
|
+
decisions.push(row({
|
|
172
|
+
outcome: 'deny',
|
|
173
|
+
changed: true,
|
|
174
|
+
why: outcome.reason,
|
|
175
|
+
before: result,
|
|
176
|
+
after: outcome.reason,
|
|
177
|
+
}));
|
|
178
|
+
return { kind: 'deny', reason: outcome.reason, middleware: mw.name, result: real, decisions };
|
|
179
|
+
}
|
|
180
|
+
if (outcome.value !== undefined) {
|
|
181
|
+
const before = result;
|
|
182
|
+
result = outcome.value;
|
|
183
|
+
decisions.push(row({ changed: true, ...(outcome.why && { why: outcome.why }), before, after: result }));
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
decisions.push(row(outcome.why ? { why: outcome.why } : {}));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return { kind: 'allow', result, decisions };
|
|
190
|
+
}
|
|
95
191
|
/** Walk the message chain. Never throws — a throwing link becomes a denial. */
|
|
96
192
|
export async function runMessageChain(chain, input) {
|
|
97
193
|
const decisions = [];
|
|
@@ -99,6 +195,7 @@ export async function runMessageChain(chain, input) {
|
|
|
99
195
|
for (const mw of chain) {
|
|
100
196
|
const row = (extra) => ({
|
|
101
197
|
middleware: mw.name,
|
|
198
|
+
moment: input.phase,
|
|
102
199
|
at: 'message',
|
|
103
200
|
phase: input.phase,
|
|
104
201
|
iteration: input.iteration,
|
|
@@ -131,7 +228,7 @@ export async function runMessageChain(chain, input) {
|
|
|
131
228
|
decisions.push(row({ changed: true, ...(outcome.why && { why: outcome.why }), before, after: content }));
|
|
132
229
|
}
|
|
133
230
|
else {
|
|
134
|
-
decisions.push(row({}));
|
|
231
|
+
decisions.push(row(outcome.why ? { why: outcome.why } : {}));
|
|
135
232
|
}
|
|
136
233
|
}
|
|
137
234
|
return { kind: 'allow', content, decisions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runChain.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/runChain.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runChain.js","sourceRoot":"","sources":["../../../../../src/core/agent/middleware/runChain.ts"],"names":[],"mappings":"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"}
|