tnega 0.1.1 → 0.3.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 +115 -100
- package/dist/agent.js +2510 -134
- package/dist/agent.js.map +4 -4
- package/dist/bin.js +30723 -5163
- package/dist/bin.js.map +4 -4
- package/dist/cli-runtime.js +30690 -5094
- package/dist/cli-runtime.js.map +4 -4
- package/dist/coding-agent.js +19088 -0
- package/dist/coding-agent.js.map +7 -0
- package/dist/core.js +74 -1
- package/dist/core.js.map +4 -4
- package/dist/eval.js +23159 -1990
- package/dist/eval.js.map +4 -4
- package/dist/events.js +22 -1
- package/dist/events.js.map +2 -2
- package/dist/evolve.js +17631 -1815
- package/dist/evolve.js.map +4 -4
- package/dist/index.js +31848 -6076
- package/dist/index.js.map +4 -4
- package/dist/llm.js +8 -0
- package/dist/llm.js.map +2 -2
- package/dist/services.js +12 -1
- package/dist/services.js.map +2 -2
- package/dist/session.js +793 -122
- package/dist/session.js.map +4 -4
- package/dist/tools.js +242 -135
- package/dist/tools.js.map +4 -4
- package/dist/types/packages/agent/src/inbox-durable.d.ts +54 -0
- package/dist/types/packages/agent/src/index.d.ts +4 -0
- package/dist/types/packages/agent/src/live.d.ts +115 -0
- package/dist/types/packages/agent/src/llm-service.d.ts +32 -0
- package/dist/types/packages/agent/src/prompt.d.ts +55 -0
- package/dist/types/packages/agent/src/service.d.ts +24 -0
- package/dist/types/packages/agent/src/types.d.ts +75 -1
- package/dist/types/packages/benchmark/src/bigcodebench.d.ts +6 -0
- package/dist/types/packages/benchmark/src/humaneval.d.ts +11 -0
- package/dist/types/packages/benchmark/src/index.d.ts +9 -0
- package/dist/types/packages/benchmark/src/manifest.d.ts +10 -0
- package/dist/types/packages/benchmark/src/mbpp.d.ts +10 -0
- package/dist/types/packages/benchmark/src/parquet.d.ts +2 -0
- package/dist/types/packages/benchmark/src/stdlib.d.ts +3 -0
- package/dist/types/packages/benchmark/src/swebench.d.ts +2 -0
- package/dist/types/packages/benchmark/src/types.d.ts +58 -0
- package/dist/types/packages/cli/src/commands.d.ts +26 -2
- package/dist/types/packages/cli/src/config.d.ts +2 -0
- package/dist/types/packages/cli/src/index.d.ts +4 -2
- package/dist/types/packages/cli/src/profile-file.d.ts +26 -0
- package/dist/types/packages/cli/src/profile.d.ts +9 -0
- package/dist/types/packages/cli/src/server.d.ts +2 -0
- package/dist/types/packages/cli/src/store.d.ts +10 -9
- package/dist/types/packages/coding-agent/src/codingAgent.d.ts +25 -0
- package/dist/types/packages/coding-agent/src/index.d.ts +6 -0
- package/dist/types/packages/coding-agent/src/mcp.d.ts +24 -0
- package/dist/types/packages/coding-agent/src/plan.d.ts +13 -0
- package/dist/types/packages/coding-agent/src/skills.d.ts +12 -0
- package/dist/types/packages/coding-agent/src/slash.d.ts +28 -0
- package/dist/types/packages/coding-agent/src/types.d.ts +41 -0
- package/dist/types/packages/core/src/events.d.ts +4 -1
- package/dist/types/packages/core/src/index.d.ts +1 -0
- package/dist/types/packages/core/src/invariant.d.ts +45 -0
- package/dist/types/packages/eval/src/codingRuntime.d.ts +18 -0
- package/dist/types/packages/eval/src/policy.d.ts +8 -0
- package/dist/types/packages/eval/src/runner.d.ts +4 -0
- package/dist/types/packages/eval/src/strategies.d.ts +10 -0
- package/dist/types/packages/eval/src/trace.d.ts +7 -0
- package/dist/types/packages/eval/src/types.d.ts +97 -1
- package/dist/types/packages/eval/src/workspace.d.ts +17 -0
- package/dist/types/packages/llm/src/types.d.ts +2 -0
- package/dist/types/packages/session/src/index.d.ts +397 -12
- package/dist/types/packages/session/src/invariant.d.ts +33 -0
- package/dist/types/packages/tools/src/builtins.d.ts +2 -0
- package/dist/types/packages/tools/src/execution.d.ts +31 -0
- package/dist/types/packages/tools/src/index.d.ts +17 -0
- package/dist/types/src/index.d.ts +5 -5
- package/dist/web/assets/index-45pokiBH.js +270 -0
- package/dist/web/assets/index-DCLL69Kz.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +92 -88
- package/dist/web/assets/index-C3jFlR4V.css +0 -1
- package/dist/web/assets/index-DeFGh2h4.js +0 -268
package/dist/tools.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createRequire as __tnegaCreateRequire } from 'node:module'; const require = __tnegaCreateRequire(import.meta.url);
|
|
2
|
+
|
|
1
3
|
// packages/core/src/utils.ts
|
|
2
4
|
var DisposableList = class {
|
|
3
5
|
sn = 0;
|
|
@@ -308,6 +310,16 @@ var EventsService = class {
|
|
|
308
310
|
args.push(next);
|
|
309
311
|
return next();
|
|
310
312
|
}
|
|
313
|
+
async waterfallAsync(...args) {
|
|
314
|
+
const [thisArg, callbacks] = this._resolve("waterfallAsync", args);
|
|
315
|
+
const inner = args.pop();
|
|
316
|
+
const next = async () => {
|
|
317
|
+
const callback = callbacks.shift();
|
|
318
|
+
return callback ? await Reflect.apply(callback, thisArg, args) : inner(...args);
|
|
319
|
+
};
|
|
320
|
+
args.push(next);
|
|
321
|
+
return next();
|
|
322
|
+
}
|
|
311
323
|
register(label, hooks, callback, options) {
|
|
312
324
|
const method = options.prepend ? "unshift" : "push";
|
|
313
325
|
return this.ctx.fiber.effect(() => {
|
|
@@ -837,7 +849,16 @@ var ReflectService = class {
|
|
|
837
849
|
this.mixin("reflect", ["get", "set", "provide", "accessor", "mixin"]);
|
|
838
850
|
this.mixin("fiber", ["runtime", "effect"]);
|
|
839
851
|
this.mixin("registry", ["inject", "plugin"]);
|
|
840
|
-
this.mixin("events", [
|
|
852
|
+
this.mixin("events", [
|
|
853
|
+
"on",
|
|
854
|
+
"once",
|
|
855
|
+
"parallel",
|
|
856
|
+
"emit",
|
|
857
|
+
"serial",
|
|
858
|
+
"bail",
|
|
859
|
+
"waterfall",
|
|
860
|
+
"waterfallAsync"
|
|
861
|
+
]);
|
|
841
862
|
}
|
|
842
863
|
ctx;
|
|
843
864
|
static handler = {
|
|
@@ -1255,7 +1276,6 @@ var Service = class _Service {
|
|
|
1255
1276
|
};
|
|
1256
1277
|
|
|
1257
1278
|
// packages/tools/src/builtins.ts
|
|
1258
|
-
import { spawn } from "node:child_process";
|
|
1259
1279
|
import {
|
|
1260
1280
|
appendFile,
|
|
1261
1281
|
mkdir,
|
|
@@ -1498,6 +1518,116 @@ function evaluateExpression(source) {
|
|
|
1498
1518
|
return value;
|
|
1499
1519
|
}
|
|
1500
1520
|
|
|
1521
|
+
// packages/tools/src/execution.ts
|
|
1522
|
+
import { spawn } from "node:child_process";
|
|
1523
|
+
function errorMessage(error) {
|
|
1524
|
+
if (error instanceof Error) return error.message;
|
|
1525
|
+
return String(error);
|
|
1526
|
+
}
|
|
1527
|
+
async function killProcessTree(child) {
|
|
1528
|
+
if (child.pid === void 0) return;
|
|
1529
|
+
if (process.platform === "win32") {
|
|
1530
|
+
await new Promise((resolve2) => {
|
|
1531
|
+
const killer = spawn("taskkill", ["/pid", String(child.pid), "/t", "/f"], {
|
|
1532
|
+
stdio: "ignore",
|
|
1533
|
+
windowsHide: true
|
|
1534
|
+
});
|
|
1535
|
+
killer.on("error", () => resolve2());
|
|
1536
|
+
killer.on("exit", () => resolve2());
|
|
1537
|
+
});
|
|
1538
|
+
} else {
|
|
1539
|
+
try {
|
|
1540
|
+
process.kill(-child.pid, "SIGKILL");
|
|
1541
|
+
} catch {
|
|
1542
|
+
}
|
|
1543
|
+
child.kill("SIGKILL");
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
function runLocalShell(request) {
|
|
1547
|
+
const timeoutMs = request.timeoutMs ?? 15e3;
|
|
1548
|
+
const maxBuffer = request.maxBuffer ?? 1024 * 1024;
|
|
1549
|
+
return new Promise((resolve2, reject) => {
|
|
1550
|
+
const child = spawn(request.command, {
|
|
1551
|
+
cwd: request.cwd,
|
|
1552
|
+
shell: true,
|
|
1553
|
+
windowsHide: true,
|
|
1554
|
+
...process.platform === "win32" ? {} : { detached: true }
|
|
1555
|
+
});
|
|
1556
|
+
let stdout = "";
|
|
1557
|
+
let stderr = "";
|
|
1558
|
+
let settled = false;
|
|
1559
|
+
let timer;
|
|
1560
|
+
let onAbort = () => {
|
|
1561
|
+
};
|
|
1562
|
+
const append = (target, chunk, limit) => {
|
|
1563
|
+
if (target.length >= limit) return target;
|
|
1564
|
+
return target + chunk.toString("utf8").slice(0, limit - target.length);
|
|
1565
|
+
};
|
|
1566
|
+
const cleanup = () => {
|
|
1567
|
+
if (timer) clearTimeout(timer);
|
|
1568
|
+
request.signal?.removeEventListener("abort", onAbort);
|
|
1569
|
+
};
|
|
1570
|
+
const finish = (action) => {
|
|
1571
|
+
if (settled) return;
|
|
1572
|
+
settled = true;
|
|
1573
|
+
cleanup();
|
|
1574
|
+
action();
|
|
1575
|
+
};
|
|
1576
|
+
const fail2 = (message2) => {
|
|
1577
|
+
finish(() => {
|
|
1578
|
+
void killProcessTree(child).finally(() => reject(new Error(message2)));
|
|
1579
|
+
});
|
|
1580
|
+
};
|
|
1581
|
+
onAbort = () => fail2("shell command cancelled");
|
|
1582
|
+
if (request.signal) {
|
|
1583
|
+
if (request.signal.aborted) onAbort();
|
|
1584
|
+
else request.signal.addEventListener("abort", onAbort, { once: true });
|
|
1585
|
+
}
|
|
1586
|
+
if (timeoutMs > 0) {
|
|
1587
|
+
timer = setTimeout(() => fail2(`shell command timed out after ${timeoutMs}ms`), timeoutMs);
|
|
1588
|
+
}
|
|
1589
|
+
child.stdout.on("data", (chunk) => {
|
|
1590
|
+
stdout = append(stdout, chunk, maxBuffer);
|
|
1591
|
+
});
|
|
1592
|
+
child.stderr.on("data", (chunk) => {
|
|
1593
|
+
stderr = append(stderr, chunk, maxBuffer);
|
|
1594
|
+
});
|
|
1595
|
+
child.on("error", (error) => {
|
|
1596
|
+
finish(() => resolve2({ exitCode: 1, stdout, stderr: errorMessage(error) }));
|
|
1597
|
+
});
|
|
1598
|
+
child.on("close", (code, closeSignal) => {
|
|
1599
|
+
finish(() => resolve2({
|
|
1600
|
+
exitCode: code ?? 1,
|
|
1601
|
+
stdout,
|
|
1602
|
+
stderr: closeSignal ? `killed by ${closeSignal}` : stderr
|
|
1603
|
+
}));
|
|
1604
|
+
});
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
var localExecutionProvider = {
|
|
1608
|
+
runShell: runLocalShell,
|
|
1609
|
+
async fetchHttp(request) {
|
|
1610
|
+
const init = {};
|
|
1611
|
+
if (request.headers) init.headers = request.headers;
|
|
1612
|
+
if (request.signal) init.signal = request.signal;
|
|
1613
|
+
const response = await fetch(request.url, init);
|
|
1614
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
1615
|
+
const maxBytes = request.maxBytes ?? 256 * 1024;
|
|
1616
|
+
const truncated = buffer.byteLength > maxBytes;
|
|
1617
|
+
const headers = {};
|
|
1618
|
+
response.headers.forEach((value, key) => {
|
|
1619
|
+
headers[key] = value;
|
|
1620
|
+
});
|
|
1621
|
+
return {
|
|
1622
|
+
status: response.status,
|
|
1623
|
+
ok: response.ok,
|
|
1624
|
+
headers,
|
|
1625
|
+
body: buffer.subarray(0, maxBytes).toString("utf8"),
|
|
1626
|
+
truncated
|
|
1627
|
+
};
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
|
|
1501
1631
|
// packages/tools/src/path.ts
|
|
1502
1632
|
import { realpath } from "node:fs/promises";
|
|
1503
1633
|
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
@@ -1570,7 +1700,8 @@ function normalizeConfig(config = {}) {
|
|
|
1570
1700
|
maxWriteBytes: config.maxWriteBytes ?? 1024 * 1024,
|
|
1571
1701
|
maxSearchBytes: config.maxSearchBytes ?? 1024 * 1024,
|
|
1572
1702
|
maxResults: config.maxResults ?? 200,
|
|
1573
|
-
timeoutMs: config.timeoutMs ?? 15e3
|
|
1703
|
+
timeoutMs: config.timeoutMs ?? 15e3,
|
|
1704
|
+
execution: config.execution ?? localExecutionProvider
|
|
1574
1705
|
};
|
|
1575
1706
|
}
|
|
1576
1707
|
function definition(name2, description, execute, parameters) {
|
|
@@ -2038,22 +2169,12 @@ function httpGetTool(config) {
|
|
|
2038
2169
|
}
|
|
2039
2170
|
const headers = optionalRecord(args.headers, "headers") ?? {};
|
|
2040
2171
|
const maxBytes = optionalNumber(args.maxBytes, "maxBytes") ?? config.maxReadBytes;
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
const headerMap = {};
|
|
2047
|
-
response.headers.forEach((value, key) => {
|
|
2048
|
-
headerMap[key] = value;
|
|
2172
|
+
return config.execution.fetchHttp({
|
|
2173
|
+
url: url.href,
|
|
2174
|
+
...Object.keys(headers).length ? { headers } : {},
|
|
2175
|
+
...maxBytes !== config.maxReadBytes ? { maxBytes } : {},
|
|
2176
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2049
2177
|
});
|
|
2050
|
-
return {
|
|
2051
|
-
status: response.status,
|
|
2052
|
-
ok: response.ok,
|
|
2053
|
-
headers: headerMap,
|
|
2054
|
-
body: buffer.subarray(0, maxBytes).toString("utf8"),
|
|
2055
|
-
truncated
|
|
2056
|
-
};
|
|
2057
2178
|
},
|
|
2058
2179
|
{
|
|
2059
2180
|
type: "object",
|
|
@@ -2078,13 +2199,13 @@ function shellTool(config) {
|
|
|
2078
2199
|
const command = stringField(args.command, "command");
|
|
2079
2200
|
const cwd = await resolveInside(config.cwd, optionalString(args.cwd, "cwd") ?? ".");
|
|
2080
2201
|
const timeoutMs = optionalNumber(args.timeoutMs, "timeoutMs") ?? config.timeoutMs;
|
|
2081
|
-
const result = await
|
|
2202
|
+
const result = await config.execution.runShell({
|
|
2082
2203
|
command,
|
|
2083
2204
|
cwd,
|
|
2084
2205
|
timeoutMs,
|
|
2085
|
-
config.maxWriteBytes,
|
|
2086
|
-
options.signal
|
|
2087
|
-
);
|
|
2206
|
+
maxBuffer: config.maxWriteBytes,
|
|
2207
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2208
|
+
});
|
|
2088
2209
|
return {
|
|
2089
2210
|
exitCode: result.exitCode,
|
|
2090
2211
|
stdout: result.stdout,
|
|
@@ -2102,84 +2223,6 @@ function shellTool(config) {
|
|
|
2102
2223
|
}
|
|
2103
2224
|
);
|
|
2104
2225
|
}
|
|
2105
|
-
async function killProcessTree(child) {
|
|
2106
|
-
if (child.pid === void 0) return;
|
|
2107
|
-
if (process.platform === "win32") {
|
|
2108
|
-
await new Promise((resolve2) => {
|
|
2109
|
-
const killer = spawn("taskkill", ["/pid", String(child.pid), "/t", "/f"], {
|
|
2110
|
-
stdio: "ignore",
|
|
2111
|
-
windowsHide: true
|
|
2112
|
-
});
|
|
2113
|
-
killer.on("error", () => resolve2());
|
|
2114
|
-
killer.on("exit", () => resolve2());
|
|
2115
|
-
});
|
|
2116
|
-
} else {
|
|
2117
|
-
try {
|
|
2118
|
-
process.kill(-child.pid, "SIGKILL");
|
|
2119
|
-
} catch {
|
|
2120
|
-
}
|
|
2121
|
-
child.kill("SIGKILL");
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2124
|
-
function runShellCommand(command, cwd, timeoutMs, maxBuffer, signal) {
|
|
2125
|
-
return new Promise((resolve2, reject) => {
|
|
2126
|
-
const child = spawn(command, {
|
|
2127
|
-
cwd,
|
|
2128
|
-
shell: true,
|
|
2129
|
-
windowsHide: true,
|
|
2130
|
-
...process.platform === "win32" ? {} : { detached: true }
|
|
2131
|
-
});
|
|
2132
|
-
let stdout = "";
|
|
2133
|
-
let stderr = "";
|
|
2134
|
-
let settled = false;
|
|
2135
|
-
let timer;
|
|
2136
|
-
let onAbort = () => {
|
|
2137
|
-
};
|
|
2138
|
-
const append = (target, chunk, limit) => {
|
|
2139
|
-
if (target.length >= limit) return target;
|
|
2140
|
-
return target + chunk.toString("utf8").slice(0, limit - target.length);
|
|
2141
|
-
};
|
|
2142
|
-
const cleanup = () => {
|
|
2143
|
-
if (timer) clearTimeout(timer);
|
|
2144
|
-
signal?.removeEventListener("abort", onAbort);
|
|
2145
|
-
};
|
|
2146
|
-
const finish = (action) => {
|
|
2147
|
-
if (settled) return;
|
|
2148
|
-
settled = true;
|
|
2149
|
-
cleanup();
|
|
2150
|
-
action();
|
|
2151
|
-
};
|
|
2152
|
-
const fail2 = (message2) => {
|
|
2153
|
-
finish(() => {
|
|
2154
|
-
void killProcessTree(child).finally(() => reject(new Error(message2)));
|
|
2155
|
-
});
|
|
2156
|
-
};
|
|
2157
|
-
onAbort = () => fail2("shell command cancelled");
|
|
2158
|
-
if (signal) {
|
|
2159
|
-
if (signal.aborted) onAbort();
|
|
2160
|
-
else signal.addEventListener("abort", onAbort, { once: true });
|
|
2161
|
-
}
|
|
2162
|
-
if (timeoutMs > 0) {
|
|
2163
|
-
timer = setTimeout(() => fail2(`shell command timed out after ${timeoutMs}ms`), timeoutMs);
|
|
2164
|
-
}
|
|
2165
|
-
child.stdout.on("data", (chunk) => {
|
|
2166
|
-
stdout = append(stdout, chunk, maxBuffer);
|
|
2167
|
-
});
|
|
2168
|
-
child.stderr.on("data", (chunk) => {
|
|
2169
|
-
stderr = append(stderr, chunk, maxBuffer);
|
|
2170
|
-
});
|
|
2171
|
-
child.on("error", (error) => {
|
|
2172
|
-
finish(() => resolve2({ exitCode: 1, stdout, stderr: message(error) }));
|
|
2173
|
-
});
|
|
2174
|
-
child.on("close", (code, closeSignal) => {
|
|
2175
|
-
finish(() => resolve2({
|
|
2176
|
-
exitCode: code ?? 1,
|
|
2177
|
-
stdout,
|
|
2178
|
-
stderr: closeSignal ? `killed by ${closeSignal}` : stderr
|
|
2179
|
-
}));
|
|
2180
|
-
});
|
|
2181
|
-
});
|
|
2182
|
-
}
|
|
2183
2226
|
function createBuiltinToolDefinitions(config = {}) {
|
|
2184
2227
|
const normalized = normalizeConfig(config);
|
|
2185
2228
|
const disabled = new Set(normalized.disabled);
|
|
@@ -2320,6 +2363,7 @@ function toToolError(error) {
|
|
|
2320
2363
|
var ToolsService = class extends Service {
|
|
2321
2364
|
static provide = "tools";
|
|
2322
2365
|
_tools = /* @__PURE__ */ new Map();
|
|
2366
|
+
_guards = /* @__PURE__ */ new Set();
|
|
2323
2367
|
_policy;
|
|
2324
2368
|
constructor(ctx, config = {}) {
|
|
2325
2369
|
super(ctx, "tools");
|
|
@@ -2337,13 +2381,27 @@ var ToolsService = class extends Service {
|
|
|
2337
2381
|
throw new ToolAlreadyRegisteredError(name2);
|
|
2338
2382
|
}
|
|
2339
2383
|
this._tools.set(name2, definition2);
|
|
2384
|
+
this.ctx.emit("tools/change");
|
|
2340
2385
|
return () => {
|
|
2341
2386
|
this._tools.delete(name2);
|
|
2387
|
+
this.ctx.emit("tools/change");
|
|
2342
2388
|
};
|
|
2343
2389
|
}, `ctx.tools.register(${JSON.stringify(name2)})`);
|
|
2344
2390
|
}
|
|
2345
2391
|
unregister(name2) {
|
|
2346
|
-
|
|
2392
|
+
const removed = this._tools.delete(name2);
|
|
2393
|
+
if (removed) this.ctx.emit("tools/change");
|
|
2394
|
+
return removed;
|
|
2395
|
+
}
|
|
2396
|
+
/** Register a monotonic guard evaluated after pre-execute policy. */
|
|
2397
|
+
guard(guard) {
|
|
2398
|
+
if (typeof guard !== "function") throw new TypeError("tool guard must be a function");
|
|
2399
|
+
return this.ctx.fiber.effect(() => {
|
|
2400
|
+
this._guards.add(guard);
|
|
2401
|
+
return () => {
|
|
2402
|
+
this._guards.delete(guard);
|
|
2403
|
+
};
|
|
2404
|
+
}, "ctx.tools.guard()");
|
|
2347
2405
|
}
|
|
2348
2406
|
has(name2) {
|
|
2349
2407
|
return this._tools.has(name2);
|
|
@@ -2357,58 +2415,99 @@ var ToolsService = class extends Service {
|
|
|
2357
2415
|
async execute(name2, input, options = {}) {
|
|
2358
2416
|
const tool = this._tools.get(name2);
|
|
2359
2417
|
if (!tool) throw new ToolNotFoundError(name2);
|
|
2360
|
-
|
|
2418
|
+
let request = {
|
|
2361
2419
|
tool,
|
|
2362
2420
|
name: name2,
|
|
2363
2421
|
input,
|
|
2364
2422
|
options,
|
|
2365
2423
|
startedAt: Date.now()
|
|
2366
2424
|
};
|
|
2367
|
-
|
|
2368
|
-
const policy = request.tool.policy;
|
|
2369
|
-
const authorizer = policy?.authorizer ?? this._policy.authorizer;
|
|
2370
|
-
if (authorizer) {
|
|
2371
|
-
const allowed = await authorizer(request);
|
|
2372
|
-
if (!allowed) {
|
|
2373
|
-
return this._finish(
|
|
2374
|
-
request,
|
|
2375
|
-
this._failure(
|
|
2376
|
-
request,
|
|
2377
|
-
new ToolAuthorizationError(`tool authorization denied: ${name2}`)
|
|
2378
|
-
)
|
|
2379
|
-
);
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
const validator = policy?.validator ?? this._policy.validator;
|
|
2425
|
+
let preError;
|
|
2383
2426
|
try {
|
|
2384
|
-
await
|
|
2427
|
+
const resolved = await this.ctx.waterfallAsync(
|
|
2428
|
+
"tools/pre-execute",
|
|
2429
|
+
request,
|
|
2430
|
+
async (payload) => {
|
|
2431
|
+
await this._applyPolicy(payload);
|
|
2432
|
+
return payload;
|
|
2433
|
+
}
|
|
2434
|
+
);
|
|
2435
|
+
if (!resolved) {
|
|
2436
|
+
throw new ToolAuthorizationError(`tool rejected by tools/pre-execute: ${name2}`);
|
|
2437
|
+
}
|
|
2438
|
+
request = resolved;
|
|
2439
|
+
const denial = await this._checkGuards(request);
|
|
2440
|
+
if (denial) throw new ToolAuthorizationError(denial);
|
|
2385
2441
|
} catch (error) {
|
|
2386
|
-
|
|
2442
|
+
preError = error;
|
|
2387
2443
|
}
|
|
2388
|
-
let
|
|
2389
|
-
let caught;
|
|
2444
|
+
let result;
|
|
2390
2445
|
try {
|
|
2391
|
-
|
|
2392
|
-
|
|
2446
|
+
if (!preError) {
|
|
2447
|
+
result = await this.ctx.waterfallAsync(
|
|
2448
|
+
"tools/execute",
|
|
2449
|
+
request,
|
|
2450
|
+
async (payload) => {
|
|
2451
|
+
const output = await payload.tool.execute(payload.input, payload.options);
|
|
2452
|
+
return this._success(payload, output);
|
|
2453
|
+
}
|
|
2454
|
+
);
|
|
2455
|
+
}
|
|
2393
2456
|
} catch (error) {
|
|
2394
|
-
|
|
2457
|
+
result = this._failure(request, error);
|
|
2395
2458
|
}
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
return this._finish(request, this._failure(request, error));
|
|
2403
|
-
}
|
|
2459
|
+
if (preError) result = this._failure(request, preError);
|
|
2460
|
+
if (!result) {
|
|
2461
|
+
result = this._failure(
|
|
2462
|
+
request,
|
|
2463
|
+
new Error("tools/execute did not return a tool result")
|
|
2464
|
+
);
|
|
2404
2465
|
}
|
|
2405
|
-
|
|
2466
|
+
try {
|
|
2467
|
+
const normalized = await this.ctx.waterfallAsync(
|
|
2468
|
+
"tools/post-execute",
|
|
2469
|
+
{ request, result },
|
|
2470
|
+
async (payload) => {
|
|
2471
|
+
const policy = payload.request.tool.policy;
|
|
2472
|
+
const truncator = policy?.truncator ?? this._policy.truncator;
|
|
2473
|
+
return truncator ? await truncator(payload.result, payload.request) : payload.result;
|
|
2474
|
+
}
|
|
2475
|
+
);
|
|
2476
|
+
if (normalized && typeof normalized.ok === "boolean") result = normalized;
|
|
2477
|
+
} catch (error) {
|
|
2478
|
+
result = this._failure(request, error);
|
|
2479
|
+
}
|
|
2480
|
+
return this._finish(
|
|
2481
|
+
request,
|
|
2482
|
+
result ?? this._failure(
|
|
2483
|
+
request,
|
|
2484
|
+
new Error("tools/execute did not return a tool result")
|
|
2485
|
+
)
|
|
2486
|
+
);
|
|
2406
2487
|
}
|
|
2407
2488
|
async _finish(request, result) {
|
|
2408
|
-
await this.ctx.parallel("tools/post-execute", { request, result });
|
|
2409
2489
|
await this.ctx.parallel("tools/result", { request, result });
|
|
2410
2490
|
return result;
|
|
2411
2491
|
}
|
|
2492
|
+
async _applyPolicy(request) {
|
|
2493
|
+
const policy = request.tool.policy;
|
|
2494
|
+
const authorizer = policy?.authorizer ?? this._policy.authorizer;
|
|
2495
|
+
if (authorizer) {
|
|
2496
|
+
const allowed = await authorizer(request);
|
|
2497
|
+
if (!allowed) {
|
|
2498
|
+
throw new ToolAuthorizationError(`tool authorization denied: ${request.name}`);
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
const validator = policy?.validator ?? this._policy.validator;
|
|
2502
|
+
if (validator) await validator(request.input, request.tool);
|
|
2503
|
+
}
|
|
2504
|
+
async _checkGuards(request) {
|
|
2505
|
+
for (const guard of this._guards) {
|
|
2506
|
+
const denial = await guard(request);
|
|
2507
|
+
if (denial) return denial;
|
|
2508
|
+
}
|
|
2509
|
+
return void 0;
|
|
2510
|
+
}
|
|
2412
2511
|
_validate(definition2) {
|
|
2413
2512
|
if (!definition2 || typeof definition2.schema?.name !== "string" || !definition2.schema.name) {
|
|
2414
2513
|
throw new TypeError("tool definition requires a non-empty schema.name");
|
|
@@ -2427,6 +2526,7 @@ var ToolsService = class extends Service {
|
|
|
2427
2526
|
durationMs: Date.now() - request.startedAt
|
|
2428
2527
|
};
|
|
2429
2528
|
if (request.options.callId) result.callId = request.options.callId;
|
|
2529
|
+
this._applyConcludesTurn(request, result);
|
|
2430
2530
|
return result;
|
|
2431
2531
|
}
|
|
2432
2532
|
_failure(request, error) {
|
|
@@ -2441,6 +2541,12 @@ var ToolsService = class extends Service {
|
|
|
2441
2541
|
if (request.options.callId) result.callId = request.options.callId;
|
|
2442
2542
|
return result;
|
|
2443
2543
|
}
|
|
2544
|
+
_applyConcludesTurn(request, result) {
|
|
2545
|
+
const staticDeclares = request.tool.metadata?.concludesTurn;
|
|
2546
|
+
if (staticDeclares === true || request.options.concludesTurn === true) {
|
|
2547
|
+
result.concludesTurn = true;
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2444
2550
|
};
|
|
2445
2551
|
var tools = {
|
|
2446
2552
|
name: "tools",
|
|
@@ -2461,6 +2567,7 @@ export {
|
|
|
2461
2567
|
builtinTools,
|
|
2462
2568
|
createBuiltinToolDefinitions,
|
|
2463
2569
|
evaluateExpression,
|
|
2570
|
+
localExecutionProvider,
|
|
2464
2571
|
name,
|
|
2465
2572
|
resolveInside,
|
|
2466
2573
|
tools,
|