@theokit/agents 0.2.0 → 0.4.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/dist/bridge.d.ts +97 -13
- package/dist/bridge.js +15 -4
- package/dist/chunk-7QVYU63E.js +7 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/{chunk-YSQAZWGW.js → chunk-NC5EE7HN.js} +325 -237
- package/dist/chunk-NC5EE7HN.js.map +1 -0
- package/dist/{chunk-3LCIXX3T.js → chunk-O4UG4RXE.js} +19 -7
- package/dist/chunk-O4UG4RXE.js.map +1 -0
- package/dist/{chunk-XUACDN32.js → chunk-VKHDADMG.js} +35 -13
- package/dist/chunk-VKHDADMG.js.map +1 -0
- package/dist/decorators.d.ts +8 -4
- package/dist/decorators.js +3 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +16 -5
- package/dist/{mcp-DmtwLSF-.d.ts → mcp-yyfC5u7t.d.ts} +2 -2
- package/dist/testing.d.ts +47 -0
- package/dist/testing.js +73 -0
- package/dist/testing.js.map +1 -0
- package/package.json +9 -3
- package/dist/chunk-3LCIXX3T.js.map +0 -1
- package/dist/chunk-XUACDN32.js.map +0 -1
- package/dist/chunk-YSQAZWGW.js.map +0 -1
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
AGENT_CONFIG,
|
|
3
3
|
AGENT_MAIN_LOOP,
|
|
4
4
|
Audit,
|
|
5
|
+
Budget,
|
|
5
6
|
RequiresApproval,
|
|
6
7
|
TOOLBOX_CONFIG,
|
|
7
8
|
TOOL_CONFIG,
|
|
8
9
|
TOOL_METHODS,
|
|
9
10
|
Trace,
|
|
10
|
-
__name,
|
|
11
11
|
getAgentConfig,
|
|
12
12
|
getGatewayConfig,
|
|
13
13
|
getMcpConfig,
|
|
@@ -16,7 +16,10 @@ import {
|
|
|
16
16
|
getMixins,
|
|
17
17
|
getSkillsConfig,
|
|
18
18
|
getSubAgents
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-O4UG4RXE.js";
|
|
20
|
+
import {
|
|
21
|
+
__name
|
|
22
|
+
} from "./chunk-7QVYU63E.js";
|
|
20
23
|
|
|
21
24
|
// src/bridge/agent-execution-context.ts
|
|
22
25
|
function createAgentExecutionContext(base, agent, run, toolCall) {
|
|
@@ -39,11 +42,16 @@ __name(isAgentContext, "isAgentContext");
|
|
|
39
42
|
|
|
40
43
|
// src/bridge/walk-agent-metadata.ts
|
|
41
44
|
import "reflect-metadata";
|
|
42
|
-
import { Reflector } from "@theokit/http
|
|
43
|
-
var reflectorInstance = new Reflector();
|
|
45
|
+
import { Reflector } from "@theokit/http";
|
|
44
46
|
var USE_GUARDS = /* @__PURE__ */ Symbol.for("theokit:http-decorators:use-guards");
|
|
45
47
|
var USE_INTERCEPTORS = /* @__PURE__ */ Symbol.for("theokit:http-decorators:use-interceptors");
|
|
46
48
|
var USE_FILTERS = /* @__PURE__ */ Symbol.for("theokit:http-decorators:use-filters");
|
|
49
|
+
var AgentWarningCode = {
|
|
50
|
+
INTERCEPTOR_METADATA_ONLY: "THEO_AGENT_INTERCEPTOR_METADATA_ONLY",
|
|
51
|
+
FILTER_METADATA_ONLY: "THEO_AGENT_FILTER_METADATA_ONLY",
|
|
52
|
+
BUDGET_TOP_LEVEL_METADATA_ONLY: "THEO_AGENT_BUDGET_TOP_LEVEL_METADATA_ONLY"
|
|
53
|
+
};
|
|
54
|
+
var reflectorInstance = new Reflector();
|
|
47
55
|
function walkToolbox(ToolboxClass) {
|
|
48
56
|
const config = getMeta(TOOLBOX_CONFIG, ToolboxClass) ?? {};
|
|
49
57
|
const methods = getMeta(TOOL_METHODS, ToolboxClass) ?? [];
|
|
@@ -96,7 +104,17 @@ function walkAgentMetadata(AgentClass, toolboxClasses = []) {
|
|
|
96
104
|
}
|
|
97
105
|
const guards = getMeta(USE_GUARDS, AgentClass) ?? [];
|
|
98
106
|
const interceptors = getMeta(USE_INTERCEPTORS, AgentClass) ?? [];
|
|
107
|
+
if (interceptors.length > 0) {
|
|
108
|
+
console.warn(`[${AgentWarningCode.INTERCEPTOR_METADATA_ONLY}] Agent ${AgentClass.name}: @UseInterceptors is metadata-only on agents and will not execute. Agent pipeline shares guards with HTTP but uses a distinct execution model. Interceptors are reserved for future agent-specific lifecycle hooks.`);
|
|
109
|
+
}
|
|
99
110
|
const filters = getMeta(USE_FILTERS, AgentClass) ?? [];
|
|
111
|
+
if (filters.length > 0) {
|
|
112
|
+
console.warn(`[${AgentWarningCode.FILTER_METADATA_ONLY}] Agent ${AgentClass.name}: @UseFilters is metadata-only on agents and will not catch agent runtime errors. Agent errors flow through SSE error events, not HTTP exception filters. Filters are reserved for future agent-specific error handling.`);
|
|
113
|
+
}
|
|
114
|
+
const agentBudget = reflectorInstance.get(Budget, AgentClass);
|
|
115
|
+
if (agentBudget) {
|
|
116
|
+
console.warn(`[${AgentWarningCode.BUDGET_TOP_LEVEL_METADATA_ONLY}] Agent ${AgentClass.name}: @Budget on top-level agents is metadata-only in this version. Budget enforcement currently applies to delegate() calls only. Top-level run enforcement will be wired through SDK cost tracking in a future release.`);
|
|
117
|
+
}
|
|
100
118
|
const toolboxes = toolboxClasses.map(walkToolbox);
|
|
101
119
|
const gateway = getGatewayConfig(AgentClass);
|
|
102
120
|
const subAgentClasses = getSubAgents(AgentClass);
|
|
@@ -299,7 +317,8 @@ function generateAgentRoutes(ctx) {
|
|
|
299
317
|
}
|
|
300
318
|
});
|
|
301
319
|
}
|
|
302
|
-
const
|
|
320
|
+
const rawSessionId = body?.sessionId;
|
|
321
|
+
const sessionId = typeof rawSessionId === "string" ? rawSessionId : `session-${Date.now()}`;
|
|
303
322
|
return streamAgentResponse(createRun(message, sessionId));
|
|
304
323
|
}, "handler")
|
|
305
324
|
});
|
|
@@ -337,253 +356,308 @@ function generateAgentRoutes(ctx) {
|
|
|
337
356
|
}
|
|
338
357
|
__name(generateAgentRoutes, "generateAgentRoutes");
|
|
339
358
|
|
|
340
|
-
// src/bridge/
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
359
|
+
// src/bridge/event-translator.ts
|
|
360
|
+
function asString(value, fallback) {
|
|
361
|
+
if (typeof value === "string") return value;
|
|
362
|
+
return fallback;
|
|
363
|
+
}
|
|
364
|
+
__name(asString, "asString");
|
|
365
|
+
function translateSystemEvent(msg, runId) {
|
|
366
|
+
return [
|
|
367
|
+
{
|
|
368
|
+
type: "run_started",
|
|
369
|
+
runId,
|
|
370
|
+
agentName: asString(msg.agent_id, "agent"),
|
|
371
|
+
model: asString(msg.model, "unknown")
|
|
372
|
+
}
|
|
373
|
+
];
|
|
374
|
+
}
|
|
375
|
+
__name(translateSystemEvent, "translateSystemEvent");
|
|
376
|
+
function translateAssistantEvent(msg) {
|
|
377
|
+
const events = [];
|
|
378
|
+
const content = msg.content;
|
|
379
|
+
if (!Array.isArray(content)) return events;
|
|
380
|
+
for (const block of content) {
|
|
381
|
+
const b = block;
|
|
382
|
+
if (b.type === "text" && b.text) {
|
|
383
|
+
events.push({
|
|
384
|
+
type: "text_delta",
|
|
385
|
+
content: b.text
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
if (b.type === "tool_use") {
|
|
389
|
+
events.push({
|
|
390
|
+
type: "tool_call",
|
|
391
|
+
callId: b.id ?? `tc-${Date.now()}`,
|
|
392
|
+
toolName: b.name ?? "unknown",
|
|
393
|
+
input: b.input ?? {}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
348
396
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
toolMap.set(s, t);
|
|
364
|
-
return {
|
|
365
|
-
type: "function",
|
|
366
|
-
function: {
|
|
367
|
-
name: s,
|
|
368
|
-
description: t.description,
|
|
369
|
-
parameters: convertZodToJsonSchema(t.inputSchema)
|
|
397
|
+
return events;
|
|
398
|
+
}
|
|
399
|
+
__name(translateAssistantEvent, "translateAssistantEvent");
|
|
400
|
+
function translateToolCallEvent(msg) {
|
|
401
|
+
const status = msg.status;
|
|
402
|
+
if (status === "completed") {
|
|
403
|
+
return [
|
|
404
|
+
{
|
|
405
|
+
type: "tool_result",
|
|
406
|
+
callId: asString(msg.id, `tc-${Date.now()}`),
|
|
407
|
+
toolName: asString(msg.name, "unknown"),
|
|
408
|
+
output: asString(msg.result, ""),
|
|
409
|
+
durationMs: 0,
|
|
410
|
+
isError: false
|
|
370
411
|
}
|
|
371
|
-
|
|
372
|
-
}
|
|
373
|
-
|
|
412
|
+
];
|
|
413
|
+
}
|
|
414
|
+
if (status === "error") {
|
|
415
|
+
return [
|
|
416
|
+
{
|
|
417
|
+
type: "tool_result",
|
|
418
|
+
callId: asString(msg.id, `tc-${Date.now()}`),
|
|
419
|
+
toolName: asString(msg.name, "unknown"),
|
|
420
|
+
output: asString(msg.error, "Tool failed"),
|
|
421
|
+
durationMs: 0,
|
|
422
|
+
isError: true
|
|
423
|
+
}
|
|
424
|
+
];
|
|
425
|
+
}
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
428
|
+
__name(translateToolCallEvent, "translateToolCallEvent");
|
|
429
|
+
function translateStatusEvent(msg) {
|
|
430
|
+
const s = msg.status;
|
|
431
|
+
if (s === "done" || s === "completed") {
|
|
432
|
+
return [
|
|
433
|
+
{
|
|
434
|
+
type: "done",
|
|
435
|
+
result: "",
|
|
436
|
+
usage: {
|
|
437
|
+
inputTokens: 0,
|
|
438
|
+
outputTokens: 0,
|
|
439
|
+
totalTokens: 0
|
|
440
|
+
},
|
|
441
|
+
durationMs: 0,
|
|
442
|
+
cost: 0
|
|
443
|
+
}
|
|
444
|
+
];
|
|
445
|
+
}
|
|
446
|
+
if (s === "error") {
|
|
447
|
+
return [
|
|
448
|
+
{
|
|
449
|
+
type: "error",
|
|
450
|
+
code: "AGENT_ERROR",
|
|
451
|
+
message: asString(msg.error, "Agent error"),
|
|
452
|
+
retryable: false
|
|
453
|
+
}
|
|
454
|
+
];
|
|
455
|
+
}
|
|
456
|
+
return [];
|
|
457
|
+
}
|
|
458
|
+
__name(translateStatusEvent, "translateStatusEvent");
|
|
459
|
+
function translateSdkEvent(msg, runId) {
|
|
460
|
+
switch (msg.type) {
|
|
461
|
+
case "system":
|
|
462
|
+
return translateSystemEvent(msg, runId);
|
|
463
|
+
case "assistant":
|
|
464
|
+
return translateAssistantEvent(msg);
|
|
465
|
+
case "tool_call":
|
|
466
|
+
return translateToolCallEvent(msg);
|
|
467
|
+
case "thinking":
|
|
468
|
+
return [
|
|
469
|
+
{
|
|
470
|
+
type: "thinking",
|
|
471
|
+
content: asString(msg.content, "")
|
|
472
|
+
}
|
|
473
|
+
];
|
|
474
|
+
case "status":
|
|
475
|
+
return translateStatusEvent(msg);
|
|
476
|
+
default:
|
|
477
|
+
return [];
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
__name(translateSdkEvent, "translateSdkEvent");
|
|
481
|
+
|
|
482
|
+
// src/bridge/sdk-adapter.ts
|
|
483
|
+
function createSdkAgentStream(agentWalk, compiledTools, apiKey, envModel) {
|
|
484
|
+
const model = envModel ?? agentWalk.agentConfig.model ?? "openai/gpt-4o-mini";
|
|
485
|
+
return (message, _sessionId) => ({
|
|
374
486
|
async *[Symbol.asyncIterator]() {
|
|
375
487
|
const runId = `run-${Date.now()}`;
|
|
376
488
|
const t0 = Date.now();
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
],
|
|
385
|
-
createdAt: Date.now(),
|
|
386
|
-
totalCostUsd: 0
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
const session = sessions.get(sessionId);
|
|
390
|
-
session.messages.push({
|
|
391
|
-
role: "user",
|
|
392
|
-
content: message
|
|
393
|
-
});
|
|
394
|
-
yield {
|
|
395
|
-
type: "run_started",
|
|
396
|
-
runId,
|
|
397
|
-
agentName: agentWalk.agentConfig.name,
|
|
398
|
-
model
|
|
399
|
-
};
|
|
400
|
-
const maxIter = agentWalk.mainLoop.maxIterations ?? 5;
|
|
401
|
-
let inTok = 0, outTok = 0;
|
|
402
|
-
for (let iter = 1; iter <= maxIter; iter++) {
|
|
489
|
+
let Agent;
|
|
490
|
+
let defineTool;
|
|
491
|
+
try {
|
|
492
|
+
const sdk = await import("@theokit/sdk");
|
|
493
|
+
Agent = sdk.Agent;
|
|
494
|
+
defineTool = sdk.defineTool;
|
|
495
|
+
} catch {
|
|
403
496
|
yield {
|
|
404
|
-
type: "
|
|
405
|
-
|
|
406
|
-
|
|
497
|
+
type: "error",
|
|
498
|
+
code: "SDK_NOT_INSTALLED",
|
|
499
|
+
message: "Install @theokit/sdk: pnpm add @theokit/sdk",
|
|
500
|
+
retryable: false
|
|
407
501
|
};
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
const sdkTools = compiledTools.map((t) => defineTool({
|
|
505
|
+
name: t.name,
|
|
506
|
+
description: t.description,
|
|
507
|
+
inputSchema: t.inputSchema,
|
|
508
|
+
handler: t.handler
|
|
509
|
+
}));
|
|
510
|
+
try {
|
|
511
|
+
const agent = await Agent.create({
|
|
512
|
+
apiKey,
|
|
513
|
+
model: {
|
|
514
|
+
id: model
|
|
413
515
|
},
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
messages: session.messages,
|
|
417
|
-
tools: orTools.length ? orTools : void 0,
|
|
418
|
-
max_tokens: 1e3,
|
|
419
|
-
stream: true
|
|
420
|
-
})
|
|
516
|
+
tools: sdkTools,
|
|
517
|
+
systemPrompt: agentWalk.agentConfig.systemPrompt
|
|
421
518
|
});
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
retryable: res.status === 429
|
|
428
|
-
};
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
const reader = res.body.getReader();
|
|
432
|
-
const dec = new TextDecoder();
|
|
433
|
-
let buf = "";
|
|
434
|
-
let content = "";
|
|
435
|
-
let tcs = [];
|
|
436
|
-
let finish = "";
|
|
437
|
-
while (true) {
|
|
438
|
-
const { done, value } = await reader.read();
|
|
439
|
-
if (done) break;
|
|
440
|
-
buf += dec.decode(value, {
|
|
441
|
-
stream: true
|
|
442
|
-
});
|
|
443
|
-
const lines = buf.split("\n");
|
|
444
|
-
buf = lines.pop() ?? "";
|
|
445
|
-
for (const line of lines) {
|
|
446
|
-
if (!line.startsWith("data: ")) continue;
|
|
447
|
-
const d = line.slice(6).trim();
|
|
448
|
-
if (d === "[DONE]") continue;
|
|
449
|
-
try {
|
|
450
|
-
const c = JSON.parse(d);
|
|
451
|
-
const delta = c.choices?.[0]?.delta;
|
|
452
|
-
if (delta?.content) {
|
|
453
|
-
content += delta.content;
|
|
454
|
-
yield {
|
|
455
|
-
type: "text_delta",
|
|
456
|
-
content: delta.content
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
if (delta?.tool_calls) {
|
|
460
|
-
for (const tc of delta.tool_calls) {
|
|
461
|
-
if (tc.id) tcs[tc.index] = {
|
|
462
|
-
id: tc.id,
|
|
463
|
-
type: "function",
|
|
464
|
-
function: {
|
|
465
|
-
name: tc.function?.name ?? "",
|
|
466
|
-
arguments: ""
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
if (tc.function?.arguments && tcs[tc.index]) tcs[tc.index].function.arguments += tc.function.arguments;
|
|
470
|
-
if (tc.function?.name && tcs[tc.index]) tcs[tc.index].function.name = tc.function.name;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
if (c.choices[0]?.finish_reason) finish = c.choices[0].finish_reason;
|
|
474
|
-
if (c.usage) {
|
|
475
|
-
inTok += c.usage.prompt_tokens;
|
|
476
|
-
outTok += c.usage.completion_tokens;
|
|
477
|
-
if (c.usage.cost) session.totalCostUsd += c.usage.cost;
|
|
478
|
-
}
|
|
479
|
-
} catch {
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
if (finish === "tool_calls" && tcs.length > 0) {
|
|
484
|
-
session.messages.push({
|
|
485
|
-
role: "assistant",
|
|
486
|
-
content: null,
|
|
487
|
-
tool_calls: tcs
|
|
488
|
-
});
|
|
489
|
-
for (const tc of tcs) {
|
|
490
|
-
const orig = nameMap.get(tc.function.name) ?? tc.function.name;
|
|
491
|
-
const tool = toolMap.get(tc.function.name);
|
|
492
|
-
yield {
|
|
493
|
-
type: "tool_call",
|
|
494
|
-
callId: tc.id,
|
|
495
|
-
toolName: orig,
|
|
496
|
-
input: JSON.parse(tc.function.arguments || "{}")
|
|
497
|
-
};
|
|
498
|
-
if (!tool) {
|
|
499
|
-
session.messages.push({
|
|
500
|
-
role: "tool",
|
|
501
|
-
content: "Tool not found",
|
|
502
|
-
tool_call_id: tc.id
|
|
503
|
-
});
|
|
504
|
-
yield {
|
|
505
|
-
type: "tool_result",
|
|
506
|
-
callId: tc.id,
|
|
507
|
-
toolName: orig,
|
|
508
|
-
output: "Not found",
|
|
509
|
-
durationMs: 0,
|
|
510
|
-
isError: true
|
|
511
|
-
};
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
const s = Date.now();
|
|
515
|
-
try {
|
|
516
|
-
const r = await tool.handler(JSON.parse(tc.function.arguments || "{}"));
|
|
517
|
-
session.messages.push({
|
|
518
|
-
role: "tool",
|
|
519
|
-
content: r,
|
|
520
|
-
tool_call_id: tc.id
|
|
521
|
-
});
|
|
522
|
-
yield {
|
|
523
|
-
type: "tool_result",
|
|
524
|
-
callId: tc.id,
|
|
525
|
-
toolName: orig,
|
|
526
|
-
output: r.substring(0, 200),
|
|
527
|
-
durationMs: Date.now() - s,
|
|
528
|
-
isError: false
|
|
529
|
-
};
|
|
530
|
-
} catch (e) {
|
|
531
|
-
const m = e instanceof Error ? e.message : "Failed";
|
|
532
|
-
session.messages.push({
|
|
533
|
-
role: "tool",
|
|
534
|
-
content: `Error: ${m}`,
|
|
535
|
-
tool_call_id: tc.id
|
|
536
|
-
});
|
|
537
|
-
yield {
|
|
538
|
-
type: "tool_result",
|
|
539
|
-
callId: tc.id,
|
|
540
|
-
toolName: orig,
|
|
541
|
-
output: m,
|
|
542
|
-
durationMs: Date.now() - s,
|
|
543
|
-
isError: true
|
|
544
|
-
};
|
|
545
|
-
}
|
|
519
|
+
const run = await agent.send(message);
|
|
520
|
+
for await (const sdkEvent of run.stream()) {
|
|
521
|
+
const translated = translateSdkEvent(sdkEvent, runId);
|
|
522
|
+
for (const event of translated) {
|
|
523
|
+
yield event;
|
|
546
524
|
}
|
|
547
|
-
tcs = [];
|
|
548
|
-
content = "";
|
|
549
|
-
continue;
|
|
550
525
|
}
|
|
551
|
-
if (content) session.messages.push({
|
|
552
|
-
role: "assistant",
|
|
553
|
-
content
|
|
554
|
-
});
|
|
555
526
|
yield {
|
|
556
527
|
type: "done",
|
|
557
|
-
result:
|
|
528
|
+
result: "",
|
|
558
529
|
usage: {
|
|
559
|
-
inputTokens:
|
|
560
|
-
outputTokens:
|
|
561
|
-
totalTokens:
|
|
530
|
+
inputTokens: 0,
|
|
531
|
+
outputTokens: 0,
|
|
532
|
+
totalTokens: 0
|
|
562
533
|
},
|
|
563
534
|
durationMs: Date.now() - t0,
|
|
564
|
-
cost:
|
|
535
|
+
cost: 0
|
|
536
|
+
};
|
|
537
|
+
await agent.dispose();
|
|
538
|
+
} catch (err) {
|
|
539
|
+
yield {
|
|
540
|
+
type: "error",
|
|
541
|
+
code: "SDK_ERROR",
|
|
542
|
+
message: err instanceof Error ? err.message : "SDK agent error",
|
|
543
|
+
retryable: false
|
|
565
544
|
};
|
|
566
|
-
return;
|
|
567
545
|
}
|
|
568
|
-
yield {
|
|
569
|
-
type: "error",
|
|
570
|
-
code: "MAX_ITERATIONS",
|
|
571
|
-
message: `Max iterations (${maxIter})`,
|
|
572
|
-
retryable: false
|
|
573
|
-
};
|
|
574
546
|
}
|
|
575
547
|
});
|
|
576
548
|
}
|
|
577
|
-
__name(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
549
|
+
__name(createSdkAgentStream, "createSdkAgentStream");
|
|
550
|
+
|
|
551
|
+
// src/bridge/agent-orchestrator.ts
|
|
552
|
+
var BudgetExceededError = class extends Error {
|
|
553
|
+
static {
|
|
554
|
+
__name(this, "BudgetExceededError");
|
|
555
|
+
}
|
|
556
|
+
agentName;
|
|
557
|
+
actualCost;
|
|
558
|
+
budgetLimit;
|
|
559
|
+
constructor(agentName, actualCost, budgetLimit) {
|
|
560
|
+
super(`Agent "${agentName}" exceeded budget: $${actualCost.toFixed(4)} > $${budgetLimit.toFixed(4)}`), this.agentName = agentName, this.actualCost = actualCost, this.budgetLimit = budgetLimit;
|
|
561
|
+
this.name = "BudgetExceededError";
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
var DelegationError = class extends Error {
|
|
565
|
+
static {
|
|
566
|
+
__name(this, "DelegationError");
|
|
567
|
+
}
|
|
568
|
+
agentName;
|
|
569
|
+
cause;
|
|
570
|
+
constructor(agentName, cause) {
|
|
571
|
+
super(`Delegation to agent "${agentName}" failed: ${cause instanceof Error ? cause.message : String(cause)}`), this.agentName = agentName, this.cause = cause;
|
|
572
|
+
this.name = "DelegationError";
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
function asString2(value, fallback) {
|
|
576
|
+
if (typeof value === "string") return value;
|
|
577
|
+
return fallback;
|
|
578
|
+
}
|
|
579
|
+
__name(asString2, "asString");
|
|
580
|
+
function asNumber(value, fallback) {
|
|
581
|
+
if (typeof value === "number") return value;
|
|
582
|
+
return fallback;
|
|
583
|
+
}
|
|
584
|
+
__name(asNumber, "asNumber");
|
|
585
|
+
function requireApiKey(opts, agentName) {
|
|
586
|
+
const apiKey = opts.apiKey ?? "";
|
|
587
|
+
if (!apiKey) {
|
|
588
|
+
throw new DelegationError(agentName, "No API key provided. Pass apiKey in DelegateOptions.");
|
|
589
|
+
}
|
|
590
|
+
return apiKey;
|
|
591
|
+
}
|
|
592
|
+
__name(requireApiKey, "requireApiKey");
|
|
593
|
+
function mergeTools(parentTools, subTools) {
|
|
594
|
+
const subToolNames = new Set(subTools.map((t) => t.name));
|
|
595
|
+
const inherited = parentTools.filter((t) => !subToolNames.has(t.name));
|
|
596
|
+
return [
|
|
597
|
+
...inherited,
|
|
598
|
+
...subTools
|
|
599
|
+
];
|
|
600
|
+
}
|
|
601
|
+
__name(mergeTools, "mergeTools");
|
|
602
|
+
function processStreamEvent(event, acc, budget, agentName) {
|
|
603
|
+
if (event.type === "text_delta" && typeof event.content === "string") {
|
|
604
|
+
acc.response += event.content;
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (event.type === "tool_result") {
|
|
608
|
+
acc.toolCalls.push({
|
|
609
|
+
name: asString2(event.toolName, "unknown"),
|
|
610
|
+
input: event.input ?? {},
|
|
611
|
+
output: asString2(event.output, "")
|
|
612
|
+
});
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
if (event.type === "done") {
|
|
616
|
+
acc.cost = asNumber(event.cost, 0);
|
|
617
|
+
const usage = event.usage;
|
|
618
|
+
acc.tokens = usage?.totalTokens ?? 0;
|
|
619
|
+
if (Number.isFinite(budget) && acc.cost > budget) {
|
|
620
|
+
throw new BudgetExceededError(agentName, acc.cost, budget);
|
|
621
|
+
}
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
if (event.type === "error") {
|
|
625
|
+
throw new DelegationError(agentName, asString2(event.message, "Unknown agent error"));
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
__name(processStreamEvent, "processStreamEvent");
|
|
629
|
+
async function delegate(SubAgentClass, message, opts = {}) {
|
|
630
|
+
const apiKey = requireApiKey(opts, SubAgentClass.name);
|
|
631
|
+
const walk = walkAgentMetadata(SubAgentClass, []);
|
|
632
|
+
const toolboxInstances = new Map(walk.toolboxes.map((tb) => [
|
|
633
|
+
tb.class,
|
|
634
|
+
new tb.class()
|
|
635
|
+
]));
|
|
636
|
+
const compiled = compileAgent(walk, toolboxInstances);
|
|
637
|
+
const allTools = mergeTools(opts.parentTools ?? [], compiled.tools);
|
|
638
|
+
const budget = Math.min(opts.budget ?? Infinity, opts.parentBudgetRemaining ?? Infinity);
|
|
639
|
+
const streamFactory = createSdkAgentStream(walk, allTools, apiKey, walk.agentConfig.model);
|
|
640
|
+
const sessionId = opts.sessionId ?? `sub-${crypto.randomUUID()}`;
|
|
641
|
+
const acc = {
|
|
642
|
+
response: "",
|
|
643
|
+
toolCalls: [],
|
|
644
|
+
cost: 0,
|
|
645
|
+
tokens: 0
|
|
582
646
|
};
|
|
583
|
-
|
|
584
|
-
|
|
647
|
+
try {
|
|
648
|
+
for await (const event of streamFactory(message, sessionId)) {
|
|
649
|
+
processStreamEvent(event, acc, budget, SubAgentClass.name);
|
|
650
|
+
}
|
|
651
|
+
} catch (err) {
|
|
652
|
+
if (err instanceof BudgetExceededError || err instanceof DelegationError) throw err;
|
|
653
|
+
throw new DelegationError(SubAgentClass.name, err);
|
|
654
|
+
}
|
|
655
|
+
if (Number.isFinite(budget) && acc.cost > budget) {
|
|
656
|
+
throw new BudgetExceededError(SubAgentClass.name, acc.cost, budget);
|
|
657
|
+
}
|
|
658
|
+
return acc;
|
|
585
659
|
}
|
|
586
|
-
__name(
|
|
660
|
+
__name(delegate, "delegate");
|
|
587
661
|
|
|
588
662
|
// src/manifest/agent-manifest.ts
|
|
589
663
|
function generateAgentManifest(walkResults) {
|
|
@@ -636,7 +710,7 @@ function agentsPlugin(opts) {
|
|
|
636
710
|
name: "@theokit/agents",
|
|
637
711
|
register(app) {
|
|
638
712
|
app.addHook("onRequest", async (pluginCtx) => {
|
|
639
|
-
|
|
713
|
+
routes ??= initRoutes(opts);
|
|
640
714
|
const request = pluginCtx.request;
|
|
641
715
|
const url = new URL(request.url);
|
|
642
716
|
const method = request.method.toUpperCase();
|
|
@@ -669,11 +743,12 @@ function initRoutes(opts) {
|
|
|
669
743
|
allRoutes.push(...agentRoutes);
|
|
670
744
|
}
|
|
671
745
|
validateUniqueRoutes(walkResults);
|
|
672
|
-
return allRoutes;
|
|
746
|
+
return compileRoutePatterns(allRoutes);
|
|
673
747
|
}
|
|
674
748
|
__name(initRoutes, "initRoutes");
|
|
675
749
|
function defaultCreateRun(compiled) {
|
|
676
750
|
return async function* (_message, _sessionId) {
|
|
751
|
+
await Promise.resolve();
|
|
677
752
|
yield {
|
|
678
753
|
type: "run_started",
|
|
679
754
|
runId: `run-${Date.now()}`,
|
|
@@ -688,13 +763,21 @@ function defaultCreateRun(compiled) {
|
|
|
688
763
|
};
|
|
689
764
|
}
|
|
690
765
|
__name(defaultCreateRun, "defaultCreateRun");
|
|
766
|
+
function compileRoutePatterns(routes) {
|
|
767
|
+
return routes.map((r) => {
|
|
768
|
+
if (!r.path.includes(":")) return r;
|
|
769
|
+
const regexSource = r.path.replace(/:[^/]+/g, "[^/]+");
|
|
770
|
+
return {
|
|
771
|
+
...r,
|
|
772
|
+
regex: RegExp(`^${regexSource}$`)
|
|
773
|
+
};
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
__name(compileRoutePatterns, "compileRoutePatterns");
|
|
691
777
|
function matchRoute(routes, method, pathname) {
|
|
692
778
|
return routes.find((r) => {
|
|
693
779
|
if (r.method !== method) return false;
|
|
694
|
-
if (r.
|
|
695
|
-
const pattern = r.path.replace(/:[^/]+/g, "[^/]+");
|
|
696
|
-
return new RegExp(`^${pattern}$`).test(pathname);
|
|
697
|
-
}
|
|
780
|
+
if (r.regex) return r.regex.test(pathname);
|
|
698
781
|
return r.path === pathname;
|
|
699
782
|
});
|
|
700
783
|
}
|
|
@@ -703,6 +786,7 @@ __name(matchRoute, "matchRoute");
|
|
|
703
786
|
export {
|
|
704
787
|
createAgentExecutionContext,
|
|
705
788
|
isAgentContext,
|
|
789
|
+
AgentWarningCode,
|
|
706
790
|
walkAgentMetadata,
|
|
707
791
|
validateUniqueRoutes,
|
|
708
792
|
compileTools,
|
|
@@ -715,8 +799,12 @@ export {
|
|
|
715
799
|
isError,
|
|
716
800
|
isApprovalRequired,
|
|
717
801
|
generateAgentRoutes,
|
|
718
|
-
|
|
802
|
+
translateSdkEvent,
|
|
803
|
+
createSdkAgentStream,
|
|
804
|
+
BudgetExceededError,
|
|
805
|
+
DelegationError,
|
|
806
|
+
delegate,
|
|
719
807
|
generateAgentManifest,
|
|
720
808
|
agentsPlugin
|
|
721
809
|
};
|
|
722
|
-
//# sourceMappingURL=chunk-
|
|
810
|
+
//# sourceMappingURL=chunk-NC5EE7HN.js.map
|