@rarebit-one/harness-kernel 0.18.0 → 0.19.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 +255 -16
- package/dist/agent.d.ts +24 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +138 -30
- package/dist/agent.js.map +1 -1
- package/dist/connectors/auth.d.ts +32 -0
- package/dist/connectors/auth.d.ts.map +1 -0
- package/dist/connectors/auth.js +85 -0
- package/dist/connectors/auth.js.map +1 -0
- package/dist/connectors/mcpClient.d.ts +14 -4
- package/dist/connectors/mcpClient.d.ts.map +1 -1
- package/dist/connectors/mcpClient.js +32 -11
- package/dist/connectors/mcpClient.js.map +1 -1
- package/dist/engines/acp.d.ts.map +1 -1
- package/dist/engines/acp.js +2 -1
- package/dist/engines/acp.js.map +1 -1
- package/dist/engines/capability.d.ts +1 -1
- package/dist/engines/capability.js +1 -1
- package/dist/engines/claudeCode.d.ts.map +1 -1
- package/dist/engines/claudeCode.js +2 -1
- package/dist/engines/claudeCode.js.map +1 -1
- package/dist/engines/claudeCodeDriver.d.ts.map +1 -1
- package/dist/engines/claudeCodeDriver.js +4 -3
- package/dist/engines/claudeCodeDriver.js.map +1 -1
- package/dist/engines/codex.d.ts +4 -4
- package/dist/engines/codex.d.ts.map +1 -1
- package/dist/engines/codex.js +6 -5
- package/dist/engines/codex.js.map +1 -1
- package/dist/engines/codexDriver.d.ts +1 -1
- package/dist/engines/codexDriver.js +1 -1
- package/dist/engines/connectorMcp.d.ts +13 -0
- package/dist/engines/connectorMcp.d.ts.map +1 -1
- package/dist/engines/connectorMcp.js +23 -0
- package/dist/engines/connectorMcp.js.map +1 -1
- package/dist/engines/gateway.d.ts +5 -2
- package/dist/engines/gateway.d.ts.map +1 -1
- package/dist/engines/gateway.js +7 -2
- package/dist/engines/gateway.js.map +1 -1
- package/dist/engines/native.d.ts.map +1 -1
- package/dist/engines/native.js +10 -3
- package/dist/engines/native.js.map +1 -1
- package/dist/engines/types.d.ts +10 -1
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/events.d.ts +22 -8
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/loop.d.ts +23 -0
- package/dist/loop.d.ts.map +1 -1
- package/dist/loop.js +1 -0
- package/dist/loop.js.map +1 -1
- package/dist/models/chat.d.ts +12 -6
- package/dist/models/chat.d.ts.map +1 -1
- package/dist/models/chat.js +11 -6
- package/dist/models/chat.js.map +1 -1
- package/dist/models/retry.d.ts +252 -0
- package/dist/models/retry.d.ts.map +1 -0
- package/dist/models/retry.js +400 -0
- package/dist/models/retry.js.map +1 -0
- package/dist/models/types.d.ts +7 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js.map +1 -1
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +12 -2
- package/dist/private.js.map +1 -1
- package/dist/secrets.d.ts +17 -7
- package/dist/secrets.d.ts.map +1 -1
- package/dist/secrets.js +38 -24
- package/dist/secrets.js.map +1 -1
- package/dist/tools/concurrency.d.ts +48 -0
- package/dist/tools/concurrency.d.ts.map +1 -0
- package/dist/tools/concurrency.js +64 -0
- package/dist/tools/concurrency.js.map +1 -0
- package/dist/tools/metadata.d.ts +18 -3
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +7 -0
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/registry.d.ts +6 -4
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +5 -3
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/terminal.d.ts +8 -6
- package/dist/tools/terminal.d.ts.map +1 -1
- package/dist/tools/terminal.js +8 -6
- package/dist/tools/terminal.js.map +1 -1
- package/dist/tools/validate.d.ts +49 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +346 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/transcript.d.ts +53 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +104 -0
- package/dist/transcript.js.map +1 -0
- package/dist/types.d.ts +44 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check a tool call's arguments against a JSON Schema, returning every problem
|
|
3
|
+
* found (empty when the arguments fit).
|
|
4
|
+
*
|
|
5
|
+
* This is the subset of JSON Schema that tool schemas actually use: `type`
|
|
6
|
+
* (including `integer`, `null` and type arrays), `properties`, `required`,
|
|
7
|
+
* `additionalProperties`, `enum`, `const`, `items` / `prefixItems`, the
|
|
8
|
+
* length, size and range bounds, `pattern`, `allOf` / `anyOf` / `oneOf`,
|
|
9
|
+
* local `$ref`s (`#/$defs/...`, `#/definitions/...`) and OpenAPI's
|
|
10
|
+
* `nullable`. A `$ref`'s sibling keywords apply as in 2019-09 and later, and
|
|
11
|
+
* are ignored when the root `$schema` names draft 03 to 07, where a `$ref`
|
|
12
|
+
* replaced its whole schema object; `const` is ignored before draft 6 and
|
|
13
|
+
* `prefixItems` before 2020-12, the drafts that introduced them. Any other keyword (`format`, `not`,
|
|
14
|
+
* `if`/`then`/`else`, `multipleOf`, `uniqueItems`, the `dependent*` family, a
|
|
15
|
+
* remote or malformed `$ref`, a local `$ref` inside an embedded resource with
|
|
16
|
+
* its own `$id`, a `type` name outside the seven JSON types) is ignored, and
|
|
17
|
+
* `oneOf` is read as `anyOf`. A schema whose check would take more than a
|
|
18
|
+
* fixed amount of work is not judged at all: no problems are returned.
|
|
19
|
+
*
|
|
20
|
+
* Ignoring is the point: the validator may let a bad call through, but it
|
|
21
|
+
* never refuses a call the schema accepts. A refusal costs the model a turn,
|
|
22
|
+
* so a false one is worse than a missed one, and a schema written by someone
|
|
23
|
+
* else (an MCP server's) can use any keyword it likes without the run
|
|
24
|
+
* starting to refuse calls its server would have taken.
|
|
25
|
+
*
|
|
26
|
+
* `pattern` is compiled and run synchronously on the model's input, like any
|
|
27
|
+
* regular expression. A schema author's pattern with catastrophic
|
|
28
|
+
* backtracking (`^(a+)+$`) can stall the event loop, and the run's deadline
|
|
29
|
+
* cannot interrupt it; turn validation on only for tools whose schemas you
|
|
30
|
+
* would run that way.
|
|
31
|
+
*/
|
|
32
|
+
export function validateToolInput(schema, input) {
|
|
33
|
+
const problems = [];
|
|
34
|
+
try {
|
|
35
|
+
check(schema, input, "", { root: schema, scoped: false, work: { left: MAX_WORK } }, 0, problems);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
// A schema too costly to judge is one the validator cannot judge.
|
|
39
|
+
if (err instanceof WorkExhausted)
|
|
40
|
+
return [];
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
return problems;
|
|
44
|
+
}
|
|
45
|
+
/** How many problems the model is told about; the rest are counted. */
|
|
46
|
+
const MAX_REPORTED = 10;
|
|
47
|
+
/**
|
|
48
|
+
* The tool result a call gets when its arguments fail the tool's schema, or
|
|
49
|
+
* `undefined` when they fit. The loop answers the call with this instead of
|
|
50
|
+
* running it, and the model corrects the call within its own budgets.
|
|
51
|
+
*/
|
|
52
|
+
export function invalidInputRefusal(tool, input) {
|
|
53
|
+
let problems;
|
|
54
|
+
try {
|
|
55
|
+
problems = validateToolInput(tool.spec.inputSchema, input);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// A schema the validator trips over is one it cannot judge: the call runs,
|
|
59
|
+
// as it would with validation off, rather than the run failing.
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (problems.length === 0)
|
|
63
|
+
return undefined;
|
|
64
|
+
const shown = problems
|
|
65
|
+
.slice(0, MAX_REPORTED)
|
|
66
|
+
.map((p) => `${p.path || "(arguments)"}: ${p.message}`);
|
|
67
|
+
const more = problems.length - shown.length;
|
|
68
|
+
return (`invalid arguments for ${tool.spec.name}; the call was not run. ` +
|
|
69
|
+
`Call it again with arguments that match its input schema: ${shown.join("; ")}` +
|
|
70
|
+
(more > 0 ? `; and ${more} more` : ""));
|
|
71
|
+
}
|
|
72
|
+
/** Deep enough for any real tool schema; a `$ref` cycle stops here instead of looping. */
|
|
73
|
+
const MAX_DEPTH = 32;
|
|
74
|
+
/**
|
|
75
|
+
* How many schema/value checks one validation may make. Shared definitions
|
|
76
|
+
* referenced from several composition branches can multiply the work
|
|
77
|
+
* exponentially without any cycle, and validation runs synchronously before
|
|
78
|
+
* the call, where no deadline can interrupt it; past this the validator gives
|
|
79
|
+
* up and the call runs unjudged.
|
|
80
|
+
*/
|
|
81
|
+
const MAX_WORK = 25_000;
|
|
82
|
+
class WorkExhausted extends Error {
|
|
83
|
+
}
|
|
84
|
+
const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
85
|
+
/** The JSON type of a parsed value, as JSON Schema names it. */
|
|
86
|
+
function jsonType(value) {
|
|
87
|
+
if (value === null)
|
|
88
|
+
return "null";
|
|
89
|
+
if (Array.isArray(value))
|
|
90
|
+
return "array";
|
|
91
|
+
if (typeof value === "number")
|
|
92
|
+
return Number.isInteger(value) ? "integer" : "number";
|
|
93
|
+
return typeof value;
|
|
94
|
+
}
|
|
95
|
+
const JSON_TYPES = new Set(["null", "boolean", "object", "array", "number", "integer", "string"]);
|
|
96
|
+
/**
|
|
97
|
+
* The draft the root schema declares in `$schema`: 3 to 7 for draft-03 to
|
|
98
|
+
* draft-07, 2019 for 2019-09, 2020 for 2020-12, or `undefined` when it names
|
|
99
|
+
* none (then every keyword the validator knows applies).
|
|
100
|
+
*/
|
|
101
|
+
function declaredDraft(root) {
|
|
102
|
+
const declared = isObject(root) ? root.$schema : undefined;
|
|
103
|
+
if (typeof declared !== "string")
|
|
104
|
+
return undefined;
|
|
105
|
+
const old = /draft-0([3-7])\b/.exec(declared);
|
|
106
|
+
if (old)
|
|
107
|
+
return Number(old[1]);
|
|
108
|
+
if (declared.includes("2019-09"))
|
|
109
|
+
return 2019;
|
|
110
|
+
if (declared.includes("2020-12"))
|
|
111
|
+
return 2020;
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
/** Whether the root schema declares a draft (03 to 07) in which `$ref` siblings are ignored. */
|
|
115
|
+
function refReplacesSiblings(root) {
|
|
116
|
+
const draft = declaredDraft(root);
|
|
117
|
+
return draft !== undefined && draft <= 7;
|
|
118
|
+
}
|
|
119
|
+
/** Whether a keyword introduced in `since` exists in the draft the root schema declares. */
|
|
120
|
+
function inDraft(root, since) {
|
|
121
|
+
const draft = declaredDraft(root);
|
|
122
|
+
return draft === undefined || draft >= since;
|
|
123
|
+
}
|
|
124
|
+
function typeMatches(expected, actual) {
|
|
125
|
+
return expected === actual || (expected === "number" && actual === "integer");
|
|
126
|
+
}
|
|
127
|
+
function deepEqual(a, b) {
|
|
128
|
+
if (a === b)
|
|
129
|
+
return true;
|
|
130
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
131
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
132
|
+
}
|
|
133
|
+
if (isObject(a) && isObject(b)) {
|
|
134
|
+
const keys = Object.keys(a);
|
|
135
|
+
return (keys.length === Object.keys(b).length &&
|
|
136
|
+
keys.every((k) => Object.hasOwn(b, k) && deepEqual(a[k], b[k])));
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
/** A pattern the validator can compile, or `undefined` for one it cannot (then the keyword is ignored). */
|
|
141
|
+
function compile(pattern) {
|
|
142
|
+
if (typeof pattern !== "string")
|
|
143
|
+
return undefined;
|
|
144
|
+
try {
|
|
145
|
+
return new RegExp(pattern, "u");
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
try {
|
|
149
|
+
return new RegExp(pattern);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Resolve a local `#/...` JSON Pointer against the root schema. */
|
|
157
|
+
function resolveRef(root, ref) {
|
|
158
|
+
if (!ref.startsWith("#"))
|
|
159
|
+
return undefined;
|
|
160
|
+
// The fragment is percent-decoded as a whole before it is read as a JSON
|
|
161
|
+
// Pointer (RFC 6901 §6), so an encoded `/` (`%2F`) separates tokens.
|
|
162
|
+
let fragment;
|
|
163
|
+
try {
|
|
164
|
+
fragment = decodeURIComponent(ref.slice(1));
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// A malformed escape (`%` not followed by two hex digits) names nothing.
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
if (fragment === "")
|
|
171
|
+
return root;
|
|
172
|
+
if (!fragment.startsWith("/"))
|
|
173
|
+
return undefined;
|
|
174
|
+
let node = root;
|
|
175
|
+
for (const raw of fragment.slice(1).split("/")) {
|
|
176
|
+
const key = raw.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
177
|
+
if (!isObject(node) && !Array.isArray(node))
|
|
178
|
+
return undefined;
|
|
179
|
+
node = node[key];
|
|
180
|
+
}
|
|
181
|
+
return node;
|
|
182
|
+
}
|
|
183
|
+
const pointer = (path, key) => `${path}/${String(key).replaceAll("~", "~0").replaceAll("/", "~1")}`;
|
|
184
|
+
const num = (v) => (typeof v === "number" ? v : undefined);
|
|
185
|
+
const quoted = (values) => {
|
|
186
|
+
const shown = values.slice(0, MAX_REPORTED).map((v) => JSON.stringify(v));
|
|
187
|
+
return values.length > shown.length ? `${shown.join(", ")}, …` : shown.join(", ");
|
|
188
|
+
};
|
|
189
|
+
function check(schema, value, path, outer, depth, problems) {
|
|
190
|
+
if (--outer.work.left < 0)
|
|
191
|
+
throw new WorkExhausted();
|
|
192
|
+
if (schema === false) {
|
|
193
|
+
problems.push({ path, message: "is not allowed" });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (!isObject(schema) || depth > MAX_DEPTH)
|
|
197
|
+
return;
|
|
198
|
+
const s = schema;
|
|
199
|
+
const env = !outer.scoped &&
|
|
200
|
+
schema !== outer.root &&
|
|
201
|
+
(typeof s.$id === "string" || typeof s.id === "string")
|
|
202
|
+
? { ...outer, scoped: true }
|
|
203
|
+
: outer;
|
|
204
|
+
const at = (message) => problems.push({ path, message });
|
|
205
|
+
// OpenAPI's `nullable` admits null whatever else the schema says, composition
|
|
206
|
+
// included (generators emit `{ allOf: [{ $ref }], nullable: true }`).
|
|
207
|
+
if (s.nullable === true && value === null)
|
|
208
|
+
return;
|
|
209
|
+
if (typeof s.$ref === "string") {
|
|
210
|
+
// Inside an embedded resource a local `$ref` means that resource, which
|
|
211
|
+
// this validator does not track, so it is ignored rather than misread.
|
|
212
|
+
const target = env.scoped ? undefined : resolveRef(env.root, s.$ref);
|
|
213
|
+
if (target !== undefined)
|
|
214
|
+
check(target, value, path, env, depth + 1, problems);
|
|
215
|
+
// Before 2019-09 a `$ref` replaced its whole schema object: the keywords
|
|
216
|
+
// beside it are ignored, so they are ignored here too.
|
|
217
|
+
if (refReplacesSiblings(env.root))
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (Array.isArray(s.allOf)) {
|
|
221
|
+
for (const branch of s.allOf)
|
|
222
|
+
check(branch, value, path, env, depth + 1, problems);
|
|
223
|
+
}
|
|
224
|
+
for (const key of ["anyOf", "oneOf"]) {
|
|
225
|
+
const branches = s[key];
|
|
226
|
+
if (!Array.isArray(branches) || branches.length === 0)
|
|
227
|
+
continue;
|
|
228
|
+
const fits = branches.some((branch) => {
|
|
229
|
+
const inner = [];
|
|
230
|
+
check(branch, value, path, env, depth + 1, inner);
|
|
231
|
+
return inner.length === 0;
|
|
232
|
+
});
|
|
233
|
+
if (!fits)
|
|
234
|
+
at(`matches none of the ${branches.length} allowed shapes`);
|
|
235
|
+
}
|
|
236
|
+
const actual = jsonType(value);
|
|
237
|
+
const types = typeof s.type === "string" ? [s.type] : Array.isArray(s.type) ? s.type : undefined;
|
|
238
|
+
// A type name outside the seven JSON types (draft 3's `any`, a typo) is a
|
|
239
|
+
// keyword the validator does not know, so the whole `type` check is skipped.
|
|
240
|
+
const knownTypes = types !== undefined &&
|
|
241
|
+
types.length > 0 &&
|
|
242
|
+
types.every((t) => typeof t === "string" && JSON_TYPES.has(t));
|
|
243
|
+
if (types && knownTypes && !types.some((t) => typeMatches(t, actual))) {
|
|
244
|
+
// "integer" is the schema's word for a kind of number, not a type a model writes.
|
|
245
|
+
at(`expected ${types.join(" or ")}, got ${actual === "integer" ? "number" : actual}`);
|
|
246
|
+
// The keywords below would only restate a wrong type as several problems.
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (Array.isArray(s.enum) && !s.enum.some((v) => deepEqual(v, value))) {
|
|
250
|
+
at(`must be one of ${quoted(s.enum)}`);
|
|
251
|
+
}
|
|
252
|
+
// `const` arrived in draft 6; an older schema's `const` is an unknown keyword.
|
|
253
|
+
if (Object.hasOwn(s, "const") && inDraft(env.root, 6) && !deepEqual(s.const, value)) {
|
|
254
|
+
at(`must be ${JSON.stringify(s.const)}`);
|
|
255
|
+
}
|
|
256
|
+
if (typeof value === "string") {
|
|
257
|
+
const length = [...value].length;
|
|
258
|
+
const min = num(s.minLength);
|
|
259
|
+
const max = num(s.maxLength);
|
|
260
|
+
if (min !== undefined && length < min)
|
|
261
|
+
at(`must be at least ${min} characters`);
|
|
262
|
+
if (max !== undefined && length > max)
|
|
263
|
+
at(`must be at most ${max} characters`);
|
|
264
|
+
const pattern = compile(s.pattern);
|
|
265
|
+
if (pattern && !pattern.test(value))
|
|
266
|
+
at(`must match the pattern ${String(s.pattern)}`);
|
|
267
|
+
}
|
|
268
|
+
if (typeof value === "number") {
|
|
269
|
+
const min = num(s.minimum);
|
|
270
|
+
const max = num(s.maximum);
|
|
271
|
+
// Draft 4 spelled the exclusive bounds as booleans beside minimum/maximum.
|
|
272
|
+
const exMin = num(s.exclusiveMinimum) ?? (s.exclusiveMinimum === true ? min : undefined);
|
|
273
|
+
const exMax = num(s.exclusiveMaximum) ?? (s.exclusiveMaximum === true ? max : undefined);
|
|
274
|
+
if (min !== undefined && s.exclusiveMinimum !== true && value < min)
|
|
275
|
+
at(`must be >= ${min}`);
|
|
276
|
+
if (max !== undefined && s.exclusiveMaximum !== true && value > max)
|
|
277
|
+
at(`must be <= ${max}`);
|
|
278
|
+
if (exMin !== undefined && value <= exMin)
|
|
279
|
+
at(`must be > ${exMin}`);
|
|
280
|
+
if (exMax !== undefined && value >= exMax)
|
|
281
|
+
at(`must be < ${exMax}`);
|
|
282
|
+
}
|
|
283
|
+
if (Array.isArray(value)) {
|
|
284
|
+
const min = num(s.minItems);
|
|
285
|
+
const max = num(s.maxItems);
|
|
286
|
+
if (min !== undefined && value.length < min)
|
|
287
|
+
at(`must have at least ${min} items`);
|
|
288
|
+
if (max !== undefined && value.length > max)
|
|
289
|
+
at(`must have at most ${max} items`);
|
|
290
|
+
// Positional schemas: `prefixItems` (2020-12) or an `items` array (draft 7).
|
|
291
|
+
// `prefixItems` arrived in 2020-12; under an older declared draft it is unknown.
|
|
292
|
+
const positional = Array.isArray(s.prefixItems) && inDraft(env.root, 2020)
|
|
293
|
+
? s.prefixItems
|
|
294
|
+
: Array.isArray(s.items)
|
|
295
|
+
? s.items
|
|
296
|
+
: [];
|
|
297
|
+
positional.forEach((item, i) => {
|
|
298
|
+
if (i < value.length)
|
|
299
|
+
check(item, value[i], pointer(path, i), env, depth + 1, problems);
|
|
300
|
+
});
|
|
301
|
+
if (!Array.isArray(s.items) && s.items !== undefined) {
|
|
302
|
+
for (let i = positional.length; i < value.length; i += 1) {
|
|
303
|
+
check(s.items, value[i], pointer(path, i), env, depth + 1, problems);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (isObject(value)) {
|
|
308
|
+
const properties = isObject(s.properties) ? s.properties : {};
|
|
309
|
+
if (Array.isArray(s.required)) {
|
|
310
|
+
for (const key of s.required) {
|
|
311
|
+
if (typeof key === "string" && !Object.hasOwn(value, key)) {
|
|
312
|
+
problems.push({ path: pointer(path, key), message: "is required" });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const min = num(s.minProperties);
|
|
317
|
+
const max = num(s.maxProperties);
|
|
318
|
+
const count = Object.keys(value).length;
|
|
319
|
+
if (min !== undefined && count < min)
|
|
320
|
+
at(`must have at least ${min} properties`);
|
|
321
|
+
if (max !== undefined && count > max)
|
|
322
|
+
at(`must have at most ${max} properties`);
|
|
323
|
+
// A key matched by `patternProperties` is not "additional". If any of its
|
|
324
|
+
// patterns cannot be compiled, nothing can be called additional with
|
|
325
|
+
// confidence, so that check is skipped rather than guessed.
|
|
326
|
+
const patternKeys = isObject(s.patternProperties) ? Object.keys(s.patternProperties) : [];
|
|
327
|
+
const patterns = patternKeys.map(compile);
|
|
328
|
+
const additionalKnown = patterns.every((p) => p !== undefined);
|
|
329
|
+
for (const [key, item] of Object.entries(value)) {
|
|
330
|
+
const where = pointer(path, key);
|
|
331
|
+
if (Object.hasOwn(properties, key)) {
|
|
332
|
+
check(properties[key], item, where, env, depth + 1, problems);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (!additionalKnown || patterns.some((p) => p?.test(key)))
|
|
336
|
+
continue;
|
|
337
|
+
if (s.additionalProperties === false) {
|
|
338
|
+
problems.push({ path: where, message: "is not an allowed property" });
|
|
339
|
+
}
|
|
340
|
+
else if (isObject(s.additionalProperties)) {
|
|
341
|
+
check(s.additionalProperties, item, where, env, depth + 1, problems);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AgentMessage, ToolCall, ToolResult } from "./providers/types.js";
|
|
2
|
+
/** A user turn as the loop's history carries it. */
|
|
3
|
+
export type UserTurn = Extract<AgentMessage, {
|
|
4
|
+
role: "user";
|
|
5
|
+
}>;
|
|
6
|
+
/** How {@link settleMessages} answers a tool call that has no result. */
|
|
7
|
+
export interface SettleOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The result for an unanswered call. The helper sets `toolCallId` itself.
|
|
10
|
+
* Absent, each call gets a neutral error result saying it was not run; pass
|
|
11
|
+
* one to say something else (`rejected: true` for a parked call the caller
|
|
12
|
+
* declined, say).
|
|
13
|
+
*/
|
|
14
|
+
answer?: (call: ToolCall) => Omit<ToolResult, "toolCallId">;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A transcript in which every tool call has a result, ready to be continued.
|
|
18
|
+
*
|
|
19
|
+
* A stored transcript can end on calls nobody answered: a run that suspended
|
|
20
|
+
* on an external call the caller then abandoned, or a transcript an
|
|
21
|
+
* application built or cut itself. Every provider rejects a tool call with no
|
|
22
|
+
* result, wherever it sits in the history, so each assistant turn's missing
|
|
23
|
+
* results are added here: into the tool turn that follows it when there is
|
|
24
|
+
* one (one tool turn answers one assistant turn, as `withToolResults` keeps
|
|
25
|
+
* it), else as a new tool turn straight after it. Calls that already have a
|
|
26
|
+
* result are left alone, so settling twice changes nothing.
|
|
27
|
+
*
|
|
28
|
+
* What the loop never writes is thrown on rather than dropped, since it
|
|
29
|
+
* means the transcript was damaged and rewriting what the model was shown
|
|
30
|
+
* would hide that: a tool turn that answers no call (one that does not follow
|
|
31
|
+
* an assistant turn, or a result for a call id that turn never made), two
|
|
32
|
+
* results for one call, two calls with one id, and an assistant turn's
|
|
33
|
+
* results split across consecutive tool turns. Settle after answering, never
|
|
34
|
+
* before: `settleMessages(withToolResults(messages, results))`.
|
|
35
|
+
*
|
|
36
|
+
* The output ends with whatever the input ended with, now whole; it is a
|
|
37
|
+
* valid seed when that is a user message or a tool turn. Use
|
|
38
|
+
* {@link withUserTurn} to append the next user message. Neither array is
|
|
39
|
+
* mutated; untouched messages are shared with the input.
|
|
40
|
+
*/
|
|
41
|
+
export declare function settleMessages(messages: AgentMessage[], options?: SettleOptions): AgentMessage[];
|
|
42
|
+
/**
|
|
43
|
+
* The seed for the next user turn: `messages` settled (see
|
|
44
|
+
* {@link settleMessages}), then `turn` appended. The result always passes the
|
|
45
|
+
* loop's seed check. A string is the turn's text; an object is the turn
|
|
46
|
+
* without its `role`.
|
|
47
|
+
*
|
|
48
|
+
* This prepares the transcript and nothing else. What the next run may spend
|
|
49
|
+
* is the caller's policy: pass fresh limits for a per-turn budget, or
|
|
50
|
+
* `remainingLimits(limits, consumed)` to carry one budget across turns.
|
|
51
|
+
*/
|
|
52
|
+
export declare function withUserTurn(messages: AgentMessage[], turn: string | Omit<UserTurn, "role">, options?: SettleOptions): AgentMessage[];
|
|
53
|
+
//# sourceMappingURL=transcript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAE9E,oDAAoD;AACpD,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE9D,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;CAC5D;AAeD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,GAAE,aAAkB,GAC1B,YAAY,EAAE,CA2DhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,YAAY,EAAE,EACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,EACrC,OAAO,GAAE,aAAkB,GAC1B,YAAY,EAAE,CAIhB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/** The result an unanswered call gets when the caller chose none. */
|
|
2
|
+
function unanswered() {
|
|
3
|
+
return { content: "not run: the turn ended before this tool call was answered", isError: true };
|
|
4
|
+
}
|
|
5
|
+
/** The values that occur more than once, each named once. */
|
|
6
|
+
function repeated(ids) {
|
|
7
|
+
const seen = new Set();
|
|
8
|
+
const twice = new Set();
|
|
9
|
+
for (const id of ids)
|
|
10
|
+
(seen.has(id) ? twice : seen).add(id);
|
|
11
|
+
return [...twice];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A transcript in which every tool call has a result, ready to be continued.
|
|
15
|
+
*
|
|
16
|
+
* A stored transcript can end on calls nobody answered: a run that suspended
|
|
17
|
+
* on an external call the caller then abandoned, or a transcript an
|
|
18
|
+
* application built or cut itself. Every provider rejects a tool call with no
|
|
19
|
+
* result, wherever it sits in the history, so each assistant turn's missing
|
|
20
|
+
* results are added here: into the tool turn that follows it when there is
|
|
21
|
+
* one (one tool turn answers one assistant turn, as `withToolResults` keeps
|
|
22
|
+
* it), else as a new tool turn straight after it. Calls that already have a
|
|
23
|
+
* result are left alone, so settling twice changes nothing.
|
|
24
|
+
*
|
|
25
|
+
* What the loop never writes is thrown on rather than dropped, since it
|
|
26
|
+
* means the transcript was damaged and rewriting what the model was shown
|
|
27
|
+
* would hide that: a tool turn that answers no call (one that does not follow
|
|
28
|
+
* an assistant turn, or a result for a call id that turn never made), two
|
|
29
|
+
* results for one call, two calls with one id, and an assistant turn's
|
|
30
|
+
* results split across consecutive tool turns. Settle after answering, never
|
|
31
|
+
* before: `settleMessages(withToolResults(messages, results))`.
|
|
32
|
+
*
|
|
33
|
+
* The output ends with whatever the input ended with, now whole; it is a
|
|
34
|
+
* valid seed when that is a user message or a tool turn. Use
|
|
35
|
+
* {@link withUserTurn} to append the next user message. Neither array is
|
|
36
|
+
* mutated; untouched messages are shared with the input.
|
|
37
|
+
*/
|
|
38
|
+
export function settleMessages(messages, options = {}) {
|
|
39
|
+
const answer = options.answer ?? unanswered;
|
|
40
|
+
const settled = [];
|
|
41
|
+
for (let i = 0; i < messages.length; i += 1) {
|
|
42
|
+
const message = messages[i];
|
|
43
|
+
if (!message)
|
|
44
|
+
continue;
|
|
45
|
+
if (message.role === "tool") {
|
|
46
|
+
// Every tool turn that follows an assistant turn is consumed below, so
|
|
47
|
+
// one reached here answers nothing.
|
|
48
|
+
throw new Error(`transcript message ${i} is a tool turn that does not follow an assistant turn, ` +
|
|
49
|
+
"so its results answer no call");
|
|
50
|
+
}
|
|
51
|
+
settled.push(message);
|
|
52
|
+
if (message.role !== "assistant" || message.toolCalls.length === 0)
|
|
53
|
+
continue;
|
|
54
|
+
const duplicateCalls = repeated(message.toolCalls.map((c) => c.id));
|
|
55
|
+
if (duplicateCalls.length > 0) {
|
|
56
|
+
throw new Error(`transcript message ${i} makes more than one tool call with the same id: ` +
|
|
57
|
+
duplicateCalls.join(", "));
|
|
58
|
+
}
|
|
59
|
+
const next = messages[i + 1];
|
|
60
|
+
const given = next?.role === "tool" ? next.results : [];
|
|
61
|
+
const asked = new Set(message.toolCalls.map((c) => c.id));
|
|
62
|
+
const stray = given.filter((r) => !asked.has(r.toolCallId)).map((r) => r.toolCallId);
|
|
63
|
+
if (stray.length > 0) {
|
|
64
|
+
throw new Error(`transcript message ${i + 1} answers call id(s) the assistant turn before it never made: ` +
|
|
65
|
+
stray.join(", "));
|
|
66
|
+
}
|
|
67
|
+
// Settling before answering (`withToolResults` after this helper) gives a
|
|
68
|
+
// call its placeholder and then its real result; every provider refuses
|
|
69
|
+
// two results for one call, so that is refused here instead.
|
|
70
|
+
const duplicateResults = repeated(given.map((r) => r.toolCallId));
|
|
71
|
+
if (duplicateResults.length > 0) {
|
|
72
|
+
throw new Error(`transcript message ${i + 1} answers call id(s) more than once: ` +
|
|
73
|
+
duplicateResults.join(", "));
|
|
74
|
+
}
|
|
75
|
+
const byId = new Map(given.map((r) => [r.toolCallId, r]));
|
|
76
|
+
if (next?.role === "tool")
|
|
77
|
+
i += 1;
|
|
78
|
+
if (next?.role === "tool" && byId.size === message.toolCalls.length) {
|
|
79
|
+
settled.push(next);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// In call order, so a stored tool turn reads in the order the calls were made.
|
|
83
|
+
settled.push({
|
|
84
|
+
role: "tool",
|
|
85
|
+
results: message.toolCalls.map((call) => byId.get(call.id) ?? { ...answer(call), toolCallId: call.id }),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return settled;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The seed for the next user turn: `messages` settled (see
|
|
92
|
+
* {@link settleMessages}), then `turn` appended. The result always passes the
|
|
93
|
+
* loop's seed check. A string is the turn's text; an object is the turn
|
|
94
|
+
* without its `role`.
|
|
95
|
+
*
|
|
96
|
+
* This prepares the transcript and nothing else. What the next run may spend
|
|
97
|
+
* is the caller's policy: pass fresh limits for a per-turn budget, or
|
|
98
|
+
* `remainingLimits(limits, consumed)` to carry one budget across turns.
|
|
99
|
+
*/
|
|
100
|
+
export function withUserTurn(messages, turn, options = {}) {
|
|
101
|
+
const user = typeof turn === "string" ? { role: "user", text: turn } : { ...turn, role: "user" };
|
|
102
|
+
return [...settleMessages(messages, options), user];
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -12,10 +12,23 @@ export interface ConnectorConfig {
|
|
|
12
12
|
/** For the stdio transport. */
|
|
13
13
|
command?: string;
|
|
14
14
|
args?: string[];
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Token is already resolved by the caller; the kernel treats it as opaque.
|
|
17
|
+
* For a credential that rotates, set `headers` instead of `token`: the
|
|
18
|
+
* kernel asks it for every request (HTTP-family transports only).
|
|
19
|
+
*/
|
|
16
20
|
auth?: {
|
|
17
21
|
type: "bearer" | "none";
|
|
18
22
|
token?: string;
|
|
23
|
+
headers?: ConnectorAuthHeaders;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The client identity announced to the server. Absent means the kernel's
|
|
27
|
+
* default name suffixed with the connector's own name, at version `0.1.0`.
|
|
28
|
+
*/
|
|
29
|
+
clientInfo?: {
|
|
30
|
+
name: string;
|
|
31
|
+
version?: string;
|
|
19
32
|
};
|
|
20
33
|
/**
|
|
21
34
|
* The server's own tool names (not namespaced) this run may see and call.
|
|
@@ -26,6 +39,28 @@ export interface ConnectorConfig {
|
|
|
26
39
|
*/
|
|
27
40
|
tools?: string[];
|
|
28
41
|
}
|
|
42
|
+
/** What the kernel tells a {@link ConnectorAuthHeaders} function when it asks. */
|
|
43
|
+
export interface ConnectorAuthRequest {
|
|
44
|
+
/** The connector's `name`. */
|
|
45
|
+
connector: string;
|
|
46
|
+
/**
|
|
47
|
+
* True when the server just answered 401 to headers this function gave: the
|
|
48
|
+
* kernel asks once more and retries the request once, so return a fresh
|
|
49
|
+
* credential rather than a cached one.
|
|
50
|
+
*/
|
|
51
|
+
refresh: boolean;
|
|
52
|
+
/** Aborts when the connection is closed. */
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Returns the headers that authenticate one request to an MCP server, e.g.
|
|
57
|
+
* `{ Authorization: "Bearer …" }`. Called before every request the transport
|
|
58
|
+
* makes, so cache inside it if minting is expensive. Every value is masked in
|
|
59
|
+
* what the run's tools hand back to the model, so return only credential
|
|
60
|
+
* headers. A throw fails that request with a message naming the connector,
|
|
61
|
+
* not the error.
|
|
62
|
+
*/
|
|
63
|
+
export type ConnectorAuthHeaders = (request: ConnectorAuthRequest) => Record<string, string> | Promise<Record<string, string>>;
|
|
29
64
|
/**
|
|
30
65
|
* What a run is allowed to touch. `tools` acts as an allowlist of tool names,
|
|
31
66
|
* `hosts` as an egress allowlist for the http_fetch primitive; the open index
|
|
@@ -69,11 +104,15 @@ export interface WorkflowDefinition {
|
|
|
69
104
|
preferred?: string;
|
|
70
105
|
};
|
|
71
106
|
prompt?: string;
|
|
72
|
-
/** Shell commands run in the sandbox BEFORE the agent, to install the
|
|
73
|
-
* dependencies (e.g. `npm ci`).
|
|
74
|
-
*
|
|
107
|
+
/** Shell commands meant to run in the sandbox BEFORE the agent, to install the
|
|
108
|
+
* run's own dependencies (e.g. `npm ci`). The kernel carries this and never
|
|
109
|
+
* executes it: the caller runs it before `engine.run`, with the run's secrets
|
|
110
|
+
* in env, and should abort the run on failure (the agent must not run without
|
|
111
|
+
* its deps). */
|
|
75
112
|
setup?: string[];
|
|
76
|
-
/** Shell commands run as a deterministic audit gate after output is
|
|
113
|
+
/** Shell commands meant to run as a deterministic audit gate after output is
|
|
114
|
+
* produced. The kernel carries this and never executes it: the caller runs it
|
|
115
|
+
* after `engine.run` and decides what a failure means. */
|
|
77
116
|
verify?: string[];
|
|
78
117
|
}
|
|
79
118
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IACpB,SAAS,EAAE,OAAO,GAAG,iBAAiB,GAAG,KAAK,CAAA;IAC9C,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IACpB,SAAS,EAAE,OAAO,GAAG,iBAAiB,GAAG,KAAK,CAAA;IAC9C,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAA;IAClF;;;OAGG;IACH,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/C;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,kFAAkF;AAClF,MAAM,WAAW,oBAAoB;IACnC,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,oBAAoB,KAC1B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAE7D;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3B,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,QAAQ,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;IAC1C,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC7C,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7B,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;qBAIiB;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB;;+DAE2D;IAC3D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rarebit-one/harness-kernel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Provider-neutral AI-harness kernel — LLM adapters, tool-use loop, MCP connectors, and a pluggable agent-engine seam",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"author": "
|
|
6
|
+
"author": "Rarebit One <code@jaryl.dev>",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"module": "./dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@anthropic-ai/sdk": "^1.0.0",
|
|
55
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.32.0",
|
|
56
56
|
"@zed-industries/agent-client-protocol": "^0.4.5",
|
|
57
57
|
"openai": "^7.4.0",
|
|
58
58
|
"undici": "^8.10.0",
|