@theokit/sdk 2.20.0 → 2.21.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 +115 -0
- package/dist/a2a/index.cjs +592 -290
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +593 -291
- package/dist/a2a/index.js.map +1 -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-D2yLOrk2.d.ts → cron-YrmsszEN.d.cts} +53 -3
- package/dist/{cron-B8fqui49.d.cts → cron-dpvtRoro.d.ts} +53 -3
- package/dist/cron.cjs +642 -387
- 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 +643 -388
- package/dist/cron.js.map +1 -1
- package/dist/{errors-5lj1EWgs.d.ts → errors-C4vZPqXf.d.ts} +2 -2
- package/dist/{errors-CE-lMBi2.d.cts → errors-DrcpYVfZ.d.cts} +2 -2
- package/dist/errors.d.cts +3 -2
- package/dist/eval.cjs +642 -387
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +642 -387
- package/dist/eval.js.map +1 -1
- package/dist/generate-object.d.ts +4 -3
- package/dist/index.cjs +788 -390
- 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 +786 -392
- 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-BMo8yRwK.d.cts} +262 -19
- package/dist/{run-BgfBWX-z.d.ts → run-BMo8yRwK.d.ts} +262 -19
- package/dist/stream-object.d.ts +2 -1
- package/dist/tool-error.d.ts +30 -0
- package/dist/types/agent-prims.d.ts +10 -8
- package/dist/types/agent.d.ts +12 -1
- 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/cron.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
|
-
import { readFile, unlink, mkdir, open, rename, statfs, stat, rm, readdir, appendFile, access } from 'fs/promises';
|
|
4
|
+
import { readFile, unlink, mkdir, open, rename, statfs, stat, rm, readdir, writeFile, 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 { mkdirSync, readdirSync, existsSync, realpathSync, lstatSync, readlinkSync, readFileSync } from 'fs';
|
|
6
7
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
7
|
-
import { createRequire } from 'module';
|
|
8
8
|
import { homedir } from 'os';
|
|
9
9
|
import { spawn } from 'child_process';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
@@ -510,6 +510,256 @@ var init_errors = __esm({
|
|
|
510
510
|
};
|
|
511
511
|
}
|
|
512
512
|
});
|
|
513
|
+
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
514
|
+
return toJSONSchema(schema, options);
|
|
515
|
+
}
|
|
516
|
+
var init_to_json_schema = __esm({
|
|
517
|
+
"src/internal/zod/to-json-schema.ts"() {
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
function requireZod() {
|
|
521
|
+
if (cachedZ !== void 0) return cachedZ;
|
|
522
|
+
const r = createRequire(import.meta.url);
|
|
523
|
+
let mod;
|
|
524
|
+
try {
|
|
525
|
+
mod = r("zod");
|
|
526
|
+
} catch (cause) {
|
|
527
|
+
throw new ConfigurationError(
|
|
528
|
+
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
529
|
+
{ code: "zod_not_installed", cause }
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
cachedZ = mod.z ?? mod;
|
|
533
|
+
return cachedZ;
|
|
534
|
+
}
|
|
535
|
+
function makeOutputTool(jsonSchema, onCapture) {
|
|
536
|
+
return {
|
|
537
|
+
name: "output",
|
|
538
|
+
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
539
|
+
inputSchema: jsonSchema,
|
|
540
|
+
handler: (input) => {
|
|
541
|
+
const out = onCapture(input);
|
|
542
|
+
if (typeof out === "string") return out;
|
|
543
|
+
if (out instanceof Promise) return out;
|
|
544
|
+
return "";
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function buildTransientAgentOptions(params) {
|
|
549
|
+
return {
|
|
550
|
+
model: params.model,
|
|
551
|
+
local: params.local,
|
|
552
|
+
tools: [params.outputTool],
|
|
553
|
+
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
554
|
+
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
555
|
+
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
function extractUsage(result) {
|
|
559
|
+
const u = result.usage;
|
|
560
|
+
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
561
|
+
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
562
|
+
}
|
|
563
|
+
function buildToolPrompt(prompt) {
|
|
564
|
+
return `${prompt}
|
|
565
|
+
|
|
566
|
+
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
567
|
+
}
|
|
568
|
+
function setupStructuredOutput(schema, maxRetries) {
|
|
569
|
+
const z6 = requireZod();
|
|
570
|
+
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
571
|
+
return {
|
|
572
|
+
z: z6,
|
|
573
|
+
jsonSchema,
|
|
574
|
+
maxRetries: maxRetries ?? 1,
|
|
575
|
+
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
async function disposeAndDeleteTransient(agent, deletor) {
|
|
579
|
+
await agent.dispose();
|
|
580
|
+
try {
|
|
581
|
+
await deletor(agent.agentId);
|
|
582
|
+
} catch {
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
var cachedZ;
|
|
586
|
+
var init_structured_output_helpers = __esm({
|
|
587
|
+
"src/internal/structured-output-helpers.ts"() {
|
|
588
|
+
init_errors();
|
|
589
|
+
init_to_json_schema();
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// src/generate-object.ts
|
|
594
|
+
var generate_object_exports = {};
|
|
595
|
+
__export(generate_object_exports, {
|
|
596
|
+
GenerateObjectError: () => GenerateObjectError,
|
|
597
|
+
generateObjectImpl: () => generateObjectImpl
|
|
598
|
+
});
|
|
599
|
+
function salvagePartial(schema, raw) {
|
|
600
|
+
if (typeof raw !== "object" || raw === null) return raw;
|
|
601
|
+
const shape = schema.shape;
|
|
602
|
+
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
603
|
+
const rawObj = raw;
|
|
604
|
+
const out = {};
|
|
605
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
606
|
+
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
607
|
+
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
608
|
+
if (parsed.success) out[key] = parsed.data;
|
|
609
|
+
}
|
|
610
|
+
return out;
|
|
611
|
+
}
|
|
612
|
+
async function runReasoningPhase(options, deps) {
|
|
613
|
+
const reasoningOptions = {
|
|
614
|
+
model: options.model,
|
|
615
|
+
local: options.local,
|
|
616
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
617
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
618
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
619
|
+
};
|
|
620
|
+
const reasoningAgent = await deps.create(reasoningOptions);
|
|
621
|
+
try {
|
|
622
|
+
const run = await reasoningAgent.send(options.prompt);
|
|
623
|
+
const result = await run.wait();
|
|
624
|
+
const text = result.result;
|
|
625
|
+
return typeof text === "string" ? text : options.prompt;
|
|
626
|
+
} finally {
|
|
627
|
+
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
async function generateObjectImpl(options, deps) {
|
|
631
|
+
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
632
|
+
options.schema,
|
|
633
|
+
options.maxRetries
|
|
634
|
+
);
|
|
635
|
+
let capturedRaw;
|
|
636
|
+
let lastUsage = initialUsage;
|
|
637
|
+
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
638
|
+
class CaptureSentinel extends Error {
|
|
639
|
+
constructor(captured) {
|
|
640
|
+
super("generate-object-capture");
|
|
641
|
+
this.captured = captured;
|
|
642
|
+
}
|
|
643
|
+
captured;
|
|
644
|
+
[sentinel] = true;
|
|
645
|
+
}
|
|
646
|
+
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
647
|
+
if (capturedRaw === void 0) {
|
|
648
|
+
capturedRaw = input;
|
|
649
|
+
}
|
|
650
|
+
throw new CaptureSentinel(input);
|
|
651
|
+
});
|
|
652
|
+
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
653
|
+
const structuringModel = options.structuringModel ?? options.model;
|
|
654
|
+
const structuringPrompt = reasoningText ?? options.prompt;
|
|
655
|
+
const agentOptions = buildTransientAgentOptions({
|
|
656
|
+
model: structuringModel,
|
|
657
|
+
local: options.local,
|
|
658
|
+
outputTool,
|
|
659
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
660
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
661
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
662
|
+
});
|
|
663
|
+
const agent = await deps.create(agentOptions);
|
|
664
|
+
try {
|
|
665
|
+
const userMessage = buildToolPrompt(structuringPrompt);
|
|
666
|
+
let lastParseError;
|
|
667
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
668
|
+
capturedRaw = void 0;
|
|
669
|
+
const run = await agent.send(userMessage);
|
|
670
|
+
const result = await run.wait();
|
|
671
|
+
lastUsage = extractUsage(result);
|
|
672
|
+
if (capturedRaw === void 0) {
|
|
673
|
+
if (result.status === "error" && result.error !== void 0) {
|
|
674
|
+
throw new GenerateObjectError(
|
|
675
|
+
"no_tool_call",
|
|
676
|
+
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
677
|
+
result.error
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
if (attempt === maxRetries) {
|
|
681
|
+
throw new GenerateObjectError(
|
|
682
|
+
"no_tool_call",
|
|
683
|
+
"The model returned text instead of calling the `output` tool."
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
const parsed = options.schema.safeParse(capturedRaw);
|
|
689
|
+
if (parsed.success) {
|
|
690
|
+
return {
|
|
691
|
+
object: parsed.data,
|
|
692
|
+
raw: capturedRaw,
|
|
693
|
+
usage: lastUsage,
|
|
694
|
+
finishReason: "tool_use"
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
lastParseError = parsed.error;
|
|
698
|
+
}
|
|
699
|
+
if (options.errorStrategy === "return-raw") {
|
|
700
|
+
return {
|
|
701
|
+
object: capturedRaw,
|
|
702
|
+
raw: capturedRaw,
|
|
703
|
+
usage: lastUsage,
|
|
704
|
+
finishReason: "tool_use"
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
if (options.errorStrategy === "return-partial") {
|
|
708
|
+
return {
|
|
709
|
+
object: salvagePartial(options.schema, capturedRaw),
|
|
710
|
+
raw: capturedRaw,
|
|
711
|
+
usage: lastUsage,
|
|
712
|
+
finishReason: "tool_use"
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
throw new GenerateObjectError(
|
|
716
|
+
"parse_failed",
|
|
717
|
+
"Schema parse failed after all retries.",
|
|
718
|
+
lastParseError
|
|
719
|
+
);
|
|
720
|
+
} finally {
|
|
721
|
+
await disposeAndDeleteTransient(agent, deps.delete);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
var GenerateObjectError;
|
|
725
|
+
var init_generate_object = __esm({
|
|
726
|
+
"src/generate-object.ts"() {
|
|
727
|
+
init_structured_output_helpers();
|
|
728
|
+
GenerateObjectError = class extends Error {
|
|
729
|
+
name = "GenerateObjectError";
|
|
730
|
+
code;
|
|
731
|
+
cause;
|
|
732
|
+
constructor(code, message, cause) {
|
|
733
|
+
super(message);
|
|
734
|
+
this.code = code;
|
|
735
|
+
if (cause !== void 0) this.cause = cause;
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
742
|
+
var agent_factory_registry_exports = {};
|
|
743
|
+
__export(agent_factory_registry_exports, {
|
|
744
|
+
getAgentFacade: () => getAgentFacade,
|
|
745
|
+
setAgentFacade: () => setAgentFacade
|
|
746
|
+
});
|
|
747
|
+
function setAgentFacade(facade) {
|
|
748
|
+
registered = facade;
|
|
749
|
+
}
|
|
750
|
+
function getAgentFacade() {
|
|
751
|
+
if (registered === void 0) {
|
|
752
|
+
throw new Error(
|
|
753
|
+
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
return registered;
|
|
757
|
+
}
|
|
758
|
+
var registered;
|
|
759
|
+
var init_agent_factory_registry = __esm({
|
|
760
|
+
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
761
|
+
}
|
|
762
|
+
});
|
|
513
763
|
|
|
514
764
|
// src/internal/persistence/cwd-mutex.ts
|
|
515
765
|
function withCwdMutex(key, fn) {
|
|
@@ -1427,29 +1677,6 @@ var init_judge_call = __esm({
|
|
|
1427
1677
|
}
|
|
1428
1678
|
});
|
|
1429
1679
|
|
|
1430
|
-
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
1431
|
-
var agent_factory_registry_exports = {};
|
|
1432
|
-
__export(agent_factory_registry_exports, {
|
|
1433
|
-
getAgentFacade: () => getAgentFacade,
|
|
1434
|
-
setAgentFacade: () => setAgentFacade
|
|
1435
|
-
});
|
|
1436
|
-
function setAgentFacade(facade) {
|
|
1437
|
-
registered3 = facade;
|
|
1438
|
-
}
|
|
1439
|
-
function getAgentFacade() {
|
|
1440
|
-
if (registered3 === void 0) {
|
|
1441
|
-
throw new Error(
|
|
1442
|
-
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
1443
|
-
);
|
|
1444
|
-
}
|
|
1445
|
-
return registered3;
|
|
1446
|
-
}
|
|
1447
|
-
var registered3;
|
|
1448
|
-
var init_agent_factory_registry = __esm({
|
|
1449
|
-
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
1450
|
-
}
|
|
1451
|
-
});
|
|
1452
|
-
|
|
1453
1680
|
// src/internal/runtime/lifecycle/run-to-completion.ts
|
|
1454
1681
|
var run_to_completion_exports = {};
|
|
1455
1682
|
__export(run_to_completion_exports, {
|
|
@@ -1614,14 +1841,14 @@ async function forkAgentImpl(parent, options, deps) {
|
|
|
1614
1841
|
return {
|
|
1615
1842
|
result: result.result,
|
|
1616
1843
|
toolCalls: [],
|
|
1617
|
-
usage:
|
|
1844
|
+
usage: extractUsage2(result)
|
|
1618
1845
|
};
|
|
1619
1846
|
});
|
|
1620
1847
|
} finally {
|
|
1621
1848
|
await fork.dispose();
|
|
1622
1849
|
}
|
|
1623
1850
|
}
|
|
1624
|
-
function
|
|
1851
|
+
function extractUsage2(result) {
|
|
1625
1852
|
if (typeof result !== "object" || result === null) {
|
|
1626
1853
|
return { inputTokens: 0, outputTokens: 0 };
|
|
1627
1854
|
}
|
|
@@ -2054,345 +2281,118 @@ async function runWorkAndFinalize(taskId, aborter, work) {
|
|
|
2054
2281
|
emit(payload) {
|
|
2055
2282
|
void checkCancelRequestedAt(taskId, aborter);
|
|
2056
2283
|
emitToSubscribers(taskId, {
|
|
2057
|
-
type: "progress",
|
|
2058
|
-
taskId,
|
|
2059
|
-
at: Date.now(),
|
|
2060
|
-
payload
|
|
2061
|
-
});
|
|
2062
|
-
}
|
|
2063
|
-
};
|
|
2064
|
-
try {
|
|
2065
|
-
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2066
|
-
if (aborter.signal.aborted) {
|
|
2067
|
-
const cancelledAt = Date.now();
|
|
2068
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2069
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2070
|
-
return;
|
|
2071
|
-
}
|
|
2072
|
-
const finishedAt = Date.now();
|
|
2073
|
-
await transition(taskId, "finished", { finishedAt, result });
|
|
2074
|
-
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2075
|
-
} catch (err) {
|
|
2076
|
-
if (aborter.signal.aborted) {
|
|
2077
|
-
const cancelledAt = Date.now();
|
|
2078
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2079
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2080
|
-
return;
|
|
2081
|
-
}
|
|
2082
|
-
const erroredAt = Date.now();
|
|
2083
|
-
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2084
|
-
await transition(taskId, "error", { erroredAt, error });
|
|
2085
|
-
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2089
|
-
if (aborter.signal.aborted) return;
|
|
2090
|
-
try {
|
|
2091
|
-
const handle = await state.store.get(taskId);
|
|
2092
|
-
if (handle?.cancelRequested === true) {
|
|
2093
|
-
aborter.abort("cancelRequested");
|
|
2094
|
-
}
|
|
2095
|
-
} catch {
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
async function acquireSlot() {
|
|
2099
|
-
if (reentryAls.getStore() === true) {
|
|
2100
|
-
return () => {
|
|
2101
|
-
};
|
|
2102
|
-
}
|
|
2103
|
-
return state.semaphore.acquire();
|
|
2104
|
-
}
|
|
2105
|
-
async function submit(internal) {
|
|
2106
|
-
state.firstSubmitSeen = true;
|
|
2107
|
-
startEvictTimerIfNeeded();
|
|
2108
|
-
const resolvedId = resolveIdInternal(internal);
|
|
2109
|
-
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2110
|
-
const existing = await state.store.get(resolvedId);
|
|
2111
|
-
if (existing !== void 0) {
|
|
2112
|
-
submitSpan.end();
|
|
2113
|
-
return existing;
|
|
2114
|
-
}
|
|
2115
|
-
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2116
|
-
submitSpan.end();
|
|
2117
|
-
if (internal.signal?.aborted === true) {
|
|
2118
|
-
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2119
|
-
}
|
|
2120
|
-
const aborter = new AbortController();
|
|
2121
|
-
state.aborters.set(resolvedId, aborter);
|
|
2122
|
-
if (internal.signal !== void 0) {
|
|
2123
|
-
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2124
|
-
once: true
|
|
2125
|
-
});
|
|
2126
|
-
}
|
|
2127
|
-
const release = await acquireSlot();
|
|
2128
|
-
void (async () => {
|
|
2129
|
-
try {
|
|
2130
|
-
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2131
|
-
if (aborter.signal.aborted) {
|
|
2132
|
-
const cancelledAt = Date.now();
|
|
2133
|
-
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2134
|
-
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2135
|
-
return;
|
|
2136
|
-
}
|
|
2137
|
-
const startedAt = Date.now();
|
|
2138
|
-
await transition(resolvedId, "running", { startedAt });
|
|
2139
|
-
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2140
|
-
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2141
|
-
} finally {
|
|
2142
|
-
release();
|
|
2143
|
-
state.aborters.delete(resolvedId);
|
|
2144
|
-
}
|
|
2145
|
-
})();
|
|
2146
|
-
return queuedHandle;
|
|
2147
|
-
}
|
|
2148
|
-
async function get(id) {
|
|
2149
|
-
if (!isValidTaskId(id, true)) return void 0;
|
|
2150
|
-
return state.store.get(id);
|
|
2151
|
-
}
|
|
2152
|
-
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2153
|
-
var init_registry = __esm({
|
|
2154
|
-
"src/internal/task/registry.ts"() {
|
|
2155
|
-
init_errors();
|
|
2156
|
-
init_task();
|
|
2157
|
-
init_async_semaphore();
|
|
2158
|
-
init_ring_buffer();
|
|
2159
|
-
init_store();
|
|
2160
|
-
init_subscribe();
|
|
2161
|
-
init_telemetry();
|
|
2162
|
-
DEFAULT_CONCURRENCY = 8;
|
|
2163
|
-
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2164
|
-
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2165
|
-
RING_CAP = 64;
|
|
2166
|
-
reentryAls = new AsyncLocalStorage();
|
|
2167
|
-
state = buildState({});
|
|
2168
|
-
}
|
|
2169
|
-
});
|
|
2170
|
-
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
2171
|
-
return toJSONSchema(schema, options);
|
|
2172
|
-
}
|
|
2173
|
-
var init_to_json_schema = __esm({
|
|
2174
|
-
"src/internal/zod/to-json-schema.ts"() {
|
|
2175
|
-
}
|
|
2176
|
-
});
|
|
2177
|
-
function requireZod() {
|
|
2178
|
-
if (cachedZ !== void 0) return cachedZ;
|
|
2179
|
-
const r = createRequire(import.meta.url);
|
|
2180
|
-
let mod;
|
|
2181
|
-
try {
|
|
2182
|
-
mod = r("zod");
|
|
2183
|
-
} catch (cause) {
|
|
2184
|
-
throw new ConfigurationError(
|
|
2185
|
-
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
2186
|
-
{ code: "zod_not_installed", cause }
|
|
2187
|
-
);
|
|
2188
|
-
}
|
|
2189
|
-
cachedZ = mod.z ?? mod;
|
|
2190
|
-
return cachedZ;
|
|
2191
|
-
}
|
|
2192
|
-
function makeOutputTool(jsonSchema, onCapture) {
|
|
2193
|
-
return {
|
|
2194
|
-
name: "output",
|
|
2195
|
-
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
2196
|
-
inputSchema: jsonSchema,
|
|
2197
|
-
handler: (input) => {
|
|
2198
|
-
const out = onCapture(input);
|
|
2199
|
-
if (typeof out === "string") return out;
|
|
2200
|
-
if (out instanceof Promise) return out;
|
|
2201
|
-
return "";
|
|
2202
|
-
}
|
|
2203
|
-
};
|
|
2204
|
-
}
|
|
2205
|
-
function buildTransientAgentOptions(params) {
|
|
2206
|
-
return {
|
|
2207
|
-
model: params.model,
|
|
2208
|
-
local: params.local,
|
|
2209
|
-
tools: [params.outputTool],
|
|
2210
|
-
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
2211
|
-
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
2212
|
-
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
2213
|
-
};
|
|
2214
|
-
}
|
|
2215
|
-
function extractUsage2(result) {
|
|
2216
|
-
const u = result.usage;
|
|
2217
|
-
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
2218
|
-
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
2219
|
-
}
|
|
2220
|
-
function buildToolPrompt(prompt) {
|
|
2221
|
-
return `${prompt}
|
|
2222
|
-
|
|
2223
|
-
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
2224
|
-
}
|
|
2225
|
-
function setupStructuredOutput(schema, maxRetries) {
|
|
2226
|
-
const z6 = requireZod();
|
|
2227
|
-
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
2228
|
-
return {
|
|
2229
|
-
z: z6,
|
|
2230
|
-
jsonSchema,
|
|
2231
|
-
maxRetries: maxRetries ?? 1,
|
|
2232
|
-
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
2233
|
-
};
|
|
2234
|
-
}
|
|
2235
|
-
async function disposeAndDeleteTransient(agent, deletor) {
|
|
2236
|
-
await agent.dispose();
|
|
2237
|
-
try {
|
|
2238
|
-
await deletor(agent.agentId);
|
|
2239
|
-
} catch {
|
|
2240
|
-
}
|
|
2241
|
-
}
|
|
2242
|
-
var cachedZ;
|
|
2243
|
-
var init_structured_output_helpers = __esm({
|
|
2244
|
-
"src/internal/structured-output-helpers.ts"() {
|
|
2245
|
-
init_errors();
|
|
2246
|
-
init_to_json_schema();
|
|
2247
|
-
}
|
|
2248
|
-
});
|
|
2249
|
-
|
|
2250
|
-
// src/generate-object.ts
|
|
2251
|
-
var generate_object_exports = {};
|
|
2252
|
-
__export(generate_object_exports, {
|
|
2253
|
-
GenerateObjectError: () => GenerateObjectError,
|
|
2254
|
-
generateObjectImpl: () => generateObjectImpl
|
|
2255
|
-
});
|
|
2256
|
-
function salvagePartial(schema, raw) {
|
|
2257
|
-
if (typeof raw !== "object" || raw === null) return raw;
|
|
2258
|
-
const shape = schema.shape;
|
|
2259
|
-
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
2260
|
-
const rawObj = raw;
|
|
2261
|
-
const out = {};
|
|
2262
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
2263
|
-
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
2264
|
-
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
2265
|
-
if (parsed.success) out[key] = parsed.data;
|
|
2266
|
-
}
|
|
2267
|
-
return out;
|
|
2268
|
-
}
|
|
2269
|
-
async function runReasoningPhase(options, deps) {
|
|
2270
|
-
const reasoningOptions = {
|
|
2271
|
-
model: options.model,
|
|
2272
|
-
local: options.local,
|
|
2273
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2274
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2275
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2276
|
-
};
|
|
2277
|
-
const reasoningAgent = await deps.create(reasoningOptions);
|
|
2278
|
-
try {
|
|
2279
|
-
const run = await reasoningAgent.send(options.prompt);
|
|
2280
|
-
const result = await run.wait();
|
|
2281
|
-
const text = result.result;
|
|
2282
|
-
return typeof text === "string" ? text : options.prompt;
|
|
2283
|
-
} finally {
|
|
2284
|
-
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
2285
|
-
}
|
|
2286
|
-
}
|
|
2287
|
-
async function generateObjectImpl(options, deps) {
|
|
2288
|
-
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
2289
|
-
options.schema,
|
|
2290
|
-
options.maxRetries
|
|
2291
|
-
);
|
|
2292
|
-
let capturedRaw;
|
|
2293
|
-
let lastUsage = initialUsage;
|
|
2294
|
-
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
2295
|
-
class CaptureSentinel extends Error {
|
|
2296
|
-
constructor(captured) {
|
|
2297
|
-
super("generate-object-capture");
|
|
2298
|
-
this.captured = captured;
|
|
2299
|
-
}
|
|
2300
|
-
captured;
|
|
2301
|
-
[sentinel] = true;
|
|
2302
|
-
}
|
|
2303
|
-
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
2304
|
-
if (capturedRaw === void 0) {
|
|
2305
|
-
capturedRaw = input;
|
|
2306
|
-
}
|
|
2307
|
-
throw new CaptureSentinel(input);
|
|
2308
|
-
});
|
|
2309
|
-
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
2310
|
-
const structuringModel = options.structuringModel ?? options.model;
|
|
2311
|
-
const structuringPrompt = reasoningText ?? options.prompt;
|
|
2312
|
-
const agentOptions = buildTransientAgentOptions({
|
|
2313
|
-
model: structuringModel,
|
|
2314
|
-
local: options.local,
|
|
2315
|
-
outputTool,
|
|
2316
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2317
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2318
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2319
|
-
});
|
|
2320
|
-
const agent = await deps.create(agentOptions);
|
|
2284
|
+
type: "progress",
|
|
2285
|
+
taskId,
|
|
2286
|
+
at: Date.now(),
|
|
2287
|
+
payload
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
};
|
|
2321
2291
|
try {
|
|
2322
|
-
const
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
lastUsage = extractUsage2(result);
|
|
2329
|
-
if (capturedRaw === void 0) {
|
|
2330
|
-
if (result.status === "error" && result.error !== void 0) {
|
|
2331
|
-
throw new GenerateObjectError(
|
|
2332
|
-
"no_tool_call",
|
|
2333
|
-
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
2334
|
-
result.error
|
|
2335
|
-
);
|
|
2336
|
-
}
|
|
2337
|
-
if (attempt === maxRetries) {
|
|
2338
|
-
throw new GenerateObjectError(
|
|
2339
|
-
"no_tool_call",
|
|
2340
|
-
"The model returned text instead of calling the `output` tool."
|
|
2341
|
-
);
|
|
2342
|
-
}
|
|
2343
|
-
continue;
|
|
2344
|
-
}
|
|
2345
|
-
const parsed = options.schema.safeParse(capturedRaw);
|
|
2346
|
-
if (parsed.success) {
|
|
2347
|
-
return {
|
|
2348
|
-
object: parsed.data,
|
|
2349
|
-
raw: capturedRaw,
|
|
2350
|
-
usage: lastUsage,
|
|
2351
|
-
finishReason: "tool_use"
|
|
2352
|
-
};
|
|
2353
|
-
}
|
|
2354
|
-
lastParseError = parsed.error;
|
|
2292
|
+
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2293
|
+
if (aborter.signal.aborted) {
|
|
2294
|
+
const cancelledAt = Date.now();
|
|
2295
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2296
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2297
|
+
return;
|
|
2355
2298
|
}
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
};
|
|
2299
|
+
const finishedAt = Date.now();
|
|
2300
|
+
await transition(taskId, "finished", { finishedAt, result });
|
|
2301
|
+
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2302
|
+
} catch (err) {
|
|
2303
|
+
if (aborter.signal.aborted) {
|
|
2304
|
+
const cancelledAt = Date.now();
|
|
2305
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2306
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2307
|
+
return;
|
|
2363
2308
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2309
|
+
const erroredAt = Date.now();
|
|
2310
|
+
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2311
|
+
await transition(taskId, "error", { erroredAt, error });
|
|
2312
|
+
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2316
|
+
if (aborter.signal.aborted) return;
|
|
2317
|
+
try {
|
|
2318
|
+
const handle = await state.store.get(taskId);
|
|
2319
|
+
if (handle?.cancelRequested === true) {
|
|
2320
|
+
aborter.abort("cancelRequested");
|
|
2371
2321
|
}
|
|
2372
|
-
|
|
2373
|
-
"parse_failed",
|
|
2374
|
-
"Schema parse failed after all retries.",
|
|
2375
|
-
lastParseError
|
|
2376
|
-
);
|
|
2377
|
-
} finally {
|
|
2378
|
-
await disposeAndDeleteTransient(agent, deps.delete);
|
|
2322
|
+
} catch {
|
|
2379
2323
|
}
|
|
2380
2324
|
}
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
init_structured_output_helpers();
|
|
2385
|
-
GenerateObjectError = class extends Error {
|
|
2386
|
-
name = "GenerateObjectError";
|
|
2387
|
-
code;
|
|
2388
|
-
cause;
|
|
2389
|
-
constructor(code, message, cause) {
|
|
2390
|
-
super(message);
|
|
2391
|
-
this.code = code;
|
|
2392
|
-
if (cause !== void 0) this.cause = cause;
|
|
2393
|
-
}
|
|
2325
|
+
async function acquireSlot() {
|
|
2326
|
+
if (reentryAls.getStore() === true) {
|
|
2327
|
+
return () => {
|
|
2394
2328
|
};
|
|
2395
2329
|
}
|
|
2330
|
+
return state.semaphore.acquire();
|
|
2331
|
+
}
|
|
2332
|
+
async function submit(internal) {
|
|
2333
|
+
state.firstSubmitSeen = true;
|
|
2334
|
+
startEvictTimerIfNeeded();
|
|
2335
|
+
const resolvedId = resolveIdInternal(internal);
|
|
2336
|
+
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2337
|
+
const existing = await state.store.get(resolvedId);
|
|
2338
|
+
if (existing !== void 0) {
|
|
2339
|
+
submitSpan.end();
|
|
2340
|
+
return existing;
|
|
2341
|
+
}
|
|
2342
|
+
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2343
|
+
submitSpan.end();
|
|
2344
|
+
if (internal.signal?.aborted === true) {
|
|
2345
|
+
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2346
|
+
}
|
|
2347
|
+
const aborter = new AbortController();
|
|
2348
|
+
state.aborters.set(resolvedId, aborter);
|
|
2349
|
+
if (internal.signal !== void 0) {
|
|
2350
|
+
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2351
|
+
once: true
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
const release = await acquireSlot();
|
|
2355
|
+
void (async () => {
|
|
2356
|
+
try {
|
|
2357
|
+
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2358
|
+
if (aborter.signal.aborted) {
|
|
2359
|
+
const cancelledAt = Date.now();
|
|
2360
|
+
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2361
|
+
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
const startedAt = Date.now();
|
|
2365
|
+
await transition(resolvedId, "running", { startedAt });
|
|
2366
|
+
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2367
|
+
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2368
|
+
} finally {
|
|
2369
|
+
release();
|
|
2370
|
+
state.aborters.delete(resolvedId);
|
|
2371
|
+
}
|
|
2372
|
+
})();
|
|
2373
|
+
return queuedHandle;
|
|
2374
|
+
}
|
|
2375
|
+
async function get(id) {
|
|
2376
|
+
if (!isValidTaskId(id, true)) return void 0;
|
|
2377
|
+
return state.store.get(id);
|
|
2378
|
+
}
|
|
2379
|
+
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2380
|
+
var init_registry = __esm({
|
|
2381
|
+
"src/internal/task/registry.ts"() {
|
|
2382
|
+
init_errors();
|
|
2383
|
+
init_task();
|
|
2384
|
+
init_async_semaphore();
|
|
2385
|
+
init_ring_buffer();
|
|
2386
|
+
init_store();
|
|
2387
|
+
init_subscribe();
|
|
2388
|
+
init_telemetry();
|
|
2389
|
+
DEFAULT_CONCURRENCY = 8;
|
|
2390
|
+
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2391
|
+
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2392
|
+
RING_CAP = 64;
|
|
2393
|
+
reentryAls = new AsyncLocalStorage();
|
|
2394
|
+
state = buildState({});
|
|
2395
|
+
}
|
|
2396
2396
|
});
|
|
2397
2397
|
|
|
2398
2398
|
// src/stream-object.ts
|
|
@@ -2449,7 +2449,7 @@ async function* streamObjectImpl(options, deps) {
|
|
|
2449
2449
|
}
|
|
2450
2450
|
}
|
|
2451
2451
|
const result = await run.wait();
|
|
2452
|
-
lastUsage =
|
|
2452
|
+
lastUsage = extractUsage(result);
|
|
2453
2453
|
if (capturedRaw === void 0) {
|
|
2454
2454
|
if (result.status === "error" && result.error !== void 0) {
|
|
2455
2455
|
throw new StreamObjectError(
|
|
@@ -2795,6 +2795,7 @@ var AgentBuilder = class {
|
|
|
2795
2795
|
constructor(deps) {
|
|
2796
2796
|
this.deps = deps;
|
|
2797
2797
|
}
|
|
2798
|
+
/** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
|
|
2798
2799
|
model(m) {
|
|
2799
2800
|
this.opts.model = m;
|
|
2800
2801
|
return this;
|
|
@@ -3148,6 +3149,69 @@ function isLocalAgentId(id) {
|
|
|
3148
3149
|
return id.startsWith(PREFIX.localAgent);
|
|
3149
3150
|
}
|
|
3150
3151
|
|
|
3152
|
+
// src/internal/runtime/config/default-model.ts
|
|
3153
|
+
var DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
|
|
3154
|
+
|
|
3155
|
+
// src/agent-generate.ts
|
|
3156
|
+
async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
|
|
3157
|
+
const { output, maxRetries, errorStrategy, ...sendOptions } = options;
|
|
3158
|
+
const run = await agent.send(input, sendOptions);
|
|
3159
|
+
const result = await run.wait();
|
|
3160
|
+
const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
|
|
3161
|
+
const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
|
|
3162
|
+
const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
|
|
3163
|
+
const facade = getAgentFacade2();
|
|
3164
|
+
const structured = await generateObjectImpl2(
|
|
3165
|
+
{
|
|
3166
|
+
prompt: answer,
|
|
3167
|
+
schema: output,
|
|
3168
|
+
// `agentModel` arrives already normalized (`this.model` passed through
|
|
3169
|
+
// `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
|
|
3170
|
+
// `string | ModelSelection` field only ever receives a `ModelSelection` here.
|
|
3171
|
+
model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
|
|
3172
|
+
// `local` is required to keep the transient structuring agent local-only;
|
|
3173
|
+
// default to the process cwd when the agent had no explicit local config.
|
|
3174
|
+
local: agentLocal ?? { cwd: process.cwd() },
|
|
3175
|
+
...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
|
|
3176
|
+
...maxRetries !== void 0 ? { maxRetries } : {},
|
|
3177
|
+
...errorStrategy !== void 0 ? { errorStrategy } : {}
|
|
3178
|
+
},
|
|
3179
|
+
{
|
|
3180
|
+
create: (opts) => facade.create(opts),
|
|
3181
|
+
delete: (agentId) => facade.delete(agentId)
|
|
3182
|
+
}
|
|
3183
|
+
);
|
|
3184
|
+
return {
|
|
3185
|
+
object: structured.object,
|
|
3186
|
+
result,
|
|
3187
|
+
raw: structured.raw,
|
|
3188
|
+
usage: structured.usage
|
|
3189
|
+
};
|
|
3190
|
+
}
|
|
3191
|
+
function structurableAnswerOrThrow(result, GenerateObjectError2) {
|
|
3192
|
+
if (result.status === "error") {
|
|
3193
|
+
throw new GenerateObjectError2(
|
|
3194
|
+
"no_tool_call",
|
|
3195
|
+
`Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
|
|
3196
|
+
result.error
|
|
3197
|
+
);
|
|
3198
|
+
}
|
|
3199
|
+
if (result.status === "cancelled") {
|
|
3200
|
+
throw new GenerateObjectError2(
|
|
3201
|
+
"no_tool_call",
|
|
3202
|
+
"Agent run was cancelled before an answer could be structured."
|
|
3203
|
+
);
|
|
3204
|
+
}
|
|
3205
|
+
const answer = result.result;
|
|
3206
|
+
if (answer === void 0 || answer.length === 0) {
|
|
3207
|
+
throw new GenerateObjectError2(
|
|
3208
|
+
"no_tool_call",
|
|
3209
|
+
"The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
|
|
3210
|
+
);
|
|
3211
|
+
}
|
|
3212
|
+
return answer;
|
|
3213
|
+
}
|
|
3214
|
+
|
|
3151
3215
|
// src/internal/runtime/cloud/cloud-agent.ts
|
|
3152
3216
|
init_errors();
|
|
3153
3217
|
init_cwd_mutex();
|
|
@@ -3298,8 +3362,19 @@ function safeFilenameForId(id, options) {
|
|
|
3298
3362
|
return `h-${createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
|
|
3299
3363
|
}
|
|
3300
3364
|
|
|
3301
|
-
// src/internal/runtime/
|
|
3302
|
-
|
|
3365
|
+
// src/internal/runtime/model-selection.ts
|
|
3366
|
+
init_errors();
|
|
3367
|
+
function normalizeModel(m) {
|
|
3368
|
+
if (m === void 0 || typeof m !== "string") return m;
|
|
3369
|
+
const id = m.trim();
|
|
3370
|
+
if (id.length === 0) {
|
|
3371
|
+
throw new ConfigurationError(
|
|
3372
|
+
'model must be a non-empty "provider/model" id string or a ModelSelection object',
|
|
3373
|
+
{ code: "invalid_model_selection" }
|
|
3374
|
+
);
|
|
3375
|
+
}
|
|
3376
|
+
return { id };
|
|
3377
|
+
}
|
|
3303
3378
|
|
|
3304
3379
|
// src/internal/runtime/registry/agent-registry-store.ts
|
|
3305
3380
|
init_cwd_mutex();
|
|
@@ -3376,7 +3451,10 @@ var REGISTRY_RELATIVE_PATH = join(".theokit", "agents", "registry.json");
|
|
|
3376
3451
|
function stripSecretsFromOptions(options) {
|
|
3377
3452
|
return assignDefined({
|
|
3378
3453
|
name: options.name,
|
|
3379
|
-
model:
|
|
3454
|
+
model: (() => {
|
|
3455
|
+
const m = normalizeModel(options.model);
|
|
3456
|
+
return m !== void 0 ? { id: m.id } : void 0;
|
|
3457
|
+
})(),
|
|
3380
3458
|
systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
|
|
3381
3459
|
local: serializeLocal(options.local),
|
|
3382
3460
|
cloud: serializeCloud(options.cloud),
|
|
@@ -3661,7 +3739,8 @@ function serializeCloudAgentConfig(options) {
|
|
|
3661
3739
|
cloud: serializeCloud2(options.cloud)
|
|
3662
3740
|
};
|
|
3663
3741
|
if (typeof options.agentId === "string") payload.agentId = options.agentId;
|
|
3664
|
-
|
|
3742
|
+
const cfgModel = normalizeModel(options.model);
|
|
3743
|
+
if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
|
|
3665
3744
|
if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
|
|
3666
3745
|
const skills = serializeSkills(options.skills);
|
|
3667
3746
|
if (skills !== void 0) payload.skills = skills;
|
|
@@ -4557,6 +4636,7 @@ function applyScriptMetrics(base, script) {
|
|
|
4557
4636
|
if (script.cost !== void 0) base.cost = script.cost;
|
|
4558
4637
|
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
4559
4638
|
if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
|
|
4639
|
+
if (script.origin !== void 0) base.origin = script.origin;
|
|
4560
4640
|
}
|
|
4561
4641
|
|
|
4562
4642
|
// src/internal/runtime/cloud/cloud-run.ts
|
|
@@ -4912,7 +4992,7 @@ var CloudAgent = class {
|
|
|
4912
4992
|
disposed = false;
|
|
4913
4993
|
constructor(options, providedAgentId) {
|
|
4914
4994
|
this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
|
|
4915
|
-
this.model = options.model;
|
|
4995
|
+
this.model = normalizeModel(options.model);
|
|
4916
4996
|
this.options = options;
|
|
4917
4997
|
this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
|
|
4918
4998
|
const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
|
|
@@ -4942,6 +5022,17 @@ var CloudAgent = class {
|
|
|
4942
5022
|
const apiKey = resolveApiKey(this.options.apiKey);
|
|
4943
5023
|
return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
|
|
4944
5024
|
}
|
|
5025
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
5026
|
+
generate(message, options) {
|
|
5027
|
+
return agentGenerate(
|
|
5028
|
+
this,
|
|
5029
|
+
this.model,
|
|
5030
|
+
this.options.apiKey,
|
|
5031
|
+
this.options.local,
|
|
5032
|
+
message,
|
|
5033
|
+
options
|
|
5034
|
+
);
|
|
5035
|
+
}
|
|
4945
5036
|
async send(message, options = {}) {
|
|
4946
5037
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
4947
5038
|
throw new ConfigurationError(
|
|
@@ -4972,7 +5063,7 @@ var CloudAgent = class {
|
|
|
4972
5063
|
});
|
|
4973
5064
|
}
|
|
4974
5065
|
async sendLocked(message, options) {
|
|
4975
|
-
const overrideModel = options.model;
|
|
5066
|
+
const overrideModel = normalizeModel(options.model);
|
|
4976
5067
|
if (overrideModel !== void 0) {
|
|
4977
5068
|
this.model = overrideModel;
|
|
4978
5069
|
updateRegisteredAgent(this.agentId, { model: overrideModel });
|
|
@@ -5886,18 +5977,18 @@ var ALL_ADAPTERS = [
|
|
|
5886
5977
|
arizeAdapter,
|
|
5887
5978
|
braintrustAdapter
|
|
5888
5979
|
];
|
|
5889
|
-
var
|
|
5980
|
+
var registered2 = /* @__PURE__ */ new Set();
|
|
5890
5981
|
function tryAutoRegisterAdapters(settings) {
|
|
5891
5982
|
if (settings?.enabled !== true) return;
|
|
5892
5983
|
if (settings.autoDetect === false) return;
|
|
5893
5984
|
const disabled = new Set(settings.disable ?? []);
|
|
5894
5985
|
for (const adapter of ALL_ADAPTERS) {
|
|
5895
|
-
if (
|
|
5986
|
+
if (registered2.has(adapter.moduleName)) continue;
|
|
5896
5987
|
if (disabled.has(adapter.displayName.toLowerCase())) continue;
|
|
5897
5988
|
if (!adapter.detect()) continue;
|
|
5898
5989
|
try {
|
|
5899
5990
|
adapter.register();
|
|
5900
|
-
|
|
5991
|
+
registered2.add(adapter.moduleName);
|
|
5901
5992
|
process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
|
|
5902
5993
|
`);
|
|
5903
5994
|
} catch (cause) {
|
|
@@ -6460,6 +6551,26 @@ function paginate(items, opts) {
|
|
|
6460
6551
|
return items.slice(start, end);
|
|
6461
6552
|
}
|
|
6462
6553
|
|
|
6554
|
+
// src/internal/persistence/session-meta.ts
|
|
6555
|
+
function applyMetaPatch(current, patch) {
|
|
6556
|
+
const next = {};
|
|
6557
|
+
if (current.title !== void 0) next.title = current.title;
|
|
6558
|
+
if (current.tag !== void 0) next.tag = current.tag;
|
|
6559
|
+
if (patch.title === null) delete next.title;
|
|
6560
|
+
else if (patch.title !== void 0) next.title = patch.title;
|
|
6561
|
+
if (patch.tag === null) delete next.tag;
|
|
6562
|
+
else if (patch.tag !== void 0) next.tag = patch.tag;
|
|
6563
|
+
return next;
|
|
6564
|
+
}
|
|
6565
|
+
function coerceSessionMeta(raw) {
|
|
6566
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
6567
|
+
const obj = raw;
|
|
6568
|
+
const meta = {};
|
|
6569
|
+
if (typeof obj.title === "string") meta.title = obj.title;
|
|
6570
|
+
if (typeof obj.tag === "string") meta.tag = obj.tag;
|
|
6571
|
+
return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
|
|
6572
|
+
}
|
|
6573
|
+
|
|
6463
6574
|
// src/internal/persistence/conversation-storage-fs.ts
|
|
6464
6575
|
var FileSystemConversationStorage = class {
|
|
6465
6576
|
#root;
|
|
@@ -6510,6 +6621,37 @@ var FileSystemConversationStorage = class {
|
|
|
6510
6621
|
async compact(conversationId, maxTurns) {
|
|
6511
6622
|
await compactSessionFile(this.#root, conversationId, maxTurns);
|
|
6512
6623
|
}
|
|
6624
|
+
// SE4 — session metadata persisted as a per-conversation sidecar
|
|
6625
|
+
// `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
|
|
6626
|
+
// the transcript). Kept separate from messages.jsonl so a title/tag write does
|
|
6627
|
+
// not rewrite the append-only log.
|
|
6628
|
+
#metaPath(conversationId) {
|
|
6629
|
+
const safe2 = sanitizeIdentifier(conversationId, { maxLen: 128 });
|
|
6630
|
+
return safePathJoin(this.#root, ".theokit", "agents", safe2, "session.json");
|
|
6631
|
+
}
|
|
6632
|
+
async getSessionMeta(conversationId) {
|
|
6633
|
+
try {
|
|
6634
|
+
const raw = await readFile(this.#metaPath(conversationId), "utf8");
|
|
6635
|
+
return coerceSessionMeta(JSON.parse(raw));
|
|
6636
|
+
} catch (cause) {
|
|
6637
|
+
if (cause.code === "ENOENT") return void 0;
|
|
6638
|
+
throw cause;
|
|
6639
|
+
}
|
|
6640
|
+
}
|
|
6641
|
+
async setSessionMeta(conversationId, patch) {
|
|
6642
|
+
const metaPath = this.#metaPath(conversationId);
|
|
6643
|
+
await mkdir(dirname(metaPath), { recursive: true });
|
|
6644
|
+
await withFileLock(metaPath, async () => {
|
|
6645
|
+
let current = {};
|
|
6646
|
+
try {
|
|
6647
|
+
current = coerceSessionMeta(JSON.parse(await readFile(metaPath, "utf8"))) ?? {};
|
|
6648
|
+
} catch (cause) {
|
|
6649
|
+
if (cause.code !== "ENOENT") throw cause;
|
|
6650
|
+
}
|
|
6651
|
+
const next = applyMetaPatch(current, patch);
|
|
6652
|
+
await writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
|
|
6653
|
+
});
|
|
6654
|
+
}
|
|
6513
6655
|
async dispose() {
|
|
6514
6656
|
}
|
|
6515
6657
|
};
|
|
@@ -8429,7 +8571,7 @@ function bootstrapSubmanagers(args) {
|
|
|
8429
8571
|
const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
|
|
8430
8572
|
if (providerCount > 0 || args.options.providers !== void 0) {
|
|
8431
8573
|
out.providers = new ProvidersManagerImpl(
|
|
8432
|
-
args.options.model,
|
|
8574
|
+
normalizeModel(args.options.model),
|
|
8433
8575
|
args.options.providers,
|
|
8434
8576
|
args.options.plugins
|
|
8435
8577
|
);
|
|
@@ -8499,6 +8641,7 @@ function createLocalRun(options) {
|
|
|
8499
8641
|
projectMcpServers: options.projectMcpServers,
|
|
8500
8642
|
...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
|
|
8501
8643
|
});
|
|
8644
|
+
if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
|
|
8502
8645
|
const handle = new LocalRun({
|
|
8503
8646
|
id,
|
|
8504
8647
|
agentId: options.agentId,
|
|
@@ -9147,6 +9290,15 @@ async function emitReasoningDeltaCallback(inputs, text) {
|
|
|
9147
9290
|
);
|
|
9148
9291
|
}
|
|
9149
9292
|
|
|
9293
|
+
// src/types/run-events.ts
|
|
9294
|
+
function emitRunEvent(sink, event) {
|
|
9295
|
+
if (sink === void 0) return;
|
|
9296
|
+
try {
|
|
9297
|
+
sink(event);
|
|
9298
|
+
} catch {
|
|
9299
|
+
}
|
|
9300
|
+
}
|
|
9301
|
+
|
|
9150
9302
|
// src/internal/agent-loop/tool-dispatch.ts
|
|
9151
9303
|
init_async_local_storage();
|
|
9152
9304
|
|
|
@@ -9244,6 +9396,22 @@ function coerceArgsToSchema(args, schema) {
|
|
|
9244
9396
|
return { value: out, changed };
|
|
9245
9397
|
}
|
|
9246
9398
|
|
|
9399
|
+
// src/tool-error.ts
|
|
9400
|
+
init_errors();
|
|
9401
|
+
var ToolError = class extends TheokitAgentError {
|
|
9402
|
+
name = "ToolError";
|
|
9403
|
+
/** The error content surfaced to the model: a string, or text/image blocks. */
|
|
9404
|
+
content;
|
|
9405
|
+
constructor(content, options = {}) {
|
|
9406
|
+
super(renderToolErrorMessage(content), { ...options, isRetryable: false });
|
|
9407
|
+
this.content = content;
|
|
9408
|
+
}
|
|
9409
|
+
};
|
|
9410
|
+
function renderToolErrorMessage(content) {
|
|
9411
|
+
if (typeof content === "string") return content;
|
|
9412
|
+
return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
|
|
9413
|
+
}
|
|
9414
|
+
|
|
9247
9415
|
// src/internal/runtime/tools/shell-tool.ts
|
|
9248
9416
|
async function runShell(options) {
|
|
9249
9417
|
if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
|
|
@@ -9297,9 +9465,13 @@ async function runHandlerTool(kind, handler, call, signal, context) {
|
|
|
9297
9465
|
return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
|
|
9298
9466
|
}
|
|
9299
9467
|
try {
|
|
9300
|
-
const
|
|
9301
|
-
return { stdout, stderr: "", exitCode: 0 };
|
|
9468
|
+
const out = await handler(call.input, { signal, context });
|
|
9469
|
+
if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
|
|
9470
|
+
return { stdout: out, stderr: "", exitCode: 0 };
|
|
9302
9471
|
} catch (cause) {
|
|
9472
|
+
if (cause instanceof ToolError) {
|
|
9473
|
+
return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
|
|
9474
|
+
}
|
|
9303
9475
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
9304
9476
|
return { stdout: "", stderr: message, exitCode: 1 };
|
|
9305
9477
|
}
|
|
@@ -9418,6 +9590,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
|
|
|
9418
9590
|
toolSpan?.end();
|
|
9419
9591
|
return fileVeto;
|
|
9420
9592
|
}
|
|
9593
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9594
|
+
type: "tool_progress",
|
|
9595
|
+
toolName: workingCall.name,
|
|
9596
|
+
toolCallId: callId
|
|
9597
|
+
});
|
|
9421
9598
|
const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
|
|
9422
9599
|
await inputs.pluginManager?.runPostToolCallHooks({
|
|
9423
9600
|
name: workingCall.name,
|
|
@@ -9444,6 +9621,13 @@ function applyRepairAndExtractCall(tools, call) {
|
|
|
9444
9621
|
function vetoFromForkWhitelist(inputs, call, callId, events) {
|
|
9445
9622
|
const whitelistDecision = checkToolWhitelist(call.name);
|
|
9446
9623
|
if (whitelistDecision.allowed) return void 0;
|
|
9624
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9625
|
+
type: "permission_denied",
|
|
9626
|
+
toolName: call.name,
|
|
9627
|
+
toolCallId: callId,
|
|
9628
|
+
source: "fork_whitelist",
|
|
9629
|
+
message: whitelistDecision.reason ?? "tool not available in fork"
|
|
9630
|
+
});
|
|
9447
9631
|
events.push(buildToolUseRunning(inputs, callId, call));
|
|
9448
9632
|
events.push(
|
|
9449
9633
|
buildToolUseCompleted(inputs, callId, call, {
|
|
@@ -9480,6 +9664,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
|
|
|
9480
9664
|
runId: inputs.runId
|
|
9481
9665
|
});
|
|
9482
9666
|
if (pluginVeto === void 0) return void 0;
|
|
9667
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9668
|
+
type: "permission_denied",
|
|
9669
|
+
toolName: call.name,
|
|
9670
|
+
toolCallId: callId,
|
|
9671
|
+
source: "plugin",
|
|
9672
|
+
message: pluginVeto.message
|
|
9673
|
+
});
|
|
9483
9674
|
events.push(
|
|
9484
9675
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9485
9676
|
stdout: "",
|
|
@@ -9502,6 +9693,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
|
|
|
9502
9693
|
runId: inputs.runId
|
|
9503
9694
|
});
|
|
9504
9695
|
if (!preDecision.blocked) return void 0;
|
|
9696
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9697
|
+
type: "permission_denied",
|
|
9698
|
+
toolName: call.name,
|
|
9699
|
+
toolCallId: callId,
|
|
9700
|
+
source: "file_hook",
|
|
9701
|
+
message: preDecision.reason ?? "blocked by hook"
|
|
9702
|
+
});
|
|
9505
9703
|
events.push(
|
|
9506
9704
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9507
9705
|
stdout: "",
|
|
@@ -9545,7 +9743,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
|
|
|
9545
9743
|
await safeEmitToolHook(inputs.onToolEnd, {
|
|
9546
9744
|
toolName: call.name,
|
|
9547
9745
|
args: call.input,
|
|
9548
|
-
|
|
9746
|
+
// SE7 — a block-returning handler has empty `stdout`; surface its structured
|
|
9747
|
+
// content to the hook instead of an empty string.
|
|
9748
|
+
result: result.content !== void 0 ? result.content : result.stdout,
|
|
9549
9749
|
conversationId: inputs.agentId,
|
|
9550
9750
|
callId,
|
|
9551
9751
|
durationMs
|
|
@@ -9567,7 +9767,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9567
9767
|
output: {
|
|
9568
9768
|
stdout: result.stdout,
|
|
9569
9769
|
stderr: result.stderr,
|
|
9570
|
-
exitCode: result.exitCode ?? 0
|
|
9770
|
+
exitCode: result.exitCode ?? 0,
|
|
9771
|
+
// SE7 — structured content (text + image blocks) when the handler
|
|
9772
|
+
// returned/threw blocks; absent for the string path.
|
|
9773
|
+
...result.content !== void 0 ? { content: result.content } : {}
|
|
9571
9774
|
},
|
|
9572
9775
|
agentId: inputs.agentId,
|
|
9573
9776
|
runId: inputs.runId
|
|
@@ -9580,7 +9783,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9580
9783
|
return {
|
|
9581
9784
|
type: "tool_result",
|
|
9582
9785
|
toolUseId: call.id,
|
|
9583
|
-
content
|
|
9786
|
+
// SE7 — structured content blocks (handler-returned or ToolError-carried)
|
|
9787
|
+
// are authoritative; otherwise the legacy string rendering.
|
|
9788
|
+
content: result.content !== void 0 ? result.content : renderToolResult(result),
|
|
9584
9789
|
...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
|
|
9585
9790
|
};
|
|
9586
9791
|
}
|
|
@@ -9629,6 +9834,29 @@ function buildToolUseCompleted(inputs, callId, call, result) {
|
|
|
9629
9834
|
};
|
|
9630
9835
|
}
|
|
9631
9836
|
|
|
9837
|
+
// src/internal/llm/tool-result-content.ts
|
|
9838
|
+
init_errors();
|
|
9839
|
+
function toBlockToolResultContent(content) {
|
|
9840
|
+
return content;
|
|
9841
|
+
}
|
|
9842
|
+
function toStringToolResultContent(content, providerName) {
|
|
9843
|
+
if (typeof content === "string") return content;
|
|
9844
|
+
if (content.some((block) => block.type === "image")) {
|
|
9845
|
+
throw new ConfigurationError(
|
|
9846
|
+
`provider "${providerName}" does not support image content in tool results`
|
|
9847
|
+
);
|
|
9848
|
+
}
|
|
9849
|
+
return content.filter(
|
|
9850
|
+
(block) => block.type === "text"
|
|
9851
|
+
).map((block) => block.text).join("\n");
|
|
9852
|
+
}
|
|
9853
|
+
function renderToolResultContentText(content, fn) {
|
|
9854
|
+
if (typeof content === "string") return fn(content);
|
|
9855
|
+
return content.map(
|
|
9856
|
+
(block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
|
|
9857
|
+
);
|
|
9858
|
+
}
|
|
9859
|
+
|
|
9632
9860
|
// src/internal/agent-loop/tool-result-guard.ts
|
|
9633
9861
|
var OPEN = "<untrusted-tool-output>";
|
|
9634
9862
|
var CLOSE = "</untrusted-tool-output>";
|
|
@@ -9654,7 +9882,11 @@ ${CLOSE}`;
|
|
|
9654
9882
|
function applyToolResultGuard(parts, opts) {
|
|
9655
9883
|
if (opts.delimit !== true && opts.redactPii !== true) return parts;
|
|
9656
9884
|
return parts.map(
|
|
9657
|
-
(p) =>
|
|
9885
|
+
(p) => (
|
|
9886
|
+
// SE7 — guard the TEXT of a tool result (string or the text blocks of a
|
|
9887
|
+
// structured content); image blocks pass through untouched.
|
|
9888
|
+
p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
|
|
9889
|
+
)
|
|
9658
9890
|
);
|
|
9659
9891
|
}
|
|
9660
9892
|
|
|
@@ -10571,10 +10803,10 @@ function stripVertexPrefix(modelId) {
|
|
|
10571
10803
|
}
|
|
10572
10804
|
|
|
10573
10805
|
// src/internal/providers/builtin/index.ts
|
|
10574
|
-
var
|
|
10806
|
+
var registered3 = false;
|
|
10575
10807
|
function registerBuiltins() {
|
|
10576
|
-
if (
|
|
10577
|
-
|
|
10808
|
+
if (registered3) return;
|
|
10809
|
+
registered3 = true;
|
|
10578
10810
|
registerProvider(ANTHROPIC);
|
|
10579
10811
|
registerProvider(OPENAI);
|
|
10580
10812
|
registerProvider(OPENROUTER);
|
|
@@ -10802,7 +11034,9 @@ function toAnthropicWireMessage(message) {
|
|
|
10802
11034
|
return {
|
|
10803
11035
|
type: "tool_result",
|
|
10804
11036
|
tool_use_id: part.toolUseId,
|
|
10805
|
-
|
|
11037
|
+
// SE7 — this wire is block-capable: strings pass through, structured
|
|
11038
|
+
// text/image blocks are forwarded natively.
|
|
11039
|
+
content: toBlockToolResultContent(part.content),
|
|
10806
11040
|
...part.isError === true ? { is_error: true } : {}
|
|
10807
11041
|
};
|
|
10808
11042
|
});
|
|
@@ -11594,7 +11828,8 @@ function toOllamaMessages(message) {
|
|
|
11594
11828
|
if (part.type === "tool_result") {
|
|
11595
11829
|
out.push({
|
|
11596
11830
|
role: "tool",
|
|
11597
|
-
|
|
11831
|
+
// SE7 — string-only tool role: text blocks flatten; image fails fast.
|
|
11832
|
+
content: toStringToolResultContent(part.content, "ollama"),
|
|
11598
11833
|
tool_name: part.toolUseId
|
|
11599
11834
|
});
|
|
11600
11835
|
}
|
|
@@ -12131,7 +12366,9 @@ function userOrToolMessages(message) {
|
|
|
12131
12366
|
out.push({
|
|
12132
12367
|
role: "tool",
|
|
12133
12368
|
tool_call_id: part.toolUseId,
|
|
12134
|
-
|
|
12369
|
+
// SE7 — this wire's tool role is string-only: text blocks flatten; an
|
|
12370
|
+
// image block fails fast (ConfigurationError).
|
|
12371
|
+
content: toStringToolResultContent(part.content, "openai")
|
|
12135
12372
|
});
|
|
12136
12373
|
}
|
|
12137
12374
|
}
|
|
@@ -13060,18 +13297,20 @@ function levenshtein(a, b) {
|
|
|
13060
13297
|
function createRealLocalRun(options) {
|
|
13061
13298
|
const { userText, id, startTime } = prepareRunContext(options.message);
|
|
13062
13299
|
const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
|
|
13063
|
-
const
|
|
13300
|
+
const runScript = {
|
|
13064
13301
|
events: [],
|
|
13065
13302
|
finalStatus: "running",
|
|
13066
13303
|
cancellable: false,
|
|
13067
|
-
conversation: []
|
|
13304
|
+
conversation: [],
|
|
13305
|
+
// SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
|
|
13306
|
+
...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
|
|
13068
13307
|
};
|
|
13069
13308
|
const handle = new RealLocalRun(
|
|
13070
13309
|
{
|
|
13071
13310
|
id,
|
|
13072
13311
|
agentId: options.agentId,
|
|
13073
13312
|
model: options.model,
|
|
13074
|
-
script:
|
|
13313
|
+
script: runScript,
|
|
13075
13314
|
supportedOps: supported,
|
|
13076
13315
|
startTime
|
|
13077
13316
|
},
|
|
@@ -13183,6 +13422,8 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
13183
13422
|
// M7 — forward SendOptions.context to the loop so every tool handler receives
|
|
13184
13423
|
// it on `ctx.context` (shared run config set once, e.g. projectRoot).
|
|
13185
13424
|
...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
|
|
13425
|
+
// SE2 — forward the opt-in typed runtime-event sink to the loop.
|
|
13426
|
+
...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
|
|
13186
13427
|
// #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
|
|
13187
13428
|
// can enable them via SendOptions (not only internal AgentLoopInputs).
|
|
13188
13429
|
...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
|
|
@@ -15875,7 +16116,7 @@ function wrapRunWithPostReplyHook(args) {
|
|
|
15875
16116
|
async function executeSendLocked(inputs, message, options) {
|
|
15876
16117
|
if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
|
|
15877
16118
|
await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
|
|
15878
|
-
inputs.applyModelOverride(options.model);
|
|
16119
|
+
inputs.applyModelOverride(normalizeModel(options.model));
|
|
15879
16120
|
const userText = typeof message === "string" ? message : message.text;
|
|
15880
16121
|
if (inputs.options.onBeforeSend !== void 0) {
|
|
15881
16122
|
await inputs.options.onBeforeSend({
|
|
@@ -16027,7 +16268,7 @@ var LocalAgent = class {
|
|
|
16027
16268
|
constructor(options) {
|
|
16028
16269
|
this.agentId = options.agentId ?? generateLocalAgentId();
|
|
16029
16270
|
this._telemetry = createTelemetry(options.telemetry);
|
|
16030
|
-
this.model = options.model;
|
|
16271
|
+
this.model = normalizeModel(options.model);
|
|
16031
16272
|
this.options = options;
|
|
16032
16273
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
16033
16274
|
this.conversationStorage = options.conversationStorage;
|
|
@@ -16094,6 +16335,11 @@ var LocalAgent = class {
|
|
|
16094
16335
|
hooks() {
|
|
16095
16336
|
return this.hooksExecutor;
|
|
16096
16337
|
}
|
|
16338
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
16339
|
+
generate(message, options) {
|
|
16340
|
+
const { apiKey, local } = this.options;
|
|
16341
|
+
return agentGenerate(this, this.model, apiKey, local, message, options);
|
|
16342
|
+
}
|
|
16097
16343
|
async send(message, options = {}) {
|
|
16098
16344
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
16099
16345
|
validateToolCatalog(options.tools);
|
|
@@ -16333,6 +16579,7 @@ function includesSetting(options, source) {
|
|
|
16333
16579
|
|
|
16334
16580
|
// src/agent-helpers.ts
|
|
16335
16581
|
async function runCreateUnderSpan(options, span) {
|
|
16582
|
+
options = { ...options, model: normalizeModel(options.model) };
|
|
16336
16583
|
validateAgentOptions(options);
|
|
16337
16584
|
validateCloudToolParity(options);
|
|
16338
16585
|
await guardAgainstIdCollision(options);
|
|
@@ -16406,7 +16653,10 @@ async function createLocalAgent(options) {
|
|
|
16406
16653
|
const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
|
|
16407
16654
|
const shape = validateApiKeyShape(apiKey, {
|
|
16408
16655
|
strict: willFlowToProvider,
|
|
16409
|
-
|
|
16656
|
+
// `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
|
|
16657
|
+
// here is the idempotent narrowing of the widened public type (`{id}` passes
|
|
16658
|
+
// through by reference) — cleaner than an `as` cast.
|
|
16659
|
+
...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
|
|
16410
16660
|
});
|
|
16411
16661
|
if (shape.malformed) {
|
|
16412
16662
|
throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
|
|
@@ -16472,6 +16722,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
|
|
|
16472
16722
|
...existing.options,
|
|
16473
16723
|
...options,
|
|
16474
16724
|
...mergedLocal !== void 0 ? { local: mergedLocal } : {},
|
|
16725
|
+
// SE8 — normalize a caller-supplied bare-string model override at this resume
|
|
16726
|
+
// boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
|
|
16727
|
+
// honors it; local resume forces the persisted model below.
|
|
16728
|
+
model: normalizeModel(options.model ?? existing.options.model),
|
|
16475
16729
|
mcpServers: void 0,
|
|
16476
16730
|
agentId
|
|
16477
16731
|
};
|
|
@@ -16838,6 +17092,7 @@ async function getOrCreateUncached(agentId, options) {
|
|
|
16838
17092
|
}
|
|
16839
17093
|
setAgentFacade({
|
|
16840
17094
|
create: (options) => Agent.create(options),
|
|
17095
|
+
delete: (agentId) => Agent.delete(agentId),
|
|
16841
17096
|
prompt: (message, options) => Agent.prompt(message, options),
|
|
16842
17097
|
get: (agentId) => Agent.get(agentId),
|
|
16843
17098
|
resume: (agentId, options) => Agent.resume(agentId, options),
|