@theokit/sdk 2.20.0 → 2.22.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/CHANGELOG.md +148 -0
- package/dist/a2a/index.cjs +673 -317
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.d.cts +2 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.js +674 -318
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/subagent.d.cts +70 -1
- package/dist/a2a/subagent.d.ts +70 -1
- package/dist/a2a/types.d.cts +7 -0
- package/dist/a2a/types.d.ts +7 -0
- package/dist/agent-builder.d.ts +2 -1
- package/dist/agent-generate.d.ts +12 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +5 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/theokit-client.d.cts +6 -0
- package/dist/client/theokit-client.d.ts +6 -0
- package/dist/client/types.d.cts +2 -0
- package/dist/client/types.d.ts +2 -0
- package/dist/{cron-B8fqui49.d.cts → cron-7CruUd_0.d.ts} +53 -3
- package/dist/{cron-D2yLOrk2.d.ts → cron-Bpt_1khA.d.cts} +53 -3
- package/dist/cron.cjs +654 -389
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +3 -2
- package/dist/cron.d.ts +3 -2
- package/dist/cron.js +655 -390
- package/dist/cron.js.map +1 -1
- package/dist/{errors-5lj1EWgs.d.ts → errors-BuwwkrAk.d.ts} +2 -2
- package/dist/{errors-CE-lMBi2.d.cts → errors-CkCaIqVP.d.cts} +2 -2
- package/dist/errors.d.cts +3 -2
- package/dist/eval.cjs +654 -389
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +654 -389
- package/dist/eval.js.map +1 -1
- package/dist/generate-object.d.ts +4 -3
- package/dist/index.cjs +800 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +259 -17
- package/dist/index.d.ts +259 -17
- package/dist/index.js +798 -394
- package/dist/index.js.map +1 -1
- package/dist/internal/agent-loop/loop-types.d.ts +2 -0
- package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
- package/dist/internal/llm/tool-result-content.d.ts +40 -0
- package/dist/internal/llm/types.d.ts +6 -1
- package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
- package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
- package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
- package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
- package/dist/internal/persistence/session-meta.d.cts +13 -0
- package/dist/internal/persistence/session-meta.d.ts +13 -0
- package/dist/internal/runtime/model-selection.d.ts +14 -0
- package/dist/internal/structured-output-helpers.d.ts +1 -1
- package/dist/permission-engine.d.ts +32 -1
- package/dist/{run-BgfBWX-z.d.cts → run-CrIulPF7.d.cts} +282 -19
- package/dist/{run-BgfBWX-z.d.ts → run-CrIulPF7.d.ts} +282 -19
- package/dist/stream-object.d.ts +2 -1
- package/dist/tool-error.d.ts +30 -0
- package/dist/types/agent-prims.d.ts +30 -8
- package/dist/types/agent.d.ts +13 -2
- package/dist/types/content-blocks.d.ts +47 -0
- package/dist/types/conversation-storage.d.ts +38 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/messages.d.ts +2 -9
- package/dist/types/run-events.d.ts +84 -0
- package/dist/types/run.d.ts +115 -1
- package/dist/types/session.d.ts +99 -0
- package/dist/types/workflow.d.ts +7 -0
- package/dist/workflow.cjs +7 -2
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +2 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +7 -2
- package/dist/workflow.js.map +1 -1
- package/package.json +14 -34
- package/dist/internal/observability/context.d.cts +0 -23
- package/dist/internal/observability/context.d.ts +0 -23
- package/dist/internal/observability/index.cjs +0 -38
- package/dist/internal/observability/index.cjs.map +0 -1
- package/dist/internal/observability/index.d.cts +0 -8
- package/dist/internal/observability/index.d.ts +0 -8
- package/dist/internal/observability/index.js +0 -33
- package/dist/internal/observability/index.js.map +0 -1
- package/dist/internal/plugins/index.cjs +0 -363
- package/dist/internal/plugins/index.cjs.map +0 -1
- package/dist/internal/plugins/index.js +0 -357
- package/dist/internal/plugins/index.js.map +0 -1
- package/dist/internal/workflow/index.d.ts +0 -12
- package/dist/server/adapter/index.d.cts +0 -8
- package/dist/server/adapter/index.d.ts +0 -8
package/dist/eval.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { z, toJSONSchema } from 'zod';
|
|
2
|
+
import { createRequire } from 'module';
|
|
1
3
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
2
4
|
import { mkdir, writeFile, readFile, unlink, open, rename, statfs, stat, rm, readdir, appendFile, access } from 'fs/promises';
|
|
3
5
|
import { join, dirname, resolve, sep, relative, isAbsolute } from 'path';
|
|
4
|
-
import { z, toJSONSchema } from 'zod';
|
|
5
6
|
import { readFileSync, mkdirSync, appendFileSync, readdirSync, existsSync, realpathSync, lstatSync, readlinkSync } from 'fs';
|
|
6
7
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
7
|
-
import { createRequire } from 'module';
|
|
8
8
|
import { homedir } from 'os';
|
|
9
9
|
import { execFile, spawn } from 'child_process';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
@@ -509,6 +509,256 @@ var init_errors = __esm({
|
|
|
509
509
|
};
|
|
510
510
|
}
|
|
511
511
|
});
|
|
512
|
+
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
513
|
+
return toJSONSchema(schema, options);
|
|
514
|
+
}
|
|
515
|
+
var init_to_json_schema = __esm({
|
|
516
|
+
"src/internal/zod/to-json-schema.ts"() {
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
function requireZod() {
|
|
520
|
+
if (cachedZ !== void 0) return cachedZ;
|
|
521
|
+
const r = createRequire(import.meta.url);
|
|
522
|
+
let mod;
|
|
523
|
+
try {
|
|
524
|
+
mod = r("zod");
|
|
525
|
+
} catch (cause) {
|
|
526
|
+
throw new ConfigurationError(
|
|
527
|
+
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
528
|
+
{ code: "zod_not_installed", cause }
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
cachedZ = mod.z ?? mod;
|
|
532
|
+
return cachedZ;
|
|
533
|
+
}
|
|
534
|
+
function makeOutputTool(jsonSchema, onCapture) {
|
|
535
|
+
return {
|
|
536
|
+
name: "output",
|
|
537
|
+
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
538
|
+
inputSchema: jsonSchema,
|
|
539
|
+
handler: (input) => {
|
|
540
|
+
const out = onCapture(input);
|
|
541
|
+
if (typeof out === "string") return out;
|
|
542
|
+
if (out instanceof Promise) return out;
|
|
543
|
+
return "";
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function buildTransientAgentOptions(params) {
|
|
548
|
+
return {
|
|
549
|
+
model: params.model,
|
|
550
|
+
local: params.local,
|
|
551
|
+
tools: [params.outputTool],
|
|
552
|
+
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
553
|
+
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
554
|
+
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function extractUsage(result) {
|
|
558
|
+
const u = result.usage;
|
|
559
|
+
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
560
|
+
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
561
|
+
}
|
|
562
|
+
function buildToolPrompt(prompt) {
|
|
563
|
+
return `${prompt}
|
|
564
|
+
|
|
565
|
+
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
566
|
+
}
|
|
567
|
+
function setupStructuredOutput(schema, maxRetries) {
|
|
568
|
+
const z7 = requireZod();
|
|
569
|
+
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
570
|
+
return {
|
|
571
|
+
z: z7,
|
|
572
|
+
jsonSchema,
|
|
573
|
+
maxRetries: maxRetries ?? 1,
|
|
574
|
+
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
async function disposeAndDeleteTransient(agent, deletor) {
|
|
578
|
+
await agent.dispose();
|
|
579
|
+
try {
|
|
580
|
+
await deletor(agent.agentId);
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
var cachedZ;
|
|
585
|
+
var init_structured_output_helpers = __esm({
|
|
586
|
+
"src/internal/structured-output-helpers.ts"() {
|
|
587
|
+
init_errors();
|
|
588
|
+
init_to_json_schema();
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// src/generate-object.ts
|
|
593
|
+
var generate_object_exports = {};
|
|
594
|
+
__export(generate_object_exports, {
|
|
595
|
+
GenerateObjectError: () => GenerateObjectError,
|
|
596
|
+
generateObjectImpl: () => generateObjectImpl
|
|
597
|
+
});
|
|
598
|
+
function salvagePartial(schema, raw) {
|
|
599
|
+
if (typeof raw !== "object" || raw === null) return raw;
|
|
600
|
+
const shape = schema.shape;
|
|
601
|
+
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
602
|
+
const rawObj = raw;
|
|
603
|
+
const out = {};
|
|
604
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
605
|
+
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
606
|
+
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
607
|
+
if (parsed.success) out[key] = parsed.data;
|
|
608
|
+
}
|
|
609
|
+
return out;
|
|
610
|
+
}
|
|
611
|
+
async function runReasoningPhase(options, deps) {
|
|
612
|
+
const reasoningOptions = {
|
|
613
|
+
model: options.model,
|
|
614
|
+
local: options.local,
|
|
615
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
616
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
617
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
618
|
+
};
|
|
619
|
+
const reasoningAgent = await deps.create(reasoningOptions);
|
|
620
|
+
try {
|
|
621
|
+
const run = await reasoningAgent.send(options.prompt);
|
|
622
|
+
const result = await run.wait();
|
|
623
|
+
const text = result.result;
|
|
624
|
+
return typeof text === "string" ? text : options.prompt;
|
|
625
|
+
} finally {
|
|
626
|
+
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
async function generateObjectImpl(options, deps) {
|
|
630
|
+
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
631
|
+
options.schema,
|
|
632
|
+
options.maxRetries
|
|
633
|
+
);
|
|
634
|
+
let capturedRaw;
|
|
635
|
+
let lastUsage = initialUsage;
|
|
636
|
+
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
637
|
+
class CaptureSentinel extends Error {
|
|
638
|
+
constructor(captured) {
|
|
639
|
+
super("generate-object-capture");
|
|
640
|
+
this.captured = captured;
|
|
641
|
+
}
|
|
642
|
+
captured;
|
|
643
|
+
[sentinel] = true;
|
|
644
|
+
}
|
|
645
|
+
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
646
|
+
if (capturedRaw === void 0) {
|
|
647
|
+
capturedRaw = input;
|
|
648
|
+
}
|
|
649
|
+
throw new CaptureSentinel(input);
|
|
650
|
+
});
|
|
651
|
+
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
652
|
+
const structuringModel = options.structuringModel ?? options.model;
|
|
653
|
+
const structuringPrompt = reasoningText ?? options.prompt;
|
|
654
|
+
const agentOptions = buildTransientAgentOptions({
|
|
655
|
+
model: structuringModel,
|
|
656
|
+
local: options.local,
|
|
657
|
+
outputTool,
|
|
658
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
659
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
660
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
661
|
+
});
|
|
662
|
+
const agent = await deps.create(agentOptions);
|
|
663
|
+
try {
|
|
664
|
+
const userMessage = buildToolPrompt(structuringPrompt);
|
|
665
|
+
let lastParseError;
|
|
666
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
667
|
+
capturedRaw = void 0;
|
|
668
|
+
const run = await agent.send(userMessage);
|
|
669
|
+
const result = await run.wait();
|
|
670
|
+
lastUsage = extractUsage(result);
|
|
671
|
+
if (capturedRaw === void 0) {
|
|
672
|
+
if (result.status === "error" && result.error !== void 0) {
|
|
673
|
+
throw new GenerateObjectError(
|
|
674
|
+
"no_tool_call",
|
|
675
|
+
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
676
|
+
result.error
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
if (attempt === maxRetries) {
|
|
680
|
+
throw new GenerateObjectError(
|
|
681
|
+
"no_tool_call",
|
|
682
|
+
"The model returned text instead of calling the `output` tool."
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
const parsed = options.schema.safeParse(capturedRaw);
|
|
688
|
+
if (parsed.success) {
|
|
689
|
+
return {
|
|
690
|
+
object: parsed.data,
|
|
691
|
+
raw: capturedRaw,
|
|
692
|
+
usage: lastUsage,
|
|
693
|
+
finishReason: "tool_use"
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
lastParseError = parsed.error;
|
|
697
|
+
}
|
|
698
|
+
if (options.errorStrategy === "return-raw") {
|
|
699
|
+
return {
|
|
700
|
+
object: capturedRaw,
|
|
701
|
+
raw: capturedRaw,
|
|
702
|
+
usage: lastUsage,
|
|
703
|
+
finishReason: "tool_use"
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
if (options.errorStrategy === "return-partial") {
|
|
707
|
+
return {
|
|
708
|
+
object: salvagePartial(options.schema, capturedRaw),
|
|
709
|
+
raw: capturedRaw,
|
|
710
|
+
usage: lastUsage,
|
|
711
|
+
finishReason: "tool_use"
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
throw new GenerateObjectError(
|
|
715
|
+
"parse_failed",
|
|
716
|
+
"Schema parse failed after all retries.",
|
|
717
|
+
lastParseError
|
|
718
|
+
);
|
|
719
|
+
} finally {
|
|
720
|
+
await disposeAndDeleteTransient(agent, deps.delete);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
var GenerateObjectError;
|
|
724
|
+
var init_generate_object = __esm({
|
|
725
|
+
"src/generate-object.ts"() {
|
|
726
|
+
init_structured_output_helpers();
|
|
727
|
+
GenerateObjectError = class extends Error {
|
|
728
|
+
name = "GenerateObjectError";
|
|
729
|
+
code;
|
|
730
|
+
cause;
|
|
731
|
+
constructor(code, message, cause) {
|
|
732
|
+
super(message);
|
|
733
|
+
this.code = code;
|
|
734
|
+
if (cause !== void 0) this.cause = cause;
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
741
|
+
var agent_factory_registry_exports = {};
|
|
742
|
+
__export(agent_factory_registry_exports, {
|
|
743
|
+
getAgentFacade: () => getAgentFacade,
|
|
744
|
+
setAgentFacade: () => setAgentFacade
|
|
745
|
+
});
|
|
746
|
+
function setAgentFacade(facade) {
|
|
747
|
+
registered = facade;
|
|
748
|
+
}
|
|
749
|
+
function getAgentFacade() {
|
|
750
|
+
if (registered === void 0) {
|
|
751
|
+
throw new Error(
|
|
752
|
+
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
return registered;
|
|
756
|
+
}
|
|
757
|
+
var registered;
|
|
758
|
+
var init_agent_factory_registry = __esm({
|
|
759
|
+
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
760
|
+
}
|
|
761
|
+
});
|
|
512
762
|
|
|
513
763
|
// src/internal/persistence/cwd-mutex.ts
|
|
514
764
|
function withCwdMutex(key, fn) {
|
|
@@ -1426,29 +1676,6 @@ var init_judge_call = __esm({
|
|
|
1426
1676
|
}
|
|
1427
1677
|
});
|
|
1428
1678
|
|
|
1429
|
-
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
1430
|
-
var agent_factory_registry_exports = {};
|
|
1431
|
-
__export(agent_factory_registry_exports, {
|
|
1432
|
-
getAgentFacade: () => getAgentFacade,
|
|
1433
|
-
setAgentFacade: () => setAgentFacade
|
|
1434
|
-
});
|
|
1435
|
-
function setAgentFacade(facade) {
|
|
1436
|
-
registered3 = facade;
|
|
1437
|
-
}
|
|
1438
|
-
function getAgentFacade() {
|
|
1439
|
-
if (registered3 === void 0) {
|
|
1440
|
-
throw new Error(
|
|
1441
|
-
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1444
|
-
return registered3;
|
|
1445
|
-
}
|
|
1446
|
-
var registered3;
|
|
1447
|
-
var init_agent_factory_registry = __esm({
|
|
1448
|
-
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
1449
|
-
}
|
|
1450
|
-
});
|
|
1451
|
-
|
|
1452
1679
|
// src/internal/runtime/lifecycle/run-to-completion.ts
|
|
1453
1680
|
var run_to_completion_exports = {};
|
|
1454
1681
|
__export(run_to_completion_exports, {
|
|
@@ -1613,14 +1840,14 @@ async function forkAgentImpl(parent, options, deps) {
|
|
|
1613
1840
|
return {
|
|
1614
1841
|
result: result.result,
|
|
1615
1842
|
toolCalls: [],
|
|
1616
|
-
usage:
|
|
1843
|
+
usage: extractUsage2(result)
|
|
1617
1844
|
};
|
|
1618
1845
|
});
|
|
1619
1846
|
} finally {
|
|
1620
1847
|
await fork.dispose();
|
|
1621
1848
|
}
|
|
1622
1849
|
}
|
|
1623
|
-
function
|
|
1850
|
+
function extractUsage2(result) {
|
|
1624
1851
|
if (typeof result !== "object" || result === null) {
|
|
1625
1852
|
return { inputTokens: 0, outputTokens: 0 };
|
|
1626
1853
|
}
|
|
@@ -2056,342 +2283,115 @@ async function runWorkAndFinalize(taskId, aborter, work) {
|
|
|
2056
2283
|
type: "progress",
|
|
2057
2284
|
taskId,
|
|
2058
2285
|
at: Date.now(),
|
|
2059
|
-
payload
|
|
2060
|
-
});
|
|
2061
|
-
}
|
|
2062
|
-
};
|
|
2063
|
-
try {
|
|
2064
|
-
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2065
|
-
if (aborter.signal.aborted) {
|
|
2066
|
-
const cancelledAt = Date.now();
|
|
2067
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2068
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2069
|
-
return;
|
|
2070
|
-
}
|
|
2071
|
-
const finishedAt = Date.now();
|
|
2072
|
-
await transition(taskId, "finished", { finishedAt, result });
|
|
2073
|
-
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2074
|
-
} catch (err) {
|
|
2075
|
-
if (aborter.signal.aborted) {
|
|
2076
|
-
const cancelledAt = Date.now();
|
|
2077
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2078
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2079
|
-
return;
|
|
2080
|
-
}
|
|
2081
|
-
const erroredAt = Date.now();
|
|
2082
|
-
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2083
|
-
await transition(taskId, "error", { erroredAt, error });
|
|
2084
|
-
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2088
|
-
if (aborter.signal.aborted) return;
|
|
2089
|
-
try {
|
|
2090
|
-
const handle = await state.store.get(taskId);
|
|
2091
|
-
if (handle?.cancelRequested === true) {
|
|
2092
|
-
aborter.abort("cancelRequested");
|
|
2093
|
-
}
|
|
2094
|
-
} catch {
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
async function acquireSlot() {
|
|
2098
|
-
if (reentryAls.getStore() === true) {
|
|
2099
|
-
return () => {
|
|
2100
|
-
};
|
|
2101
|
-
}
|
|
2102
|
-
return state.semaphore.acquire();
|
|
2103
|
-
}
|
|
2104
|
-
async function submit(internal) {
|
|
2105
|
-
state.firstSubmitSeen = true;
|
|
2106
|
-
startEvictTimerIfNeeded();
|
|
2107
|
-
const resolvedId = resolveIdInternal(internal);
|
|
2108
|
-
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2109
|
-
const existing = await state.store.get(resolvedId);
|
|
2110
|
-
if (existing !== void 0) {
|
|
2111
|
-
submitSpan.end();
|
|
2112
|
-
return existing;
|
|
2113
|
-
}
|
|
2114
|
-
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2115
|
-
submitSpan.end();
|
|
2116
|
-
if (internal.signal?.aborted === true) {
|
|
2117
|
-
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2118
|
-
}
|
|
2119
|
-
const aborter = new AbortController();
|
|
2120
|
-
state.aborters.set(resolvedId, aborter);
|
|
2121
|
-
if (internal.signal !== void 0) {
|
|
2122
|
-
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2123
|
-
once: true
|
|
2124
|
-
});
|
|
2125
|
-
}
|
|
2126
|
-
const release = await acquireSlot();
|
|
2127
|
-
void (async () => {
|
|
2128
|
-
try {
|
|
2129
|
-
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2130
|
-
if (aborter.signal.aborted) {
|
|
2131
|
-
const cancelledAt = Date.now();
|
|
2132
|
-
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2133
|
-
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2134
|
-
return;
|
|
2135
|
-
}
|
|
2136
|
-
const startedAt = Date.now();
|
|
2137
|
-
await transition(resolvedId, "running", { startedAt });
|
|
2138
|
-
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2139
|
-
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2140
|
-
} finally {
|
|
2141
|
-
release();
|
|
2142
|
-
state.aborters.delete(resolvedId);
|
|
2143
|
-
}
|
|
2144
|
-
})();
|
|
2145
|
-
return queuedHandle;
|
|
2146
|
-
}
|
|
2147
|
-
async function get(id) {
|
|
2148
|
-
if (!isValidTaskId(id, true)) return void 0;
|
|
2149
|
-
return state.store.get(id);
|
|
2150
|
-
}
|
|
2151
|
-
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2152
|
-
var init_registry = __esm({
|
|
2153
|
-
"src/internal/task/registry.ts"() {
|
|
2154
|
-
init_errors();
|
|
2155
|
-
init_task();
|
|
2156
|
-
init_async_semaphore();
|
|
2157
|
-
init_ring_buffer();
|
|
2158
|
-
init_store();
|
|
2159
|
-
init_subscribe();
|
|
2160
|
-
init_telemetry();
|
|
2161
|
-
DEFAULT_CONCURRENCY = 8;
|
|
2162
|
-
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2163
|
-
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2164
|
-
RING_CAP = 64;
|
|
2165
|
-
reentryAls = new AsyncLocalStorage();
|
|
2166
|
-
state = buildState({});
|
|
2167
|
-
}
|
|
2168
|
-
});
|
|
2169
|
-
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
2170
|
-
return toJSONSchema(schema, options);
|
|
2171
|
-
}
|
|
2172
|
-
var init_to_json_schema = __esm({
|
|
2173
|
-
"src/internal/zod/to-json-schema.ts"() {
|
|
2174
|
-
}
|
|
2175
|
-
});
|
|
2176
|
-
function requireZod() {
|
|
2177
|
-
if (cachedZ !== void 0) return cachedZ;
|
|
2178
|
-
const r = createRequire(import.meta.url);
|
|
2179
|
-
let mod;
|
|
2180
|
-
try {
|
|
2181
|
-
mod = r("zod");
|
|
2182
|
-
} catch (cause) {
|
|
2183
|
-
throw new ConfigurationError(
|
|
2184
|
-
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
2185
|
-
{ code: "zod_not_installed", cause }
|
|
2186
|
-
);
|
|
2187
|
-
}
|
|
2188
|
-
cachedZ = mod.z ?? mod;
|
|
2189
|
-
return cachedZ;
|
|
2190
|
-
}
|
|
2191
|
-
function makeOutputTool(jsonSchema, onCapture) {
|
|
2192
|
-
return {
|
|
2193
|
-
name: "output",
|
|
2194
|
-
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
2195
|
-
inputSchema: jsonSchema,
|
|
2196
|
-
handler: (input) => {
|
|
2197
|
-
const out = onCapture(input);
|
|
2198
|
-
if (typeof out === "string") return out;
|
|
2199
|
-
if (out instanceof Promise) return out;
|
|
2200
|
-
return "";
|
|
2201
|
-
}
|
|
2202
|
-
};
|
|
2203
|
-
}
|
|
2204
|
-
function buildTransientAgentOptions(params) {
|
|
2205
|
-
return {
|
|
2206
|
-
model: params.model,
|
|
2207
|
-
local: params.local,
|
|
2208
|
-
tools: [params.outputTool],
|
|
2209
|
-
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
2210
|
-
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
2211
|
-
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
2212
|
-
};
|
|
2213
|
-
}
|
|
2214
|
-
function extractUsage2(result) {
|
|
2215
|
-
const u = result.usage;
|
|
2216
|
-
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
2217
|
-
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
2218
|
-
}
|
|
2219
|
-
function buildToolPrompt(prompt) {
|
|
2220
|
-
return `${prompt}
|
|
2221
|
-
|
|
2222
|
-
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
2223
|
-
}
|
|
2224
|
-
function setupStructuredOutput(schema, maxRetries) {
|
|
2225
|
-
const z7 = requireZod();
|
|
2226
|
-
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
2227
|
-
return {
|
|
2228
|
-
z: z7,
|
|
2229
|
-
jsonSchema,
|
|
2230
|
-
maxRetries: maxRetries ?? 1,
|
|
2231
|
-
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
2232
|
-
};
|
|
2233
|
-
}
|
|
2234
|
-
async function disposeAndDeleteTransient(agent, deletor) {
|
|
2235
|
-
await agent.dispose();
|
|
2236
|
-
try {
|
|
2237
|
-
await deletor(agent.agentId);
|
|
2238
|
-
} catch {
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
|
-
var cachedZ;
|
|
2242
|
-
var init_structured_output_helpers = __esm({
|
|
2243
|
-
"src/internal/structured-output-helpers.ts"() {
|
|
2244
|
-
init_errors();
|
|
2245
|
-
init_to_json_schema();
|
|
2246
|
-
}
|
|
2247
|
-
});
|
|
2248
|
-
|
|
2249
|
-
// src/generate-object.ts
|
|
2250
|
-
var generate_object_exports = {};
|
|
2251
|
-
__export(generate_object_exports, {
|
|
2252
|
-
GenerateObjectError: () => GenerateObjectError,
|
|
2253
|
-
generateObjectImpl: () => generateObjectImpl
|
|
2254
|
-
});
|
|
2255
|
-
function salvagePartial(schema, raw) {
|
|
2256
|
-
if (typeof raw !== "object" || raw === null) return raw;
|
|
2257
|
-
const shape = schema.shape;
|
|
2258
|
-
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
2259
|
-
const rawObj = raw;
|
|
2260
|
-
const out = {};
|
|
2261
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
2262
|
-
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
2263
|
-
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
2264
|
-
if (parsed.success) out[key] = parsed.data;
|
|
2265
|
-
}
|
|
2266
|
-
return out;
|
|
2267
|
-
}
|
|
2268
|
-
async function runReasoningPhase(options, deps) {
|
|
2269
|
-
const reasoningOptions = {
|
|
2270
|
-
model: options.model,
|
|
2271
|
-
local: options.local,
|
|
2272
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2273
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2274
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2275
|
-
};
|
|
2276
|
-
const reasoningAgent = await deps.create(reasoningOptions);
|
|
2277
|
-
try {
|
|
2278
|
-
const run = await reasoningAgent.send(options.prompt);
|
|
2279
|
-
const result = await run.wait();
|
|
2280
|
-
const text = result.result;
|
|
2281
|
-
return typeof text === "string" ? text : options.prompt;
|
|
2282
|
-
} finally {
|
|
2283
|
-
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
2284
|
-
}
|
|
2285
|
-
}
|
|
2286
|
-
async function generateObjectImpl(options, deps) {
|
|
2287
|
-
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
2288
|
-
options.schema,
|
|
2289
|
-
options.maxRetries
|
|
2290
|
-
);
|
|
2291
|
-
let capturedRaw;
|
|
2292
|
-
let lastUsage = initialUsage;
|
|
2293
|
-
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
2294
|
-
class CaptureSentinel extends Error {
|
|
2295
|
-
constructor(captured) {
|
|
2296
|
-
super("generate-object-capture");
|
|
2297
|
-
this.captured = captured;
|
|
2298
|
-
}
|
|
2299
|
-
captured;
|
|
2300
|
-
[sentinel] = true;
|
|
2301
|
-
}
|
|
2302
|
-
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
2303
|
-
if (capturedRaw === void 0) {
|
|
2304
|
-
capturedRaw = input;
|
|
2305
|
-
}
|
|
2306
|
-
throw new CaptureSentinel(input);
|
|
2307
|
-
});
|
|
2308
|
-
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
2309
|
-
const structuringModel = options.structuringModel ?? options.model;
|
|
2310
|
-
const structuringPrompt = reasoningText ?? options.prompt;
|
|
2311
|
-
const agentOptions = buildTransientAgentOptions({
|
|
2312
|
-
model: structuringModel,
|
|
2313
|
-
local: options.local,
|
|
2314
|
-
outputTool,
|
|
2315
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2316
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2317
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2318
|
-
});
|
|
2319
|
-
const agent = await deps.create(agentOptions);
|
|
2286
|
+
payload
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
};
|
|
2320
2290
|
try {
|
|
2321
|
-
const
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
lastUsage = extractUsage2(result);
|
|
2328
|
-
if (capturedRaw === void 0) {
|
|
2329
|
-
if (result.status === "error" && result.error !== void 0) {
|
|
2330
|
-
throw new GenerateObjectError(
|
|
2331
|
-
"no_tool_call",
|
|
2332
|
-
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
2333
|
-
result.error
|
|
2334
|
-
);
|
|
2335
|
-
}
|
|
2336
|
-
if (attempt === maxRetries) {
|
|
2337
|
-
throw new GenerateObjectError(
|
|
2338
|
-
"no_tool_call",
|
|
2339
|
-
"The model returned text instead of calling the `output` tool."
|
|
2340
|
-
);
|
|
2341
|
-
}
|
|
2342
|
-
continue;
|
|
2343
|
-
}
|
|
2344
|
-
const parsed = options.schema.safeParse(capturedRaw);
|
|
2345
|
-
if (parsed.success) {
|
|
2346
|
-
return {
|
|
2347
|
-
object: parsed.data,
|
|
2348
|
-
raw: capturedRaw,
|
|
2349
|
-
usage: lastUsage,
|
|
2350
|
-
finishReason: "tool_use"
|
|
2351
|
-
};
|
|
2352
|
-
}
|
|
2353
|
-
lastParseError = parsed.error;
|
|
2291
|
+
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2292
|
+
if (aborter.signal.aborted) {
|
|
2293
|
+
const cancelledAt = Date.now();
|
|
2294
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2295
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2296
|
+
return;
|
|
2354
2297
|
}
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
};
|
|
2298
|
+
const finishedAt = Date.now();
|
|
2299
|
+
await transition(taskId, "finished", { finishedAt, result });
|
|
2300
|
+
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2301
|
+
} catch (err) {
|
|
2302
|
+
if (aborter.signal.aborted) {
|
|
2303
|
+
const cancelledAt = Date.now();
|
|
2304
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2305
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2306
|
+
return;
|
|
2362
2307
|
}
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2308
|
+
const erroredAt = Date.now();
|
|
2309
|
+
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2310
|
+
await transition(taskId, "error", { erroredAt, error });
|
|
2311
|
+
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2315
|
+
if (aborter.signal.aborted) return;
|
|
2316
|
+
try {
|
|
2317
|
+
const handle = await state.store.get(taskId);
|
|
2318
|
+
if (handle?.cancelRequested === true) {
|
|
2319
|
+
aborter.abort("cancelRequested");
|
|
2370
2320
|
}
|
|
2371
|
-
|
|
2372
|
-
"parse_failed",
|
|
2373
|
-
"Schema parse failed after all retries.",
|
|
2374
|
-
lastParseError
|
|
2375
|
-
);
|
|
2376
|
-
} finally {
|
|
2377
|
-
await disposeAndDeleteTransient(agent, deps.delete);
|
|
2321
|
+
} catch {
|
|
2378
2322
|
}
|
|
2379
2323
|
}
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
init_structured_output_helpers();
|
|
2384
|
-
GenerateObjectError = class extends Error {
|
|
2385
|
-
name = "GenerateObjectError";
|
|
2386
|
-
code;
|
|
2387
|
-
cause;
|
|
2388
|
-
constructor(code, message, cause) {
|
|
2389
|
-
super(message);
|
|
2390
|
-
this.code = code;
|
|
2391
|
-
if (cause !== void 0) this.cause = cause;
|
|
2392
|
-
}
|
|
2324
|
+
async function acquireSlot() {
|
|
2325
|
+
if (reentryAls.getStore() === true) {
|
|
2326
|
+
return () => {
|
|
2393
2327
|
};
|
|
2394
2328
|
}
|
|
2329
|
+
return state.semaphore.acquire();
|
|
2330
|
+
}
|
|
2331
|
+
async function submit(internal) {
|
|
2332
|
+
state.firstSubmitSeen = true;
|
|
2333
|
+
startEvictTimerIfNeeded();
|
|
2334
|
+
const resolvedId = resolveIdInternal(internal);
|
|
2335
|
+
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2336
|
+
const existing = await state.store.get(resolvedId);
|
|
2337
|
+
if (existing !== void 0) {
|
|
2338
|
+
submitSpan.end();
|
|
2339
|
+
return existing;
|
|
2340
|
+
}
|
|
2341
|
+
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2342
|
+
submitSpan.end();
|
|
2343
|
+
if (internal.signal?.aborted === true) {
|
|
2344
|
+
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2345
|
+
}
|
|
2346
|
+
const aborter = new AbortController();
|
|
2347
|
+
state.aborters.set(resolvedId, aborter);
|
|
2348
|
+
if (internal.signal !== void 0) {
|
|
2349
|
+
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2350
|
+
once: true
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
const release = await acquireSlot();
|
|
2354
|
+
void (async () => {
|
|
2355
|
+
try {
|
|
2356
|
+
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2357
|
+
if (aborter.signal.aborted) {
|
|
2358
|
+
const cancelledAt = Date.now();
|
|
2359
|
+
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2360
|
+
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2363
|
+
const startedAt = Date.now();
|
|
2364
|
+
await transition(resolvedId, "running", { startedAt });
|
|
2365
|
+
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2366
|
+
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2367
|
+
} finally {
|
|
2368
|
+
release();
|
|
2369
|
+
state.aborters.delete(resolvedId);
|
|
2370
|
+
}
|
|
2371
|
+
})();
|
|
2372
|
+
return queuedHandle;
|
|
2373
|
+
}
|
|
2374
|
+
async function get(id) {
|
|
2375
|
+
if (!isValidTaskId(id, true)) return void 0;
|
|
2376
|
+
return state.store.get(id);
|
|
2377
|
+
}
|
|
2378
|
+
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2379
|
+
var init_registry = __esm({
|
|
2380
|
+
"src/internal/task/registry.ts"() {
|
|
2381
|
+
init_errors();
|
|
2382
|
+
init_task();
|
|
2383
|
+
init_async_semaphore();
|
|
2384
|
+
init_ring_buffer();
|
|
2385
|
+
init_store();
|
|
2386
|
+
init_subscribe();
|
|
2387
|
+
init_telemetry();
|
|
2388
|
+
DEFAULT_CONCURRENCY = 8;
|
|
2389
|
+
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2390
|
+
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2391
|
+
RING_CAP = 64;
|
|
2392
|
+
reentryAls = new AsyncLocalStorage();
|
|
2393
|
+
state = buildState({});
|
|
2394
|
+
}
|
|
2395
2395
|
});
|
|
2396
2396
|
|
|
2397
2397
|
// src/stream-object.ts
|
|
@@ -2448,7 +2448,7 @@ async function* streamObjectImpl(options, deps) {
|
|
|
2448
2448
|
}
|
|
2449
2449
|
}
|
|
2450
2450
|
const result = await run.wait();
|
|
2451
|
-
lastUsage =
|
|
2451
|
+
lastUsage = extractUsage(result);
|
|
2452
2452
|
if (capturedRaw === void 0) {
|
|
2453
2453
|
if (result.status === "error" && result.error !== void 0) {
|
|
2454
2454
|
throw new StreamObjectError(
|
|
@@ -2794,6 +2794,7 @@ var AgentBuilder = class {
|
|
|
2794
2794
|
constructor(deps) {
|
|
2795
2795
|
this.deps = deps;
|
|
2796
2796
|
}
|
|
2797
|
+
/** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
|
|
2797
2798
|
model(m) {
|
|
2798
2799
|
this.opts.model = m;
|
|
2799
2800
|
return this;
|
|
@@ -3143,6 +3144,69 @@ function isLocalAgentId(id) {
|
|
|
3143
3144
|
return id.startsWith(PREFIX.localAgent);
|
|
3144
3145
|
}
|
|
3145
3146
|
|
|
3147
|
+
// src/internal/runtime/config/default-model.ts
|
|
3148
|
+
var DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
|
|
3149
|
+
|
|
3150
|
+
// src/agent-generate.ts
|
|
3151
|
+
async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
|
|
3152
|
+
const { output, maxRetries, errorStrategy, ...sendOptions } = options;
|
|
3153
|
+
const run = await agent.send(input, sendOptions);
|
|
3154
|
+
const result = await run.wait();
|
|
3155
|
+
const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
|
|
3156
|
+
const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
|
|
3157
|
+
const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
|
|
3158
|
+
const facade = getAgentFacade2();
|
|
3159
|
+
const structured = await generateObjectImpl2(
|
|
3160
|
+
{
|
|
3161
|
+
prompt: answer,
|
|
3162
|
+
schema: output,
|
|
3163
|
+
// `agentModel` arrives already normalized (`this.model` passed through
|
|
3164
|
+
// `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
|
|
3165
|
+
// `string | ModelSelection` field only ever receives a `ModelSelection` here.
|
|
3166
|
+
model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
|
|
3167
|
+
// `local` is required to keep the transient structuring agent local-only;
|
|
3168
|
+
// default to the process cwd when the agent had no explicit local config.
|
|
3169
|
+
local: agentLocal ?? { cwd: process.cwd() },
|
|
3170
|
+
...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
|
|
3171
|
+
...maxRetries !== void 0 ? { maxRetries } : {},
|
|
3172
|
+
...errorStrategy !== void 0 ? { errorStrategy } : {}
|
|
3173
|
+
},
|
|
3174
|
+
{
|
|
3175
|
+
create: (opts) => facade.create(opts),
|
|
3176
|
+
delete: (agentId) => facade.delete(agentId)
|
|
3177
|
+
}
|
|
3178
|
+
);
|
|
3179
|
+
return {
|
|
3180
|
+
object: structured.object,
|
|
3181
|
+
result,
|
|
3182
|
+
raw: structured.raw,
|
|
3183
|
+
usage: structured.usage
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
function structurableAnswerOrThrow(result, GenerateObjectError2) {
|
|
3187
|
+
if (result.status === "error") {
|
|
3188
|
+
throw new GenerateObjectError2(
|
|
3189
|
+
"no_tool_call",
|
|
3190
|
+
`Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
|
|
3191
|
+
result.error
|
|
3192
|
+
);
|
|
3193
|
+
}
|
|
3194
|
+
if (result.status === "cancelled") {
|
|
3195
|
+
throw new GenerateObjectError2(
|
|
3196
|
+
"no_tool_call",
|
|
3197
|
+
"Agent run was cancelled before an answer could be structured."
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
const answer = result.result;
|
|
3201
|
+
if (answer === void 0 || answer.length === 0) {
|
|
3202
|
+
throw new GenerateObjectError2(
|
|
3203
|
+
"no_tool_call",
|
|
3204
|
+
"The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
|
|
3205
|
+
);
|
|
3206
|
+
}
|
|
3207
|
+
return answer;
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3146
3210
|
// src/internal/runtime/cloud/cloud-agent.ts
|
|
3147
3211
|
init_errors();
|
|
3148
3212
|
init_cwd_mutex();
|
|
@@ -3293,8 +3357,19 @@ function safeFilenameForId(id, options) {
|
|
|
3293
3357
|
return `h-${createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
|
|
3294
3358
|
}
|
|
3295
3359
|
|
|
3296
|
-
// src/internal/runtime/
|
|
3297
|
-
|
|
3360
|
+
// src/internal/runtime/model-selection.ts
|
|
3361
|
+
init_errors();
|
|
3362
|
+
function normalizeModel(m) {
|
|
3363
|
+
if (m === void 0 || typeof m !== "string") return m;
|
|
3364
|
+
const id = m.trim();
|
|
3365
|
+
if (id.length === 0) {
|
|
3366
|
+
throw new ConfigurationError(
|
|
3367
|
+
'model must be a non-empty "provider/model" id string or a ModelSelection object',
|
|
3368
|
+
{ code: "invalid_model_selection" }
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
return { id };
|
|
3372
|
+
}
|
|
3298
3373
|
|
|
3299
3374
|
// src/internal/runtime/registry/agent-registry-store.ts
|
|
3300
3375
|
init_cwd_mutex();
|
|
@@ -3371,7 +3446,10 @@ var REGISTRY_RELATIVE_PATH = join(".theokit", "agents", "registry.json");
|
|
|
3371
3446
|
function stripSecretsFromOptions(options) {
|
|
3372
3447
|
return assignDefined({
|
|
3373
3448
|
name: options.name,
|
|
3374
|
-
model:
|
|
3449
|
+
model: (() => {
|
|
3450
|
+
const m = normalizeModel(options.model);
|
|
3451
|
+
return m !== void 0 ? { id: m.id } : void 0;
|
|
3452
|
+
})(),
|
|
3375
3453
|
systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
|
|
3376
3454
|
local: serializeLocal(options.local),
|
|
3377
3455
|
cloud: serializeCloud(options.cloud),
|
|
@@ -3656,7 +3734,8 @@ function serializeCloudAgentConfig(options) {
|
|
|
3656
3734
|
cloud: serializeCloud2(options.cloud)
|
|
3657
3735
|
};
|
|
3658
3736
|
if (typeof options.agentId === "string") payload.agentId = options.agentId;
|
|
3659
|
-
|
|
3737
|
+
const cfgModel = normalizeModel(options.model);
|
|
3738
|
+
if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
|
|
3660
3739
|
if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
|
|
3661
3740
|
const skills = serializeSkills(options.skills);
|
|
3662
3741
|
if (skills !== void 0) payload.skills = skills;
|
|
@@ -4552,6 +4631,7 @@ function applyScriptMetrics(base, script) {
|
|
|
4552
4631
|
if (script.cost !== void 0) base.cost = script.cost;
|
|
4553
4632
|
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
4554
4633
|
if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
|
|
4634
|
+
if (script.origin !== void 0) base.origin = script.origin;
|
|
4555
4635
|
}
|
|
4556
4636
|
|
|
4557
4637
|
// src/internal/runtime/cloud/cloud-run.ts
|
|
@@ -4907,7 +4987,7 @@ var CloudAgent = class {
|
|
|
4907
4987
|
disposed = false;
|
|
4908
4988
|
constructor(options, providedAgentId) {
|
|
4909
4989
|
this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
|
|
4910
|
-
this.model = options.model;
|
|
4990
|
+
this.model = normalizeModel(options.model);
|
|
4911
4991
|
this.options = options;
|
|
4912
4992
|
this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
|
|
4913
4993
|
const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
|
|
@@ -4937,6 +5017,17 @@ var CloudAgent = class {
|
|
|
4937
5017
|
const apiKey = resolveApiKey(this.options.apiKey);
|
|
4938
5018
|
return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
|
|
4939
5019
|
}
|
|
5020
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
5021
|
+
generate(message, options) {
|
|
5022
|
+
return agentGenerate(
|
|
5023
|
+
this,
|
|
5024
|
+
this.model,
|
|
5025
|
+
this.options.apiKey,
|
|
5026
|
+
this.options.local,
|
|
5027
|
+
message,
|
|
5028
|
+
options
|
|
5029
|
+
);
|
|
5030
|
+
}
|
|
4940
5031
|
async send(message, options = {}) {
|
|
4941
5032
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
4942
5033
|
throw new ConfigurationError(
|
|
@@ -4967,7 +5058,7 @@ var CloudAgent = class {
|
|
|
4967
5058
|
});
|
|
4968
5059
|
}
|
|
4969
5060
|
async sendLocked(message, options) {
|
|
4970
|
-
const overrideModel = options.model;
|
|
5061
|
+
const overrideModel = normalizeModel(options.model);
|
|
4971
5062
|
if (overrideModel !== void 0) {
|
|
4972
5063
|
this.model = overrideModel;
|
|
4973
5064
|
updateRegisteredAgent(this.agentId, { model: overrideModel });
|
|
@@ -5881,18 +5972,18 @@ var ALL_ADAPTERS = [
|
|
|
5881
5972
|
arizeAdapter,
|
|
5882
5973
|
braintrustAdapter
|
|
5883
5974
|
];
|
|
5884
|
-
var
|
|
5975
|
+
var registered2 = /* @__PURE__ */ new Set();
|
|
5885
5976
|
function tryAutoRegisterAdapters(settings) {
|
|
5886
5977
|
if (settings?.enabled !== true) return;
|
|
5887
5978
|
if (settings.autoDetect === false) return;
|
|
5888
5979
|
const disabled = new Set(settings.disable ?? []);
|
|
5889
5980
|
for (const adapter of ALL_ADAPTERS) {
|
|
5890
|
-
if (
|
|
5981
|
+
if (registered2.has(adapter.moduleName)) continue;
|
|
5891
5982
|
if (disabled.has(adapter.displayName.toLowerCase())) continue;
|
|
5892
5983
|
if (!adapter.detect()) continue;
|
|
5893
5984
|
try {
|
|
5894
5985
|
adapter.register();
|
|
5895
|
-
|
|
5986
|
+
registered2.add(adapter.moduleName);
|
|
5896
5987
|
process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
|
|
5897
5988
|
`);
|
|
5898
5989
|
} catch (cause) {
|
|
@@ -6455,6 +6546,26 @@ function paginate(items, opts) {
|
|
|
6455
6546
|
return items.slice(start, end);
|
|
6456
6547
|
}
|
|
6457
6548
|
|
|
6549
|
+
// src/internal/persistence/session-meta.ts
|
|
6550
|
+
function applyMetaPatch(current, patch) {
|
|
6551
|
+
const next = {};
|
|
6552
|
+
if (current.title !== void 0) next.title = current.title;
|
|
6553
|
+
if (current.tag !== void 0) next.tag = current.tag;
|
|
6554
|
+
if (patch.title === null) delete next.title;
|
|
6555
|
+
else if (patch.title !== void 0) next.title = patch.title;
|
|
6556
|
+
if (patch.tag === null) delete next.tag;
|
|
6557
|
+
else if (patch.tag !== void 0) next.tag = patch.tag;
|
|
6558
|
+
return next;
|
|
6559
|
+
}
|
|
6560
|
+
function coerceSessionMeta(raw) {
|
|
6561
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
6562
|
+
const obj = raw;
|
|
6563
|
+
const meta = {};
|
|
6564
|
+
if (typeof obj.title === "string") meta.title = obj.title;
|
|
6565
|
+
if (typeof obj.tag === "string") meta.tag = obj.tag;
|
|
6566
|
+
return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
|
|
6567
|
+
}
|
|
6568
|
+
|
|
6458
6569
|
// src/internal/persistence/conversation-storage-fs.ts
|
|
6459
6570
|
var FileSystemConversationStorage = class {
|
|
6460
6571
|
#root;
|
|
@@ -6505,6 +6616,37 @@ var FileSystemConversationStorage = class {
|
|
|
6505
6616
|
async compact(conversationId, maxTurns) {
|
|
6506
6617
|
await compactSessionFile(this.#root, conversationId, maxTurns);
|
|
6507
6618
|
}
|
|
6619
|
+
// SE4 — session metadata persisted as a per-conversation sidecar
|
|
6620
|
+
// `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
|
|
6621
|
+
// the transcript). Kept separate from messages.jsonl so a title/tag write does
|
|
6622
|
+
// not rewrite the append-only log.
|
|
6623
|
+
#metaPath(conversationId) {
|
|
6624
|
+
const safe3 = sanitizeIdentifier(conversationId, { maxLen: 128 });
|
|
6625
|
+
return safePathJoin(this.#root, ".theokit", "agents", safe3, "session.json");
|
|
6626
|
+
}
|
|
6627
|
+
async getSessionMeta(conversationId) {
|
|
6628
|
+
try {
|
|
6629
|
+
const raw = await readFile(this.#metaPath(conversationId), "utf8");
|
|
6630
|
+
return coerceSessionMeta(JSON.parse(raw));
|
|
6631
|
+
} catch (cause) {
|
|
6632
|
+
if (cause.code === "ENOENT") return void 0;
|
|
6633
|
+
throw cause;
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
async setSessionMeta(conversationId, patch) {
|
|
6637
|
+
const metaPath = this.#metaPath(conversationId);
|
|
6638
|
+
await mkdir(dirname(metaPath), { recursive: true });
|
|
6639
|
+
await withFileLock(metaPath, async () => {
|
|
6640
|
+
let current = {};
|
|
6641
|
+
try {
|
|
6642
|
+
current = coerceSessionMeta(JSON.parse(await readFile(metaPath, "utf8"))) ?? {};
|
|
6643
|
+
} catch (cause) {
|
|
6644
|
+
if (cause.code !== "ENOENT") throw cause;
|
|
6645
|
+
}
|
|
6646
|
+
const next = applyMetaPatch(current, patch);
|
|
6647
|
+
await writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
|
|
6648
|
+
});
|
|
6649
|
+
}
|
|
6508
6650
|
async dispose() {
|
|
6509
6651
|
}
|
|
6510
6652
|
};
|
|
@@ -8424,7 +8566,7 @@ function bootstrapSubmanagers(args) {
|
|
|
8424
8566
|
const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
|
|
8425
8567
|
if (providerCount > 0 || args.options.providers !== void 0) {
|
|
8426
8568
|
out.providers = new ProvidersManagerImpl(
|
|
8427
|
-
args.options.model,
|
|
8569
|
+
normalizeModel(args.options.model),
|
|
8428
8570
|
args.options.providers,
|
|
8429
8571
|
args.options.plugins
|
|
8430
8572
|
);
|
|
@@ -8494,6 +8636,7 @@ function createLocalRun(options) {
|
|
|
8494
8636
|
projectMcpServers: options.projectMcpServers,
|
|
8495
8637
|
...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
|
|
8496
8638
|
});
|
|
8639
|
+
if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
|
|
8497
8640
|
const handle = new LocalRun({
|
|
8498
8641
|
id,
|
|
8499
8642
|
agentId: options.agentId,
|
|
@@ -9142,6 +9285,15 @@ async function emitReasoningDeltaCallback(inputs, text) {
|
|
|
9142
9285
|
);
|
|
9143
9286
|
}
|
|
9144
9287
|
|
|
9288
|
+
// src/types/run-events.ts
|
|
9289
|
+
function emitRunEvent(sink, event) {
|
|
9290
|
+
if (sink === void 0) return;
|
|
9291
|
+
try {
|
|
9292
|
+
sink(event);
|
|
9293
|
+
} catch {
|
|
9294
|
+
}
|
|
9295
|
+
}
|
|
9296
|
+
|
|
9145
9297
|
// src/internal/agent-loop/tool-dispatch.ts
|
|
9146
9298
|
init_async_local_storage();
|
|
9147
9299
|
|
|
@@ -9239,6 +9391,22 @@ function coerceArgsToSchema(args, schema) {
|
|
|
9239
9391
|
return { value: out, changed };
|
|
9240
9392
|
}
|
|
9241
9393
|
|
|
9394
|
+
// src/tool-error.ts
|
|
9395
|
+
init_errors();
|
|
9396
|
+
var ToolError = class extends TheokitAgentError {
|
|
9397
|
+
name = "ToolError";
|
|
9398
|
+
/** The error content surfaced to the model: a string, or text/image blocks. */
|
|
9399
|
+
content;
|
|
9400
|
+
constructor(content, options = {}) {
|
|
9401
|
+
super(renderToolErrorMessage(content), { ...options, isRetryable: false });
|
|
9402
|
+
this.content = content;
|
|
9403
|
+
}
|
|
9404
|
+
};
|
|
9405
|
+
function renderToolErrorMessage(content) {
|
|
9406
|
+
if (typeof content === "string") return content;
|
|
9407
|
+
return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
|
|
9408
|
+
}
|
|
9409
|
+
|
|
9242
9410
|
// src/internal/runtime/tools/shell-tool.ts
|
|
9243
9411
|
async function runShell(options) {
|
|
9244
9412
|
if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
|
|
@@ -9278,23 +9446,27 @@ async function executeTool(inputs, resolved, call) {
|
|
|
9278
9446
|
if (resolved.origin === "shell") return runShellTool(inputs, call);
|
|
9279
9447
|
if (resolved.origin === "memory") return runMemoryTool(resolved, call, inputs.context);
|
|
9280
9448
|
if (resolved.origin === "custom")
|
|
9281
|
-
return runCustomTool(resolved, call, inputs.signal, inputs.context);
|
|
9449
|
+
return runCustomTool(resolved, call, inputs.signal, inputs.context, inputs.messages);
|
|
9282
9450
|
return runMcpTool(inputs, resolved, call);
|
|
9283
9451
|
}
|
|
9284
9452
|
async function runMemoryTool(resolved, call, context) {
|
|
9285
9453
|
return runHandlerTool("memory", resolved.memoryHandler, call, void 0, context);
|
|
9286
9454
|
}
|
|
9287
|
-
async function runCustomTool(resolved, call, signal, context) {
|
|
9288
|
-
return runHandlerTool("custom", resolved.customHandler, call, signal, context);
|
|
9455
|
+
async function runCustomTool(resolved, call, signal, context, messages) {
|
|
9456
|
+
return runHandlerTool("custom", resolved.customHandler, call, signal, context, messages);
|
|
9289
9457
|
}
|
|
9290
|
-
async function runHandlerTool(kind, handler, call, signal, context) {
|
|
9458
|
+
async function runHandlerTool(kind, handler, call, signal, context, messages) {
|
|
9291
9459
|
if (handler === void 0) {
|
|
9292
9460
|
return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
|
|
9293
9461
|
}
|
|
9294
9462
|
try {
|
|
9295
|
-
const
|
|
9296
|
-
return { stdout, stderr: "", exitCode: 0 };
|
|
9463
|
+
const out = await handler(call.input, { signal, context, messages });
|
|
9464
|
+
if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
|
|
9465
|
+
return { stdout: out, stderr: "", exitCode: 0 };
|
|
9297
9466
|
} catch (cause) {
|
|
9467
|
+
if (cause instanceof ToolError) {
|
|
9468
|
+
return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
|
|
9469
|
+
}
|
|
9298
9470
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
9299
9471
|
return { stdout: "", stderr: message, exitCode: 1 };
|
|
9300
9472
|
}
|
|
@@ -9413,6 +9585,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
|
|
|
9413
9585
|
toolSpan?.end();
|
|
9414
9586
|
return fileVeto;
|
|
9415
9587
|
}
|
|
9588
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9589
|
+
type: "tool_progress",
|
|
9590
|
+
toolName: workingCall.name,
|
|
9591
|
+
toolCallId: callId
|
|
9592
|
+
});
|
|
9416
9593
|
const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
|
|
9417
9594
|
await inputs.pluginManager?.runPostToolCallHooks({
|
|
9418
9595
|
name: workingCall.name,
|
|
@@ -9439,6 +9616,13 @@ function applyRepairAndExtractCall(tools, call) {
|
|
|
9439
9616
|
function vetoFromForkWhitelist(inputs, call, callId, events) {
|
|
9440
9617
|
const whitelistDecision = checkToolWhitelist(call.name);
|
|
9441
9618
|
if (whitelistDecision.allowed) return void 0;
|
|
9619
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9620
|
+
type: "permission_denied",
|
|
9621
|
+
toolName: call.name,
|
|
9622
|
+
toolCallId: callId,
|
|
9623
|
+
source: "fork_whitelist",
|
|
9624
|
+
message: whitelistDecision.reason ?? "tool not available in fork"
|
|
9625
|
+
});
|
|
9442
9626
|
events.push(buildToolUseRunning(inputs, callId, call));
|
|
9443
9627
|
events.push(
|
|
9444
9628
|
buildToolUseCompleted(inputs, callId, call, {
|
|
@@ -9475,6 +9659,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
|
|
|
9475
9659
|
runId: inputs.runId
|
|
9476
9660
|
});
|
|
9477
9661
|
if (pluginVeto === void 0) return void 0;
|
|
9662
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9663
|
+
type: "permission_denied",
|
|
9664
|
+
toolName: call.name,
|
|
9665
|
+
toolCallId: callId,
|
|
9666
|
+
source: "plugin",
|
|
9667
|
+
message: pluginVeto.message
|
|
9668
|
+
});
|
|
9478
9669
|
events.push(
|
|
9479
9670
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9480
9671
|
stdout: "",
|
|
@@ -9497,6 +9688,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
|
|
|
9497
9688
|
runId: inputs.runId
|
|
9498
9689
|
});
|
|
9499
9690
|
if (!preDecision.blocked) return void 0;
|
|
9691
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9692
|
+
type: "permission_denied",
|
|
9693
|
+
toolName: call.name,
|
|
9694
|
+
toolCallId: callId,
|
|
9695
|
+
source: "file_hook",
|
|
9696
|
+
message: preDecision.reason ?? "blocked by hook"
|
|
9697
|
+
});
|
|
9500
9698
|
events.push(
|
|
9501
9699
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9502
9700
|
stdout: "",
|
|
@@ -9540,7 +9738,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
|
|
|
9540
9738
|
await safeEmitToolHook(inputs.onToolEnd, {
|
|
9541
9739
|
toolName: call.name,
|
|
9542
9740
|
args: call.input,
|
|
9543
|
-
|
|
9741
|
+
// SE7 — a block-returning handler has empty `stdout`; surface its structured
|
|
9742
|
+
// content to the hook instead of an empty string.
|
|
9743
|
+
result: result.content !== void 0 ? result.content : result.stdout,
|
|
9544
9744
|
conversationId: inputs.agentId,
|
|
9545
9745
|
callId,
|
|
9546
9746
|
durationMs
|
|
@@ -9562,7 +9762,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9562
9762
|
output: {
|
|
9563
9763
|
stdout: result.stdout,
|
|
9564
9764
|
stderr: result.stderr,
|
|
9565
|
-
exitCode: result.exitCode ?? 0
|
|
9765
|
+
exitCode: result.exitCode ?? 0,
|
|
9766
|
+
// SE7 — structured content (text + image blocks) when the handler
|
|
9767
|
+
// returned/threw blocks; absent for the string path.
|
|
9768
|
+
...result.content !== void 0 ? { content: result.content } : {}
|
|
9566
9769
|
},
|
|
9567
9770
|
agentId: inputs.agentId,
|
|
9568
9771
|
runId: inputs.runId
|
|
@@ -9575,7 +9778,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9575
9778
|
return {
|
|
9576
9779
|
type: "tool_result",
|
|
9577
9780
|
toolUseId: call.id,
|
|
9578
|
-
content
|
|
9781
|
+
// SE7 — structured content blocks (handler-returned or ToolError-carried)
|
|
9782
|
+
// are authoritative; otherwise the legacy string rendering.
|
|
9783
|
+
content: result.content !== void 0 ? result.content : renderToolResult(result),
|
|
9579
9784
|
...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
|
|
9580
9785
|
};
|
|
9581
9786
|
}
|
|
@@ -9624,6 +9829,29 @@ function buildToolUseCompleted(inputs, callId, call, result) {
|
|
|
9624
9829
|
};
|
|
9625
9830
|
}
|
|
9626
9831
|
|
|
9832
|
+
// src/internal/llm/tool-result-content.ts
|
|
9833
|
+
init_errors();
|
|
9834
|
+
function toBlockToolResultContent(content) {
|
|
9835
|
+
return content;
|
|
9836
|
+
}
|
|
9837
|
+
function toStringToolResultContent(content, providerName) {
|
|
9838
|
+
if (typeof content === "string") return content;
|
|
9839
|
+
if (content.some((block) => block.type === "image")) {
|
|
9840
|
+
throw new ConfigurationError(
|
|
9841
|
+
`provider "${providerName}" does not support image content in tool results`
|
|
9842
|
+
);
|
|
9843
|
+
}
|
|
9844
|
+
return content.filter(
|
|
9845
|
+
(block) => block.type === "text"
|
|
9846
|
+
).map((block) => block.text).join("\n");
|
|
9847
|
+
}
|
|
9848
|
+
function renderToolResultContentText(content, fn) {
|
|
9849
|
+
if (typeof content === "string") return fn(content);
|
|
9850
|
+
return content.map(
|
|
9851
|
+
(block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
|
|
9852
|
+
);
|
|
9853
|
+
}
|
|
9854
|
+
|
|
9627
9855
|
// src/internal/agent-loop/tool-result-guard.ts
|
|
9628
9856
|
var OPEN = "<untrusted-tool-output>";
|
|
9629
9857
|
var CLOSE = "</untrusted-tool-output>";
|
|
@@ -9649,7 +9877,11 @@ ${CLOSE}`;
|
|
|
9649
9877
|
function applyToolResultGuard(parts, opts) {
|
|
9650
9878
|
if (opts.delimit !== true && opts.redactPii !== true) return parts;
|
|
9651
9879
|
return parts.map(
|
|
9652
|
-
(p) =>
|
|
9880
|
+
(p) => (
|
|
9881
|
+
// SE7 — guard the TEXT of a tool result (string or the text blocks of a
|
|
9882
|
+
// structured content); image blocks pass through untouched.
|
|
9883
|
+
p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
|
|
9884
|
+
)
|
|
9653
9885
|
);
|
|
9654
9886
|
}
|
|
9655
9887
|
|
|
@@ -9988,6 +10220,14 @@ function computeUsageCost(inputs, usage) {
|
|
|
9988
10220
|
}
|
|
9989
10221
|
|
|
9990
10222
|
// src/internal/agent-loop/loop.ts
|
|
10223
|
+
function projectToolContextMessages(messages) {
|
|
10224
|
+
const projected = [];
|
|
10225
|
+
for (const m of messages) {
|
|
10226
|
+
const content = m.content.flatMap((p) => p.type === "text" ? [p.text] : []).join("");
|
|
10227
|
+
if (content !== "") projected.push({ role: m.role, content });
|
|
10228
|
+
}
|
|
10229
|
+
return projected;
|
|
10230
|
+
}
|
|
9991
10231
|
var MAX_NUDGE_ATTEMPTS = 2;
|
|
9992
10232
|
var MAX_STOP_FEEDBACK_ATTEMPTS = 2;
|
|
9993
10233
|
async function runAgentLoop(inputs) {
|
|
@@ -10230,7 +10470,9 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
|
|
|
10230
10470
|
const outText = await transformLlmOutputText(inputs, llmOutput.text, tCtx);
|
|
10231
10471
|
ctx.messages.push(buildAssistantTurn(outText, llmOutput.toolCalls));
|
|
10232
10472
|
const rawResults = await dispatchTools(
|
|
10233
|
-
|
|
10473
|
+
// SE12 — forward a read-only text projection of the transcript-so-far to tool
|
|
10474
|
+
// handlers via `ctx.messages` (consumed by defineSubAgent's messageFilter).
|
|
10475
|
+
{ ...inputs, messages: projectToolContextMessages(ctx.messages) },
|
|
10234
10476
|
ctx.tools,
|
|
10235
10477
|
llmOutput.toolCalls,
|
|
10236
10478
|
ctx.events,
|
|
@@ -10566,10 +10808,10 @@ function stripVertexPrefix(modelId) {
|
|
|
10566
10808
|
}
|
|
10567
10809
|
|
|
10568
10810
|
// src/internal/providers/builtin/index.ts
|
|
10569
|
-
var
|
|
10811
|
+
var registered3 = false;
|
|
10570
10812
|
function registerBuiltins() {
|
|
10571
|
-
if (
|
|
10572
|
-
|
|
10813
|
+
if (registered3) return;
|
|
10814
|
+
registered3 = true;
|
|
10573
10815
|
registerProvider(ANTHROPIC);
|
|
10574
10816
|
registerProvider(OPENAI);
|
|
10575
10817
|
registerProvider(OPENROUTER);
|
|
@@ -10797,7 +11039,9 @@ function toAnthropicWireMessage(message) {
|
|
|
10797
11039
|
return {
|
|
10798
11040
|
type: "tool_result",
|
|
10799
11041
|
tool_use_id: part.toolUseId,
|
|
10800
|
-
|
|
11042
|
+
// SE7 — this wire is block-capable: strings pass through, structured
|
|
11043
|
+
// text/image blocks are forwarded natively.
|
|
11044
|
+
content: toBlockToolResultContent(part.content),
|
|
10801
11045
|
...part.isError === true ? { is_error: true } : {}
|
|
10802
11046
|
};
|
|
10803
11047
|
});
|
|
@@ -11589,7 +11833,8 @@ function toOllamaMessages(message) {
|
|
|
11589
11833
|
if (part.type === "tool_result") {
|
|
11590
11834
|
out.push({
|
|
11591
11835
|
role: "tool",
|
|
11592
|
-
|
|
11836
|
+
// SE7 — string-only tool role: text blocks flatten; image fails fast.
|
|
11837
|
+
content: toStringToolResultContent(part.content, "ollama"),
|
|
11593
11838
|
tool_name: part.toolUseId
|
|
11594
11839
|
});
|
|
11595
11840
|
}
|
|
@@ -12126,7 +12371,9 @@ function userOrToolMessages(message) {
|
|
|
12126
12371
|
out.push({
|
|
12127
12372
|
role: "tool",
|
|
12128
12373
|
tool_call_id: part.toolUseId,
|
|
12129
|
-
|
|
12374
|
+
// SE7 — this wire's tool role is string-only: text blocks flatten; an
|
|
12375
|
+
// image block fails fast (ConfigurationError).
|
|
12376
|
+
content: toStringToolResultContent(part.content, "openai")
|
|
12130
12377
|
});
|
|
12131
12378
|
}
|
|
12132
12379
|
}
|
|
@@ -13055,18 +13302,20 @@ function levenshtein(a, b) {
|
|
|
13055
13302
|
function createRealLocalRun(options) {
|
|
13056
13303
|
const { userText, id, startTime } = prepareRunContext(options.message);
|
|
13057
13304
|
const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
|
|
13058
|
-
const
|
|
13305
|
+
const runScript = {
|
|
13059
13306
|
events: [],
|
|
13060
13307
|
finalStatus: "running",
|
|
13061
13308
|
cancellable: false,
|
|
13062
|
-
conversation: []
|
|
13309
|
+
conversation: [],
|
|
13310
|
+
// SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
|
|
13311
|
+
...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
|
|
13063
13312
|
};
|
|
13064
13313
|
const handle = new RealLocalRun(
|
|
13065
13314
|
{
|
|
13066
13315
|
id,
|
|
13067
13316
|
agentId: options.agentId,
|
|
13068
13317
|
model: options.model,
|
|
13069
|
-
script:
|
|
13318
|
+
script: runScript,
|
|
13070
13319
|
supportedOps: supported,
|
|
13071
13320
|
startTime
|
|
13072
13321
|
},
|
|
@@ -13178,6 +13427,8 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
13178
13427
|
// M7 — forward SendOptions.context to the loop so every tool handler receives
|
|
13179
13428
|
// it on `ctx.context` (shared run config set once, e.g. projectRoot).
|
|
13180
13429
|
...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
|
|
13430
|
+
// SE2 — forward the opt-in typed runtime-event sink to the loop.
|
|
13431
|
+
...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
|
|
13181
13432
|
// #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
|
|
13182
13433
|
// can enable them via SendOptions (not only internal AgentLoopInputs).
|
|
13183
13434
|
...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
|
|
@@ -15870,7 +16121,7 @@ function wrapRunWithPostReplyHook(args) {
|
|
|
15870
16121
|
async function executeSendLocked(inputs, message, options) {
|
|
15871
16122
|
if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
|
|
15872
16123
|
await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
|
|
15873
|
-
inputs.applyModelOverride(options.model);
|
|
16124
|
+
inputs.applyModelOverride(normalizeModel(options.model));
|
|
15874
16125
|
const userText = typeof message === "string" ? message : message.text;
|
|
15875
16126
|
if (inputs.options.onBeforeSend !== void 0) {
|
|
15876
16127
|
await inputs.options.onBeforeSend({
|
|
@@ -16022,7 +16273,7 @@ var LocalAgent = class {
|
|
|
16022
16273
|
constructor(options) {
|
|
16023
16274
|
this.agentId = options.agentId ?? generateLocalAgentId();
|
|
16024
16275
|
this._telemetry = createTelemetry(options.telemetry);
|
|
16025
|
-
this.model = options.model;
|
|
16276
|
+
this.model = normalizeModel(options.model);
|
|
16026
16277
|
this.options = options;
|
|
16027
16278
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
16028
16279
|
this.conversationStorage = options.conversationStorage;
|
|
@@ -16089,6 +16340,11 @@ var LocalAgent = class {
|
|
|
16089
16340
|
hooks() {
|
|
16090
16341
|
return this.hooksExecutor;
|
|
16091
16342
|
}
|
|
16343
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
16344
|
+
generate(message, options) {
|
|
16345
|
+
const { apiKey, local } = this.options;
|
|
16346
|
+
return agentGenerate(this, this.model, apiKey, local, message, options);
|
|
16347
|
+
}
|
|
16092
16348
|
async send(message, options = {}) {
|
|
16093
16349
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
16094
16350
|
validateToolCatalog(options.tools);
|
|
@@ -16328,6 +16584,7 @@ function includesSetting(options, source) {
|
|
|
16328
16584
|
|
|
16329
16585
|
// src/agent-helpers.ts
|
|
16330
16586
|
async function runCreateUnderSpan(options, span) {
|
|
16587
|
+
options = { ...options, model: normalizeModel(options.model) };
|
|
16331
16588
|
validateAgentOptions(options);
|
|
16332
16589
|
validateCloudToolParity(options);
|
|
16333
16590
|
await guardAgainstIdCollision(options);
|
|
@@ -16401,7 +16658,10 @@ async function createLocalAgent(options) {
|
|
|
16401
16658
|
const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
|
|
16402
16659
|
const shape = validateApiKeyShape(apiKey, {
|
|
16403
16660
|
strict: willFlowToProvider,
|
|
16404
|
-
|
|
16661
|
+
// `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
|
|
16662
|
+
// here is the idempotent narrowing of the widened public type (`{id}` passes
|
|
16663
|
+
// through by reference) — cleaner than an `as` cast.
|
|
16664
|
+
...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
|
|
16405
16665
|
});
|
|
16406
16666
|
if (shape.malformed) {
|
|
16407
16667
|
throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
|
|
@@ -16467,6 +16727,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
|
|
|
16467
16727
|
...existing.options,
|
|
16468
16728
|
...options,
|
|
16469
16729
|
...mergedLocal !== void 0 ? { local: mergedLocal } : {},
|
|
16730
|
+
// SE8 — normalize a caller-supplied bare-string model override at this resume
|
|
16731
|
+
// boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
|
|
16732
|
+
// honors it; local resume forces the persisted model below.
|
|
16733
|
+
model: normalizeModel(options.model ?? existing.options.model),
|
|
16470
16734
|
mcpServers: void 0,
|
|
16471
16735
|
agentId
|
|
16472
16736
|
};
|
|
@@ -16833,6 +17097,7 @@ async function getOrCreateUncached(agentId, options) {
|
|
|
16833
17097
|
}
|
|
16834
17098
|
setAgentFacade({
|
|
16835
17099
|
create: (options) => Agent.create(options),
|
|
17100
|
+
delete: (agentId) => Agent.delete(agentId),
|
|
16836
17101
|
prompt: (message, options) => Agent.prompt(message, options),
|
|
16837
17102
|
get: (agentId) => Agent.get(agentId),
|
|
16838
17103
|
resume: (agentId, options) => Agent.resume(agentId, options),
|