@adia-ai/agent 0.8.29 → 0.8.31
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/CHANGELOG.md +45 -0
- package/README.md +384 -11
- package/agent.d.ts +44 -3
- package/agent.d.ts.map +1 -1
- package/agent.js +172 -8
- package/agent.js.map +1 -1
- package/events.d.ts +46 -2
- package/events.d.ts.map +1 -1
- package/events.js +30 -1
- package/events.js.map +1 -1
- package/guardrail.d.ts +68 -0
- package/guardrail.d.ts.map +1 -0
- package/guardrail.js +79 -0
- package/guardrail.js.map +1 -0
- package/index.d.ts +15 -7
- package/index.d.ts.map +1 -1
- package/index.js +7 -3
- package/index.js.map +1 -1
- package/integrations.d.ts +19 -2
- package/integrations.d.ts.map +1 -1
- package/integrations.js +6 -1
- package/integrations.js.map +1 -1
- package/loop.d.ts +19 -8
- package/loop.d.ts.map +1 -1
- package/loop.js +176 -9
- package/loop.js.map +1 -1
- package/mcp-transport.d.ts +128 -0
- package/mcp-transport.d.ts.map +1 -0
- package/mcp-transport.js +361 -0
- package/mcp-transport.js.map +1 -0
- package/mcp.d.ts +120 -0
- package/mcp.d.ts.map +1 -0
- package/mcp.js +264 -0
- package/mcp.js.map +1 -0
- package/package.json +1 -1
- package/resource.d.ts +28 -3
- package/resource.d.ts.map +1 -1
- package/resource.js +43 -5
- package/resource.js.map +1 -1
- package/session.d.ts +18 -0
- package/session.d.ts.map +1 -1
- package/session.js +40 -0
- package/session.js.map +1 -1
- package/stub.d.ts +8 -0
- package/stub.d.ts.map +1 -1
- package/stub.js +13 -0
- package/stub.js.map +1 -1
- package/tools.d.ts +6 -0
- package/tools.d.ts.map +1 -1
- package/tools.js.map +1 -1
- package/trace.d.ts +50 -0
- package/trace.d.ts.map +1 -0
- package/trace.js +60 -0
- package/trace.js.map +1 -0
- package/workflow.d.ts +113 -11
- package/workflow.d.ts.map +1 -1
- package/workflow.js +93 -15
- package/workflow.js.map +1 -1
package/mcp.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP-client mode — a server becomes a tool/resource source.
|
|
3
|
+
*
|
|
4
|
+
* `mcpServer({ url })` declares a source; the agent connects it and every
|
|
5
|
+
* tool the server lists arrives as a normal `ToolDef` in the loop. Nothing
|
|
6
|
+
* downstream knows the difference: guardrails see the calls, the tracer
|
|
7
|
+
* records the executions, `checkInput` runs at the boundary, a failure comes
|
|
8
|
+
* back as an `isError` tool_result. That sameness is the point — MCP is a
|
|
9
|
+
* SOURCE of tools, not a second kind of tool.
|
|
10
|
+
*
|
|
11
|
+
* How it composes with the tier-2 registry (integrations.ts):
|
|
12
|
+
* - `register` — used, and it is the fail-fast the lead cares about: two
|
|
13
|
+
* servers exposing `search`, or a server tool colliding with a declared
|
|
14
|
+
* one, throws at connect instead of silently shadowing.
|
|
15
|
+
* - `buildToolDispatch` — used: the ONE place a manifest becomes a ToolDef
|
|
16
|
+
* (law 8's shared executor seam) stays the only place.
|
|
17
|
+
* - `resolveIntegrations` — deliberately NOT used. Its two jobs are
|
|
18
|
+
* persona-enablement intersection and dropping manifests whose env key is
|
|
19
|
+
* unprovisioned; an MCP server has neither a persona list nor an env key,
|
|
20
|
+
* and its `MAX_INTEGRATIONS` cap SILENTLY drops the overflow. A server
|
|
21
|
+
* exposing more tools than the cap is a real thing (the in-repo a2ui
|
|
22
|
+
* server has ~20), and quietly serving two thirds of them is the failure
|
|
23
|
+
* mode this whole feature is supposed to prevent. So the cap here is
|
|
24
|
+
* explicit and LOUD: `maxTools` (default `MAX_INTEGRATIONS`) throws when
|
|
25
|
+
* exceeded, and `tools` narrows the list on purpose.
|
|
26
|
+
*
|
|
27
|
+
* Schemas arrive as JSON Schema and are passed to the model VERBATIM. They
|
|
28
|
+
* are not trimmed to `checkInput`'s allowlist: the MCP server is the
|
|
29
|
+
* authoritative validator (its rejection comes back as an error result the
|
|
30
|
+
* model can read), so a faithful copy of a contract someone else owns beats
|
|
31
|
+
* a locally-enforceable subset that describes the tool less accurately. The
|
|
32
|
+
* manifest says so with `validation: 'remote'` rather than leaving it
|
|
33
|
+
* implied.
|
|
34
|
+
*
|
|
35
|
+
* RESOURCES map onto the two existing modes and no new one. `tool` is the
|
|
36
|
+
* default — the harness cannot know which of a remote server's resources an
|
|
37
|
+
* app wants in every prompt, and attaching all of them would grow the system
|
|
38
|
+
* prompt without bound — and `attach: [name|uri]` promotes the ones the APP
|
|
39
|
+
* decides belong there every turn. That is the whole application-controlled
|
|
40
|
+
* vs. model-controlled distinction MCP itself draws, expressed with the
|
|
41
|
+
* modes the harness already has. gh#671's third mode is NOT needed here; see
|
|
42
|
+
* the README's ruling.
|
|
43
|
+
*
|
|
44
|
+
* Everything a server returns — tool descriptions, resource text, error
|
|
45
|
+
* strings — is DATA. A description that reads like an instruction is still a
|
|
46
|
+
* description; it lands inside the tool spec or a `<resource>` envelope and
|
|
47
|
+
* decides nothing about what the harness does.
|
|
48
|
+
*/
|
|
49
|
+
import { buildToolDispatch, createIntegrationRegistry, MAX_INTEGRATIONS, } from './integrations.js';
|
|
50
|
+
import { defineResource } from './resource.js';
|
|
51
|
+
import { connectStreamableHttp, McpCallError, McpConnectionError, } from './mcp-transport.js';
|
|
52
|
+
/** Declare an MCP server as a source. Pure — no connection happens here, so
|
|
53
|
+
* this is safe to call at module scope; the agent connects on first use (or
|
|
54
|
+
* eagerly via `agent.connect()`). */
|
|
55
|
+
export function mcpServer(options) {
|
|
56
|
+
if (!options?.url)
|
|
57
|
+
throw new Error('mcpServer: url is required');
|
|
58
|
+
return { kind: 'mcp', url: options.url, options };
|
|
59
|
+
}
|
|
60
|
+
function sanitize(name) {
|
|
61
|
+
return name.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
62
|
+
}
|
|
63
|
+
/** Pull every page of a cursor-paginated list method. The page bound is a
|
|
64
|
+
* guard against a server that keeps handing back a cursor, not a limit on
|
|
65
|
+
* legitimate size. */
|
|
66
|
+
async function listAll(connection, method, key, signal) {
|
|
67
|
+
const items = [];
|
|
68
|
+
let cursor;
|
|
69
|
+
for (let page = 0; page < 50; page++) {
|
|
70
|
+
const result = await connection.request(method, cursor ? { cursor } : {}, signal ? { signal } : undefined);
|
|
71
|
+
const batch = result?.[key];
|
|
72
|
+
if (Array.isArray(batch))
|
|
73
|
+
items.push(...batch);
|
|
74
|
+
const next = result?.['nextCursor'];
|
|
75
|
+
if (typeof next !== 'string' || !next)
|
|
76
|
+
return items;
|
|
77
|
+
cursor = next;
|
|
78
|
+
}
|
|
79
|
+
throw new McpConnectionError(`${method} paginated past 50 pages`, connection.url);
|
|
80
|
+
}
|
|
81
|
+
/** MCP content blocks → the one string a tool_result carries. Non-text
|
|
82
|
+
* blocks are named rather than dropped: a model told "[image/png, 4.2 kB
|
|
83
|
+
* omitted]" can ask for something else; a model handed silence cannot. */
|
|
84
|
+
function contentToText(blocks) {
|
|
85
|
+
if (!Array.isArray(blocks))
|
|
86
|
+
return typeof blocks === 'string' ? blocks : JSON.stringify(blocks ?? null);
|
|
87
|
+
return blocks
|
|
88
|
+
.map((raw) => {
|
|
89
|
+
const block = (raw ?? {});
|
|
90
|
+
if (typeof block.text === 'string')
|
|
91
|
+
return block.text;
|
|
92
|
+
if (typeof block.blob === 'string') {
|
|
93
|
+
return `[${block.mimeType ?? 'binary'}, ${block.blob.length} base64 chars omitted]`;
|
|
94
|
+
}
|
|
95
|
+
return JSON.stringify(block);
|
|
96
|
+
})
|
|
97
|
+
.join('\n');
|
|
98
|
+
}
|
|
99
|
+
function toolManifest(connection, listing, prefix) {
|
|
100
|
+
const wireName = sanitize(`${prefix}${listing.name}`);
|
|
101
|
+
return {
|
|
102
|
+
id: `mcp:${connection.url}:${listing.name}`,
|
|
103
|
+
tool: {
|
|
104
|
+
name: wireName,
|
|
105
|
+
...(listing.description ? { description: listing.description } : {}),
|
|
106
|
+
inputSchema: listing.inputSchema ?? { type: 'object', properties: {} },
|
|
107
|
+
},
|
|
108
|
+
label: listing.title ?? listing.name,
|
|
109
|
+
validation: 'remote',
|
|
110
|
+
auth: { kind: 'none' },
|
|
111
|
+
execute: async (input, ctx) => {
|
|
112
|
+
// The turn's signal reaches the wire: a user who aborts mid-answer
|
|
113
|
+
// cancels the server call instead of leaving it running and ignored.
|
|
114
|
+
const result = await connection.request('tools/call', { name: listing.name, arguments: input }, ctx?.signal ? { signal: ctx.signal } : undefined);
|
|
115
|
+
const text = contentToText(result?.content);
|
|
116
|
+
// A tool the SERVER rejected must reach the model as an error, not as
|
|
117
|
+
// prose that reads like a successful answer. `executeTool` turns a
|
|
118
|
+
// throw into an isError tool_result, so throwing is how a ToolDef says
|
|
119
|
+
// "this failed" without a second return shape.
|
|
120
|
+
if (result?.isError)
|
|
121
|
+
throw new McpCallError(text || 'tool reported an error', connection.url);
|
|
122
|
+
if (text)
|
|
123
|
+
return text;
|
|
124
|
+
return result?.structuredContent ?? '';
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function resourceDef(connection, listing, prefix, mode) {
|
|
129
|
+
const name = sanitize(`${prefix}${listing.name ?? listing.uri}`);
|
|
130
|
+
return defineResource({
|
|
131
|
+
name,
|
|
132
|
+
description: listing.description ?? `MCP resource ${listing.uri}`,
|
|
133
|
+
mode,
|
|
134
|
+
get: async (_input, ctx) => {
|
|
135
|
+
const result = await connection.request('resources/read', { uri: listing.uri }, ctx?.signal ? { signal: ctx.signal } : undefined);
|
|
136
|
+
return contentToText(result?.contents);
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/** Connect one declared source: handshake, list, register, build. Any
|
|
141
|
+
* failure along the way throws `McpConnectionError` — including a failure
|
|
142
|
+
* the REGISTRY raises, which is a plain Error about a manifest and would
|
|
143
|
+
* otherwise escape as a different error class than the one the failure
|
|
144
|
+
* table promises. The caller never receives a half-built source or an empty
|
|
145
|
+
* tool list that looks like a server with nothing to offer.
|
|
146
|
+
*
|
|
147
|
+
* `signal` cancels the connect in flight (the turn that triggered it was
|
|
148
|
+
* aborted); it does NOT stay attached to the resulting connection, whose
|
|
149
|
+
* later calls carry their own turn's signal. */
|
|
150
|
+
export async function connectMcpSource(source, opts = {}) {
|
|
151
|
+
const options = source.options;
|
|
152
|
+
const signal = opts.signal;
|
|
153
|
+
const connection = await connectStreamableHttp(options, signal ? { signal } : {});
|
|
154
|
+
try {
|
|
155
|
+
return await describeSource(source, connection, signal);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
// The handshake succeeded and something after it did not: the session on
|
|
159
|
+
// the server is ours and nobody else holds a reference to it, so it gets
|
|
160
|
+
// closed here rather than left to a timeout.
|
|
161
|
+
await connection.close().catch(() => { });
|
|
162
|
+
throw err;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function describeSource(source, connection, signal) {
|
|
166
|
+
const options = source.options;
|
|
167
|
+
const prefix = options.prefix ?? '';
|
|
168
|
+
let listings;
|
|
169
|
+
try {
|
|
170
|
+
listings = await listAll(connection, 'tools/list', 'tools', signal);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
throw new McpConnectionError(`tools/list failed: ${err.message}`, source.url, { cause: err });
|
|
174
|
+
}
|
|
175
|
+
const allow = options.tools ? new Set(options.tools) : null;
|
|
176
|
+
const selected = allow ? listings.filter(t => allow.has(t.name)) : listings;
|
|
177
|
+
if (allow) {
|
|
178
|
+
const missing = [...allow].filter(name => !listings.some(t => t.name === name));
|
|
179
|
+
if (missing.length) {
|
|
180
|
+
throw new McpConnectionError(`requested tool(s) ${missing.join(', ')} are not exposed by this server ` +
|
|
181
|
+
`(it lists: ${listings.map(t => t.name).join(', ') || 'nothing'})`, source.url);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const maxTools = options.maxTools ?? MAX_INTEGRATIONS;
|
|
185
|
+
if (selected.length > maxTools) {
|
|
186
|
+
throw new McpConnectionError(`server exposes ${selected.length} tools, over the ${maxTools} cap — ` +
|
|
187
|
+
'raise maxTools or narrow the list with tools: [...]', source.url);
|
|
188
|
+
}
|
|
189
|
+
// Registration and ToolDef construction raise plain Errors about a
|
|
190
|
+
// manifest — a duplicate wire name after sanitizing, an empty name, an
|
|
191
|
+
// inputSchema that is not an object. They are connect-time faults like any
|
|
192
|
+
// other, so they wear the connect-time class (cause preserved) instead of
|
|
193
|
+
// escaping as something a caller catching McpConnectionError would miss.
|
|
194
|
+
let toolDefs;
|
|
195
|
+
try {
|
|
196
|
+
const registry = createIntegrationRegistry();
|
|
197
|
+
for (const listing of selected)
|
|
198
|
+
registry.register(toolManifest(connection, listing, prefix));
|
|
199
|
+
const dispatch = buildToolDispatch(registry.list(), {});
|
|
200
|
+
toolDefs = 'tools' in dispatch ? dispatch.tools : [];
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
if (err instanceof McpConnectionError)
|
|
204
|
+
throw err;
|
|
205
|
+
throw new McpConnectionError(`cannot register this server's tools: ${err.message}`, source.url, { cause: err });
|
|
206
|
+
}
|
|
207
|
+
let resourceDefs = [];
|
|
208
|
+
let resourceReport = [];
|
|
209
|
+
const serverDoesResources = !!connection.capabilities['resources'];
|
|
210
|
+
if (options.resources !== false && serverDoesResources) {
|
|
211
|
+
let resourceListings;
|
|
212
|
+
try {
|
|
213
|
+
resourceListings = await listAll(connection, 'resources/list', 'resources', signal);
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
throw new McpConnectionError(`resources/list failed: ${err.message}`, source.url, { cause: err });
|
|
217
|
+
}
|
|
218
|
+
const attachSet = new Set(options.attach ?? []);
|
|
219
|
+
const unknownAttach = [...attachSet].filter(key => !resourceListings.some(r => r.name === key || r.uri === key));
|
|
220
|
+
if (unknownAttach.length) {
|
|
221
|
+
throw new McpConnectionError(`attach names ${unknownAttach.join(', ')} match no listed resource ` +
|
|
222
|
+
`(it lists: ${resourceListings.map(r => r.name ?? r.uri).join(', ') || 'nothing'})`, source.url);
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
resourceDefs = resourceListings.map((listing) => {
|
|
226
|
+
const mode = attachSet.has(listing.name ?? '') || attachSet.has(listing.uri) ? 'attach' : 'tool';
|
|
227
|
+
return resourceDef(connection, listing, prefix, mode);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
throw new McpConnectionError(`cannot register this server's resources: ${err.message}`, source.url, { cause: err });
|
|
232
|
+
}
|
|
233
|
+
resourceReport = resourceListings.map((listing, index) => ({
|
|
234
|
+
name: resourceDefs[index].name,
|
|
235
|
+
uri: listing.uri,
|
|
236
|
+
mode: resourceDefs[index].mode,
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
url: source.url,
|
|
241
|
+
serverInfo: connection.serverInfo,
|
|
242
|
+
protocolVersion: connection.protocolVersion,
|
|
243
|
+
tools: toolDefs.map(t => t.name),
|
|
244
|
+
resources: resourceReport,
|
|
245
|
+
connection,
|
|
246
|
+
toolDefs,
|
|
247
|
+
resourceDefs,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/** The whole assembled tool set must have unique names — the loop dispatches
|
|
251
|
+
* by name, so a duplicate is a tool that silently never runs. Per-server
|
|
252
|
+
* registration cannot see across sources or into the declared tools, so the
|
|
253
|
+
* check lands here, once, over everything. */
|
|
254
|
+
export function assertUniqueToolNames(tools) {
|
|
255
|
+
const seen = new Set();
|
|
256
|
+
for (const tool of tools) {
|
|
257
|
+
if (seen.has(tool.name)) {
|
|
258
|
+
throw new McpConnectionError(`tool name "${tool.name}" is contributed twice (an MCP server collides with a declared tool ` +
|
|
259
|
+
'or another server) — set a prefix on one of the sources');
|
|
260
|
+
}
|
|
261
|
+
seen.add(tool.name);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=mcp.js.map
|
package/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["src/mcp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/agent",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.31",
|
|
4
4
|
"description": "Composable chat-agent harness — assemble an agent from four declared parts (prompt layers, tools, workflows, resources) on top of @adia-ai/llm. Owns the tool-call loop, the session model, and the one shared event reducer. Works in browser and Node.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
package/resource.d.ts
CHANGED
|
@@ -8,20 +8,45 @@
|
|
|
8
8
|
* never asks; the data is just there.
|
|
9
9
|
* - 'tool' — model-controlled: the resource becomes a read-only tool
|
|
10
10
|
* (`read_<name>`) the model calls when it decides it needs the data.
|
|
11
|
+
*
|
|
12
|
+
* Attach mode inlines somebody else's bytes into the system prompt, so the
|
|
13
|
+
* envelope has to be forgeable-proof: see `attachLayers` for the escaping
|
|
14
|
+
* and why it is not optional.
|
|
11
15
|
*/
|
|
12
16
|
import type { PromptLayer } from './prompt.js';
|
|
13
17
|
import { type ToolDef } from './tools.js';
|
|
18
|
+
/** What a `get` may USE — the turn's cancellation, today. Passed as the
|
|
19
|
+
* SECOND argument, so every existing one-argument `get` is unaffected. */
|
|
20
|
+
export interface ResourceContext {
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
}
|
|
14
23
|
export interface ResourceDef {
|
|
15
24
|
name: string;
|
|
16
25
|
description?: string;
|
|
17
26
|
mode: 'attach' | 'tool';
|
|
18
|
-
|
|
27
|
+
/** Tool-mode only: the arguments the model may pass. Without it a
|
|
28
|
+
* tool-mode resource is a zero-argument read, which can't express a
|
|
29
|
+
* parameterized corpus read (`search_chunks(query, kind, limit)`).
|
|
30
|
+
* Attach-mode resources take no input and ignore this. */
|
|
31
|
+
inputSchema?: Record<string, unknown>;
|
|
32
|
+
/** Non-string returns are JSON-serialized — a corpus record is an object,
|
|
33
|
+
* and making every call site stringify was the same tax the tool
|
|
34
|
+
* executor already pays for `execute`. */
|
|
35
|
+
get: (input?: Record<string, unknown>, ctx?: ResourceContext) => unknown | Promise<unknown>;
|
|
19
36
|
}
|
|
20
37
|
export declare function defineResource(def: ResourceDef): ResourceDef;
|
|
21
38
|
/** Attach-mode resources → dynamic prompt layers. Resolution happens at
|
|
22
39
|
* compose time (async), so the layer text is a plain string by the time
|
|
23
|
-
* it reaches composeSystem.
|
|
24
|
-
|
|
40
|
+
* it reaches composeSystem.
|
|
41
|
+
*
|
|
42
|
+
* The content is DATA, and the envelope is what says so. A resource body
|
|
43
|
+
* that contains `</resource>` would otherwise close its own envelope and
|
|
44
|
+
* everything after it would read as prompt — a server, a file, or a
|
|
45
|
+
* database row could then write instructions into the system prompt. That
|
|
46
|
+
* is a containment bug in the harness, not a hazard the resource's author
|
|
47
|
+
* is responsible for, so the escaping lives here and covers EVERY attach
|
|
48
|
+
* resource, MCP or hand-declared. */
|
|
49
|
+
export declare function attachLayers(resources: ResourceDef[], ctx?: ResourceContext): Promise<PromptLayer[]>;
|
|
25
50
|
/** Tool-mode resources → read-only tools the model can call. */
|
|
26
51
|
export declare function resourceTools(resources: ResourceDef[]): ToolDef[];
|
|
27
52
|
//# sourceMappingURL=resource.d.ts.map
|
package/resource.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["src/resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["src/resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAEtD;2EAC2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB;;;+DAG2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;;+CAE2C;IAC3C,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7F;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAY5D;AA0BD;;;;;;;;;;sCAUsC;AACtC,wBAAsB,YAAY,CAChC,SAAS,EAAE,WAAW,EAAE,EACxB,GAAG,CAAC,EAAE,eAAe,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC,CASxB;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CASjE"}
|
package/resource.js
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* never asks; the data is just there.
|
|
9
9
|
* - 'tool' — model-controlled: the resource becomes a read-only tool
|
|
10
10
|
* (`read_<name>`) the model calls when it decides it needs the data.
|
|
11
|
+
*
|
|
12
|
+
* Attach mode inlines somebody else's bytes into the system prompt, so the
|
|
13
|
+
* envelope has to be forgeable-proof: see `attachLayers` for the escaping
|
|
14
|
+
* and why it is not optional.
|
|
11
15
|
*/
|
|
12
16
|
import { defineTool } from './tools.js';
|
|
13
17
|
export function defineResource(def) {
|
|
@@ -19,16 +23,50 @@ export function defineResource(def) {
|
|
|
19
23
|
if (typeof def.get !== 'function') {
|
|
20
24
|
throw new Error(`defineResource "${def.name}": get() is required`);
|
|
21
25
|
}
|
|
26
|
+
if (def.inputSchema && def.mode !== 'tool') {
|
|
27
|
+
throw new Error(`defineResource "${def.name}": inputSchema is tool-mode only`);
|
|
28
|
+
}
|
|
22
29
|
return def;
|
|
23
30
|
}
|
|
31
|
+
function asText(value) {
|
|
32
|
+
return typeof value === 'string' ? value : JSON.stringify(value ?? null);
|
|
33
|
+
}
|
|
34
|
+
/** Attribute values: a `"` would end the attribute early and let the rest of
|
|
35
|
+
* a name or description pose as further attributes. */
|
|
36
|
+
function escapeAttribute(value) {
|
|
37
|
+
return value.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"');
|
|
38
|
+
}
|
|
39
|
+
/** Bodies get the narrowest escape that still makes the envelope
|
|
40
|
+
* unforgeable: only the two STRUCTURAL sequences — an opening `<resource`
|
|
41
|
+
* and a closing `</resource` — have their `<` escaped.
|
|
42
|
+
*
|
|
43
|
+
* Escaping every `<` was the alternative and it is worse: attached bodies
|
|
44
|
+
* here are catalog JSON, component markup, docs. Mangling every tag in them
|
|
45
|
+
* to close one hole degrades the data the model reads on every turn, for a
|
|
46
|
+
* containment property those two sequences already give. A body can no
|
|
47
|
+
* longer end its own envelope or open a nested one that claims a different
|
|
48
|
+
* name; everything else it contains arrives byte-for-byte. */
|
|
49
|
+
function fenceBody(text) {
|
|
50
|
+
return text.replace(/<(\/?resource\b)/gi, '<$1');
|
|
51
|
+
}
|
|
24
52
|
/** Attach-mode resources → dynamic prompt layers. Resolution happens at
|
|
25
53
|
* compose time (async), so the layer text is a plain string by the time
|
|
26
|
-
* it reaches composeSystem.
|
|
27
|
-
|
|
54
|
+
* it reaches composeSystem.
|
|
55
|
+
*
|
|
56
|
+
* The content is DATA, and the envelope is what says so. A resource body
|
|
57
|
+
* that contains `</resource>` would otherwise close its own envelope and
|
|
58
|
+
* everything after it would read as prompt — a server, a file, or a
|
|
59
|
+
* database row could then write instructions into the system prompt. That
|
|
60
|
+
* is a containment bug in the harness, not a hazard the resource's author
|
|
61
|
+
* is responsible for, so the escaping lives here and covers EVERY attach
|
|
62
|
+
* resource, MCP or hand-declared. */
|
|
63
|
+
export async function attachLayers(resources, ctx) {
|
|
28
64
|
const attach = resources.filter(r => r.mode === 'attach');
|
|
29
65
|
const resolved = await Promise.all(attach.map(async (r) => ({
|
|
30
66
|
name: `resource:${r.name}`,
|
|
31
|
-
text: `<resource name="${r.name}"
|
|
67
|
+
text: `<resource name="${escapeAttribute(r.name)}"` +
|
|
68
|
+
`${r.description ? ` description="${escapeAttribute(r.description)}"` : ''}>\n` +
|
|
69
|
+
`${fenceBody(asText(await r.get(undefined, ctx)))}\n</resource>`,
|
|
32
70
|
})));
|
|
33
71
|
return resolved.filter(l => l.text);
|
|
34
72
|
}
|
|
@@ -39,8 +77,8 @@ export function resourceTools(resources) {
|
|
|
39
77
|
.map(r => defineTool({
|
|
40
78
|
name: `read_${r.name.replace(/[^a-zA-Z0-9_-]/g, '_')}`,
|
|
41
79
|
description: r.description ?? `Read the "${r.name}" resource`,
|
|
42
|
-
inputSchema: { type: 'object', properties: {} },
|
|
43
|
-
execute: (input) => r.get(input),
|
|
80
|
+
inputSchema: r.inputSchema ?? { type: 'object', properties: {} },
|
|
81
|
+
execute: (input, toolCtx) => r.get(input, toolCtx.signal ? { signal: toolCtx.signal } : {}),
|
|
44
82
|
}));
|
|
45
83
|
}
|
|
46
84
|
//# sourceMappingURL=resource.js.map
|
package/resource.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.js","sourceRoot":"","sources":["src/resource.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"resource.js","sourceRoot":"","sources":["src/resource.ts"],"names":[],"mappings":"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"}
|
package/session.d.ts
CHANGED
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
* `draft` is reduce()'s in-flight assistant turn (text snapshot + parts
|
|
10
10
|
* accumulated between a round's first chunk and its close). It is part of
|
|
11
11
|
* the serialized shape on purpose — resuming mid-turn drops nothing.
|
|
12
|
+
*
|
|
13
|
+
* `memory` is the per-session key/value slot (gh#665). It is JSON-safe by
|
|
14
|
+
* contract and written ONLY through `reduce()` — same single-writer rule
|
|
15
|
+
* the messages obey, so a memory write is an event in the same stream and
|
|
16
|
+
* cannot happen behind a consumer's back. Cross-session persistence is a
|
|
17
|
+
* SEAM, not an implementation: a Session serializes with its memory, and
|
|
18
|
+
* where that JSON goes (localStorage, a DB row) stays the caller's.
|
|
12
19
|
*/
|
|
13
20
|
import type { Part } from '@adia-ai/llm';
|
|
14
21
|
export interface Msg {
|
|
@@ -19,11 +26,22 @@ export interface Draft {
|
|
|
19
26
|
text: string;
|
|
20
27
|
parts: Part[];
|
|
21
28
|
}
|
|
29
|
+
/** The values a memory slot may hold — the JSON-safe closure. */
|
|
30
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
31
|
+
[key: string]: JsonValue;
|
|
32
|
+
};
|
|
22
33
|
export interface Session {
|
|
23
34
|
id: string;
|
|
24
35
|
messages: Msg[];
|
|
25
36
|
draft?: Draft;
|
|
37
|
+
/** Per-session memory. Present only once something has been remembered. */
|
|
38
|
+
memory?: Record<string, JsonValue>;
|
|
26
39
|
}
|
|
40
|
+
/** Throws on anything a Session could not survive `JSON.stringify` →
|
|
41
|
+
* `JSON.parse` unchanged (functions, undefined, Date, Map, cycles). Loud
|
|
42
|
+
* at the write, because the alternative is a session that silently loses
|
|
43
|
+
* a field the next time it round-trips through storage. */
|
|
44
|
+
export declare function assertJsonSafe(value: unknown, path?: string): void;
|
|
27
45
|
export declare function createSession(id?: string): Session;
|
|
28
46
|
export declare function toJSON(session: Session): string;
|
|
29
47
|
export declare function fromJSON(json: string): Session;
|
package/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["src/session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,iEAAiE;AACjE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEtG,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,GAAG,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACpC;AAED;;;4DAG4D;AAC5D,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAW,GAAG,IAAI,CA2BpE;AAID,wBAAgB,aAAa,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAKlD;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE/C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM9C"}
|
package/session.js
CHANGED
|
@@ -9,7 +9,47 @@
|
|
|
9
9
|
* `draft` is reduce()'s in-flight assistant turn (text snapshot + parts
|
|
10
10
|
* accumulated between a round's first chunk and its close). It is part of
|
|
11
11
|
* the serialized shape on purpose — resuming mid-turn drops nothing.
|
|
12
|
+
*
|
|
13
|
+
* `memory` is the per-session key/value slot (gh#665). It is JSON-safe by
|
|
14
|
+
* contract and written ONLY through `reduce()` — same single-writer rule
|
|
15
|
+
* the messages obey, so a memory write is an event in the same stream and
|
|
16
|
+
* cannot happen behind a consumer's back. Cross-session persistence is a
|
|
17
|
+
* SEAM, not an implementation: a Session serializes with its memory, and
|
|
18
|
+
* where that JSON goes (localStorage, a DB row) stays the caller's.
|
|
12
19
|
*/
|
|
20
|
+
/** Throws on anything a Session could not survive `JSON.stringify` →
|
|
21
|
+
* `JSON.parse` unchanged (functions, undefined, Date, Map, cycles). Loud
|
|
22
|
+
* at the write, because the alternative is a session that silently loses
|
|
23
|
+
* a field the next time it round-trips through storage. */
|
|
24
|
+
export function assertJsonSafe(value, path = 'memory') {
|
|
25
|
+
if (value === null)
|
|
26
|
+
return;
|
|
27
|
+
switch (typeof value) {
|
|
28
|
+
case 'string':
|
|
29
|
+
case 'number':
|
|
30
|
+
case 'boolean':
|
|
31
|
+
if (typeof value === 'number' && !Number.isFinite(value)) {
|
|
32
|
+
throw new Error(`${path}: ${value} is not JSON-safe`);
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
case 'object': {
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
value.forEach((item, i) => assertJsonSafe(item, `${path}[${i}]`));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const proto = Object.getPrototypeOf(value);
|
|
41
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
42
|
+
throw new Error(`${path}: ${value.constructor?.name ?? 'object'} is not JSON-safe (plain objects only)`);
|
|
43
|
+
}
|
|
44
|
+
for (const [key, item] of Object.entries(value)) {
|
|
45
|
+
assertJsonSafe(item, `${path}.${key}`);
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
default:
|
|
50
|
+
throw new Error(`${path}: ${typeof value} is not JSON-safe`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
13
53
|
let sessionCounter = 0;
|
|
14
54
|
export function createSession(id) {
|
|
15
55
|
return {
|
package/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["src/session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAyBH;;;4DAG4D;AAC5D,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,IAAI,GAAG,QAAQ;IAC5D,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS;YACZ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,KAAK,mBAAmB,CAAC,CAAC;YACxD,CAAC;YACD,OAAO;QACT,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClE,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,KAAM,KAAgB,CAAC,WAAW,EAAE,IAAI,IAAI,QAAQ,wCAAwC,CAAC,CAAC;YACvH,CAAC;YACD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;gBAC3E,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,OAAO;QACT,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,KAAK,mBAAmB,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,IAAI,cAAc,GAAG,CAAC,CAAC;AAEvB,MAAM,UAAU,aAAa,CAAC,EAAW;IACvC,OAAO;QACL,EAAE,EAAE,EAAE,IAAI,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE;QAC5D,QAAQ,EAAE,EAAE;KACb,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAgB;IACrC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IAC3C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChF,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/stub.d.ts
CHANGED
|
@@ -11,6 +11,14 @@ import type { ChatOpts, LLMClient, ToolUse } from '@adia-ai/llm';
|
|
|
11
11
|
export interface ScriptedTurn {
|
|
12
12
|
text?: string;
|
|
13
13
|
toolUse?: ToolUse[];
|
|
14
|
+
/** Argument fragments streamed BEFORE the complete `toolUse` chunks, the
|
|
15
|
+
* way Anthropic/OpenAI stream partial tool input. Scripted explicitly:
|
|
16
|
+
* a stub that invented its own split would be testing the stub. */
|
|
17
|
+
toolUseDeltas?: Array<{
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
partial: string;
|
|
21
|
+
}>;
|
|
14
22
|
stopReason?: string;
|
|
15
23
|
}
|
|
16
24
|
export interface ScriptClient extends LLMClient {
|
package/stub.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["src/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAc,SAAS,EAAe,OAAO,EAAE,MAAM,cAAc,CAAC;AAE1F,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C;mDAC+C;IAC/C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;CACjC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["src/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAc,SAAS,EAAe,OAAO,EAAE,MAAM,cAAc,CAAC;AAE1F,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB;;wEAEoE;IACpE,aAAa,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C;mDAC+C;IAC/C,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;CACjC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,CAuDhE"}
|
package/stub.js
CHANGED
|
@@ -37,6 +37,19 @@ export function scriptClient(turns) {
|
|
|
37
37
|
snapshot = turn.text;
|
|
38
38
|
yield { type: 'text', text: turn.text, snapshot };
|
|
39
39
|
}
|
|
40
|
+
const snapshots = new Map();
|
|
41
|
+
for (const delta of turn.toolUseDeltas ?? []) {
|
|
42
|
+
const accumulated = (snapshots.get(delta.id) ?? '') + delta.partial;
|
|
43
|
+
snapshots.set(delta.id, accumulated);
|
|
44
|
+
yield {
|
|
45
|
+
type: 'tool_use_delta',
|
|
46
|
+
id: delta.id,
|
|
47
|
+
name: delta.name,
|
|
48
|
+
index: 0,
|
|
49
|
+
partial: delta.partial,
|
|
50
|
+
snapshot: accumulated,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
40
53
|
for (const call of turn.toolUse ?? []) {
|
|
41
54
|
yield { type: 'tool_use', id: call.id, name: call.name, input: call.input };
|
|
42
55
|
}
|
package/stub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.js","sourceRoot":"","sources":["src/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["src/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH,MAAM,UAAU,YAAY,CAAC,KAAqB;IAChD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,KAAK,GAA6B,EAAE,CAAC;IAE3C,SAAS,IAAI;QACX,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,GAAG,CAAC,aAAa,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QACvG,MAAM,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,KAAK;QACL,KAAK,CAAC,IAAI,CAAC,IAAuB;YAChC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC;YACpB,OAAO;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;gBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;gBAC1E,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAuB;YACnC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC;YACpB,IAAI,QAAQ,GAAG,EAAE,CAAC;YAClB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;gBACrB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;YACpD,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC5C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;gBAC7C,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;gBACpE,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;gBACrC,MAAM;oBACJ,IAAI,EAAE,gBAAgB;oBACtB,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,QAAQ,EAAE,WAAW;iBACtB,CAAC;YACJ,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBACtC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9E,CAAC;YACD,MAAM;gBACJ,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;gBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC;aAC3E,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/tools.d.ts
CHANGED
|
@@ -12,9 +12,15 @@
|
|
|
12
12
|
* can validate inside their own `execute`.
|
|
13
13
|
*/
|
|
14
14
|
import type { ToolSpec } from '@adia-ai/llm';
|
|
15
|
+
import type { JsonValue } from './session.js';
|
|
15
16
|
export interface ToolContext {
|
|
16
17
|
sessionId: string;
|
|
17
18
|
signal?: AbortSignal;
|
|
19
|
+
/** Ask for a session-memory write. This does NOT write: the loop turns
|
|
20
|
+
* the patch into a `memory` event, and `reduce()` remains the only
|
|
21
|
+
* writer. Absent when a tool runs outside the loop (a direct
|
|
22
|
+
* `executeTool` call). A null value deletes the key. */
|
|
23
|
+
remember?: (patch: Record<string, JsonValue | null>) => void;
|
|
18
24
|
}
|
|
19
25
|
export interface ToolDef {
|
|
20
26
|
name: string;
|
package/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;6DAGyD;IACzD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3F,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;CAC/E;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAWhD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAMpD;AAED;gDACgD;AAChD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAmBzG;AAeD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;oEAEoE;AACpE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,WAAW,CAAC,CA4BtB"}
|