@theokit/sdk 2.19.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 +123 -0
- package/dist/a2a/index.cjs +611 -274
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +612 -275
- 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/create-skill.d.ts +29 -0
- package/dist/{cron-D_wK1S-0.d.cts → cron-YrmsszEN.d.cts} +110 -3
- package/dist/{cron-Cep07kTz.d.ts → cron-dpvtRoro.d.ts} +110 -3
- package/dist/cron.cjs +660 -370
- 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 +661 -371
- 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 +660 -370
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +660 -370
- package/dist/eval.js.map +1 -1
- package/dist/generate-object.d.ts +19 -4
- package/dist/index.cjs +867 -371
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +274 -16
- package/dist/index.d.ts +274 -16
- package/dist/index.js +863 -373
- 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 +22 -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 +3 -23
- 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.cjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
var module$1 = require('module');
|
|
3
5
|
var crypto = require('crypto');
|
|
4
6
|
var promises = require('fs/promises');
|
|
5
7
|
var path = require('path');
|
|
6
|
-
var zod = require('zod');
|
|
7
8
|
var fs = require('fs');
|
|
8
9
|
var async_hooks = require('async_hooks');
|
|
9
|
-
var module$1 = require('module');
|
|
10
10
|
var os = require('os');
|
|
11
11
|
var child_process = require('child_process');
|
|
12
12
|
var url = require('url');
|
|
@@ -512,6 +512,256 @@ var init_errors = __esm({
|
|
|
512
512
|
};
|
|
513
513
|
}
|
|
514
514
|
});
|
|
515
|
+
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
516
|
+
return zod.toJSONSchema(schema, options);
|
|
517
|
+
}
|
|
518
|
+
var init_to_json_schema = __esm({
|
|
519
|
+
"src/internal/zod/to-json-schema.ts"() {
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
function requireZod() {
|
|
523
|
+
if (cachedZ !== void 0) return cachedZ;
|
|
524
|
+
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('eval.cjs', document.baseURI).href)));
|
|
525
|
+
let mod;
|
|
526
|
+
try {
|
|
527
|
+
mod = r("zod");
|
|
528
|
+
} catch (cause) {
|
|
529
|
+
throw new ConfigurationError(
|
|
530
|
+
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
531
|
+
{ code: "zod_not_installed", cause }
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
cachedZ = mod.z ?? mod;
|
|
535
|
+
return cachedZ;
|
|
536
|
+
}
|
|
537
|
+
function makeOutputTool(jsonSchema, onCapture) {
|
|
538
|
+
return {
|
|
539
|
+
name: "output",
|
|
540
|
+
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
541
|
+
inputSchema: jsonSchema,
|
|
542
|
+
handler: (input) => {
|
|
543
|
+
const out = onCapture(input);
|
|
544
|
+
if (typeof out === "string") return out;
|
|
545
|
+
if (out instanceof Promise) return out;
|
|
546
|
+
return "";
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function buildTransientAgentOptions(params) {
|
|
551
|
+
return {
|
|
552
|
+
model: params.model,
|
|
553
|
+
local: params.local,
|
|
554
|
+
tools: [params.outputTool],
|
|
555
|
+
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
556
|
+
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
557
|
+
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
function extractUsage(result) {
|
|
561
|
+
const u = result.usage;
|
|
562
|
+
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
563
|
+
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
564
|
+
}
|
|
565
|
+
function buildToolPrompt(prompt) {
|
|
566
|
+
return `${prompt}
|
|
567
|
+
|
|
568
|
+
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
569
|
+
}
|
|
570
|
+
function setupStructuredOutput(schema, maxRetries) {
|
|
571
|
+
const z7 = requireZod();
|
|
572
|
+
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
573
|
+
return {
|
|
574
|
+
z: z7,
|
|
575
|
+
jsonSchema,
|
|
576
|
+
maxRetries: maxRetries ?? 1,
|
|
577
|
+
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
async function disposeAndDeleteTransient(agent, deletor) {
|
|
581
|
+
await agent.dispose();
|
|
582
|
+
try {
|
|
583
|
+
await deletor(agent.agentId);
|
|
584
|
+
} catch {
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
var cachedZ;
|
|
588
|
+
var init_structured_output_helpers = __esm({
|
|
589
|
+
"src/internal/structured-output-helpers.ts"() {
|
|
590
|
+
init_errors();
|
|
591
|
+
init_to_json_schema();
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
// src/generate-object.ts
|
|
596
|
+
var generate_object_exports = {};
|
|
597
|
+
__export(generate_object_exports, {
|
|
598
|
+
GenerateObjectError: () => GenerateObjectError,
|
|
599
|
+
generateObjectImpl: () => generateObjectImpl
|
|
600
|
+
});
|
|
601
|
+
function salvagePartial(schema, raw) {
|
|
602
|
+
if (typeof raw !== "object" || raw === null) return raw;
|
|
603
|
+
const shape = schema.shape;
|
|
604
|
+
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
605
|
+
const rawObj = raw;
|
|
606
|
+
const out = {};
|
|
607
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
608
|
+
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
609
|
+
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
610
|
+
if (parsed.success) out[key] = parsed.data;
|
|
611
|
+
}
|
|
612
|
+
return out;
|
|
613
|
+
}
|
|
614
|
+
async function runReasoningPhase(options, deps) {
|
|
615
|
+
const reasoningOptions = {
|
|
616
|
+
model: options.model,
|
|
617
|
+
local: options.local,
|
|
618
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
619
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
620
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
621
|
+
};
|
|
622
|
+
const reasoningAgent = await deps.create(reasoningOptions);
|
|
623
|
+
try {
|
|
624
|
+
const run = await reasoningAgent.send(options.prompt);
|
|
625
|
+
const result = await run.wait();
|
|
626
|
+
const text = result.result;
|
|
627
|
+
return typeof text === "string" ? text : options.prompt;
|
|
628
|
+
} finally {
|
|
629
|
+
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
async function generateObjectImpl(options, deps) {
|
|
633
|
+
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
634
|
+
options.schema,
|
|
635
|
+
options.maxRetries
|
|
636
|
+
);
|
|
637
|
+
let capturedRaw;
|
|
638
|
+
let lastUsage = initialUsage;
|
|
639
|
+
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
640
|
+
class CaptureSentinel extends Error {
|
|
641
|
+
constructor(captured) {
|
|
642
|
+
super("generate-object-capture");
|
|
643
|
+
this.captured = captured;
|
|
644
|
+
}
|
|
645
|
+
captured;
|
|
646
|
+
[sentinel] = true;
|
|
647
|
+
}
|
|
648
|
+
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
649
|
+
if (capturedRaw === void 0) {
|
|
650
|
+
capturedRaw = input;
|
|
651
|
+
}
|
|
652
|
+
throw new CaptureSentinel(input);
|
|
653
|
+
});
|
|
654
|
+
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
655
|
+
const structuringModel = options.structuringModel ?? options.model;
|
|
656
|
+
const structuringPrompt = reasoningText ?? options.prompt;
|
|
657
|
+
const agentOptions = buildTransientAgentOptions({
|
|
658
|
+
model: structuringModel,
|
|
659
|
+
local: options.local,
|
|
660
|
+
outputTool,
|
|
661
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
662
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
663
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
664
|
+
});
|
|
665
|
+
const agent = await deps.create(agentOptions);
|
|
666
|
+
try {
|
|
667
|
+
const userMessage = buildToolPrompt(structuringPrompt);
|
|
668
|
+
let lastParseError;
|
|
669
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
670
|
+
capturedRaw = void 0;
|
|
671
|
+
const run = await agent.send(userMessage);
|
|
672
|
+
const result = await run.wait();
|
|
673
|
+
lastUsage = extractUsage(result);
|
|
674
|
+
if (capturedRaw === void 0) {
|
|
675
|
+
if (result.status === "error" && result.error !== void 0) {
|
|
676
|
+
throw new GenerateObjectError(
|
|
677
|
+
"no_tool_call",
|
|
678
|
+
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
679
|
+
result.error
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
if (attempt === maxRetries) {
|
|
683
|
+
throw new GenerateObjectError(
|
|
684
|
+
"no_tool_call",
|
|
685
|
+
"The model returned text instead of calling the `output` tool."
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
const parsed = options.schema.safeParse(capturedRaw);
|
|
691
|
+
if (parsed.success) {
|
|
692
|
+
return {
|
|
693
|
+
object: parsed.data,
|
|
694
|
+
raw: capturedRaw,
|
|
695
|
+
usage: lastUsage,
|
|
696
|
+
finishReason: "tool_use"
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
lastParseError = parsed.error;
|
|
700
|
+
}
|
|
701
|
+
if (options.errorStrategy === "return-raw") {
|
|
702
|
+
return {
|
|
703
|
+
object: capturedRaw,
|
|
704
|
+
raw: capturedRaw,
|
|
705
|
+
usage: lastUsage,
|
|
706
|
+
finishReason: "tool_use"
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
if (options.errorStrategy === "return-partial") {
|
|
710
|
+
return {
|
|
711
|
+
object: salvagePartial(options.schema, capturedRaw),
|
|
712
|
+
raw: capturedRaw,
|
|
713
|
+
usage: lastUsage,
|
|
714
|
+
finishReason: "tool_use"
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
throw new GenerateObjectError(
|
|
718
|
+
"parse_failed",
|
|
719
|
+
"Schema parse failed after all retries.",
|
|
720
|
+
lastParseError
|
|
721
|
+
);
|
|
722
|
+
} finally {
|
|
723
|
+
await disposeAndDeleteTransient(agent, deps.delete);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
var GenerateObjectError;
|
|
727
|
+
var init_generate_object = __esm({
|
|
728
|
+
"src/generate-object.ts"() {
|
|
729
|
+
init_structured_output_helpers();
|
|
730
|
+
GenerateObjectError = class extends Error {
|
|
731
|
+
name = "GenerateObjectError";
|
|
732
|
+
code;
|
|
733
|
+
cause;
|
|
734
|
+
constructor(code, message, cause) {
|
|
735
|
+
super(message);
|
|
736
|
+
this.code = code;
|
|
737
|
+
if (cause !== void 0) this.cause = cause;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
744
|
+
var agent_factory_registry_exports = {};
|
|
745
|
+
__export(agent_factory_registry_exports, {
|
|
746
|
+
getAgentFacade: () => getAgentFacade,
|
|
747
|
+
setAgentFacade: () => setAgentFacade
|
|
748
|
+
});
|
|
749
|
+
function setAgentFacade(facade) {
|
|
750
|
+
registered = facade;
|
|
751
|
+
}
|
|
752
|
+
function getAgentFacade() {
|
|
753
|
+
if (registered === void 0) {
|
|
754
|
+
throw new Error(
|
|
755
|
+
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
return registered;
|
|
759
|
+
}
|
|
760
|
+
var registered;
|
|
761
|
+
var init_agent_factory_registry = __esm({
|
|
762
|
+
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
763
|
+
}
|
|
764
|
+
});
|
|
515
765
|
|
|
516
766
|
// src/internal/persistence/cwd-mutex.ts
|
|
517
767
|
function withCwdMutex(key, fn) {
|
|
@@ -1429,29 +1679,6 @@ var init_judge_call = __esm({
|
|
|
1429
1679
|
}
|
|
1430
1680
|
});
|
|
1431
1681
|
|
|
1432
|
-
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
1433
|
-
var agent_factory_registry_exports = {};
|
|
1434
|
-
__export(agent_factory_registry_exports, {
|
|
1435
|
-
getAgentFacade: () => getAgentFacade,
|
|
1436
|
-
setAgentFacade: () => setAgentFacade
|
|
1437
|
-
});
|
|
1438
|
-
function setAgentFacade(facade) {
|
|
1439
|
-
registered3 = facade;
|
|
1440
|
-
}
|
|
1441
|
-
function getAgentFacade() {
|
|
1442
|
-
if (registered3 === void 0) {
|
|
1443
|
-
throw new Error(
|
|
1444
|
-
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
1445
|
-
);
|
|
1446
|
-
}
|
|
1447
|
-
return registered3;
|
|
1448
|
-
}
|
|
1449
|
-
var registered3;
|
|
1450
|
-
var init_agent_factory_registry = __esm({
|
|
1451
|
-
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
1452
|
-
}
|
|
1453
|
-
});
|
|
1454
|
-
|
|
1455
1682
|
// src/internal/runtime/lifecycle/run-to-completion.ts
|
|
1456
1683
|
var run_to_completion_exports = {};
|
|
1457
1684
|
__export(run_to_completion_exports, {
|
|
@@ -1616,14 +1843,14 @@ async function forkAgentImpl(parent, options, deps) {
|
|
|
1616
1843
|
return {
|
|
1617
1844
|
result: result.result,
|
|
1618
1845
|
toolCalls: [],
|
|
1619
|
-
usage:
|
|
1846
|
+
usage: extractUsage2(result)
|
|
1620
1847
|
};
|
|
1621
1848
|
});
|
|
1622
1849
|
} finally {
|
|
1623
1850
|
await fork.dispose();
|
|
1624
1851
|
}
|
|
1625
1852
|
}
|
|
1626
|
-
function
|
|
1853
|
+
function extractUsage2(result) {
|
|
1627
1854
|
if (typeof result !== "object" || result === null) {
|
|
1628
1855
|
return { inputTokens: 0, outputTokens: 0 };
|
|
1629
1856
|
}
|
|
@@ -2057,323 +2284,117 @@ async function runWorkAndFinalize(taskId, aborter, work) {
|
|
|
2057
2284
|
void checkCancelRequestedAt(taskId, aborter);
|
|
2058
2285
|
emitToSubscribers(taskId, {
|
|
2059
2286
|
type: "progress",
|
|
2060
|
-
taskId,
|
|
2061
|
-
at: Date.now(),
|
|
2062
|
-
payload
|
|
2063
|
-
});
|
|
2064
|
-
}
|
|
2065
|
-
};
|
|
2066
|
-
try {
|
|
2067
|
-
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2068
|
-
if (aborter.signal.aborted) {
|
|
2069
|
-
const cancelledAt = Date.now();
|
|
2070
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2071
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2072
|
-
return;
|
|
2073
|
-
}
|
|
2074
|
-
const finishedAt = Date.now();
|
|
2075
|
-
await transition(taskId, "finished", { finishedAt, result });
|
|
2076
|
-
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2077
|
-
} catch (err) {
|
|
2078
|
-
if (aborter.signal.aborted) {
|
|
2079
|
-
const cancelledAt = Date.now();
|
|
2080
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2081
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2082
|
-
return;
|
|
2083
|
-
}
|
|
2084
|
-
const erroredAt = Date.now();
|
|
2085
|
-
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2086
|
-
await transition(taskId, "error", { erroredAt, error });
|
|
2087
|
-
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2088
|
-
}
|
|
2089
|
-
}
|
|
2090
|
-
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2091
|
-
if (aborter.signal.aborted) return;
|
|
2092
|
-
try {
|
|
2093
|
-
const handle = await state.store.get(taskId);
|
|
2094
|
-
if (handle?.cancelRequested === true) {
|
|
2095
|
-
aborter.abort("cancelRequested");
|
|
2096
|
-
}
|
|
2097
|
-
} catch {
|
|
2098
|
-
}
|
|
2099
|
-
}
|
|
2100
|
-
async function acquireSlot() {
|
|
2101
|
-
if (reentryAls.getStore() === true) {
|
|
2102
|
-
return () => {
|
|
2103
|
-
};
|
|
2104
|
-
}
|
|
2105
|
-
return state.semaphore.acquire();
|
|
2106
|
-
}
|
|
2107
|
-
async function submit(internal) {
|
|
2108
|
-
state.firstSubmitSeen = true;
|
|
2109
|
-
startEvictTimerIfNeeded();
|
|
2110
|
-
const resolvedId = resolveIdInternal(internal);
|
|
2111
|
-
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2112
|
-
const existing = await state.store.get(resolvedId);
|
|
2113
|
-
if (existing !== void 0) {
|
|
2114
|
-
submitSpan.end();
|
|
2115
|
-
return existing;
|
|
2116
|
-
}
|
|
2117
|
-
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2118
|
-
submitSpan.end();
|
|
2119
|
-
if (internal.signal?.aborted === true) {
|
|
2120
|
-
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2121
|
-
}
|
|
2122
|
-
const aborter = new AbortController();
|
|
2123
|
-
state.aborters.set(resolvedId, aborter);
|
|
2124
|
-
if (internal.signal !== void 0) {
|
|
2125
|
-
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2126
|
-
once: true
|
|
2127
|
-
});
|
|
2128
|
-
}
|
|
2129
|
-
const release = await acquireSlot();
|
|
2130
|
-
void (async () => {
|
|
2131
|
-
try {
|
|
2132
|
-
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2133
|
-
if (aborter.signal.aborted) {
|
|
2134
|
-
const cancelledAt = Date.now();
|
|
2135
|
-
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2136
|
-
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2137
|
-
return;
|
|
2138
|
-
}
|
|
2139
|
-
const startedAt = Date.now();
|
|
2140
|
-
await transition(resolvedId, "running", { startedAt });
|
|
2141
|
-
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2142
|
-
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2143
|
-
} finally {
|
|
2144
|
-
release();
|
|
2145
|
-
state.aborters.delete(resolvedId);
|
|
2146
|
-
}
|
|
2147
|
-
})();
|
|
2148
|
-
return queuedHandle;
|
|
2149
|
-
}
|
|
2150
|
-
async function get(id) {
|
|
2151
|
-
if (!isValidTaskId(id, true)) return void 0;
|
|
2152
|
-
return state.store.get(id);
|
|
2153
|
-
}
|
|
2154
|
-
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2155
|
-
var init_registry = __esm({
|
|
2156
|
-
"src/internal/task/registry.ts"() {
|
|
2157
|
-
init_errors();
|
|
2158
|
-
init_task();
|
|
2159
|
-
init_async_semaphore();
|
|
2160
|
-
init_ring_buffer();
|
|
2161
|
-
init_store();
|
|
2162
|
-
init_subscribe();
|
|
2163
|
-
init_telemetry();
|
|
2164
|
-
DEFAULT_CONCURRENCY = 8;
|
|
2165
|
-
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2166
|
-
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2167
|
-
RING_CAP = 64;
|
|
2168
|
-
reentryAls = new async_hooks.AsyncLocalStorage();
|
|
2169
|
-
state = buildState({});
|
|
2170
|
-
}
|
|
2171
|
-
});
|
|
2172
|
-
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
2173
|
-
return zod.toJSONSchema(schema, options);
|
|
2174
|
-
}
|
|
2175
|
-
var init_to_json_schema = __esm({
|
|
2176
|
-
"src/internal/zod/to-json-schema.ts"() {
|
|
2177
|
-
}
|
|
2178
|
-
});
|
|
2179
|
-
function requireZod() {
|
|
2180
|
-
if (cachedZ !== void 0) return cachedZ;
|
|
2181
|
-
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('eval.cjs', document.baseURI).href)));
|
|
2182
|
-
let mod;
|
|
2183
|
-
try {
|
|
2184
|
-
mod = r("zod");
|
|
2185
|
-
} catch (cause) {
|
|
2186
|
-
throw new ConfigurationError(
|
|
2187
|
-
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
2188
|
-
{ code: "zod_not_installed", cause }
|
|
2189
|
-
);
|
|
2190
|
-
}
|
|
2191
|
-
cachedZ = mod.z ?? mod;
|
|
2192
|
-
return cachedZ;
|
|
2193
|
-
}
|
|
2194
|
-
function makeOutputTool(jsonSchema, onCapture) {
|
|
2195
|
-
return {
|
|
2196
|
-
name: "output",
|
|
2197
|
-
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
2198
|
-
inputSchema: jsonSchema,
|
|
2199
|
-
handler: (input) => {
|
|
2200
|
-
const out = onCapture(input);
|
|
2201
|
-
if (typeof out === "string") return out;
|
|
2202
|
-
if (out instanceof Promise) return out;
|
|
2203
|
-
return "";
|
|
2204
|
-
}
|
|
2205
|
-
};
|
|
2206
|
-
}
|
|
2207
|
-
function buildTransientAgentOptions(params) {
|
|
2208
|
-
return {
|
|
2209
|
-
model: params.model,
|
|
2210
|
-
local: params.local,
|
|
2211
|
-
tools: [params.outputTool],
|
|
2212
|
-
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
2213
|
-
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
2214
|
-
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
2215
|
-
};
|
|
2216
|
-
}
|
|
2217
|
-
function extractUsage2(result) {
|
|
2218
|
-
const u = result.usage;
|
|
2219
|
-
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
2220
|
-
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
2221
|
-
}
|
|
2222
|
-
function buildToolPrompt(prompt) {
|
|
2223
|
-
return `${prompt}
|
|
2224
|
-
|
|
2225
|
-
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
2226
|
-
}
|
|
2227
|
-
function setupStructuredOutput(schema, maxRetries) {
|
|
2228
|
-
const z7 = requireZod();
|
|
2229
|
-
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
2230
|
-
return {
|
|
2231
|
-
z: z7,
|
|
2232
|
-
jsonSchema,
|
|
2233
|
-
maxRetries: maxRetries ?? 1,
|
|
2234
|
-
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
2235
|
-
};
|
|
2236
|
-
}
|
|
2237
|
-
async function disposeAndDeleteTransient(agent, deletor) {
|
|
2238
|
-
await agent.dispose();
|
|
2239
|
-
try {
|
|
2240
|
-
await deletor(agent.agentId);
|
|
2241
|
-
} catch {
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
var cachedZ;
|
|
2245
|
-
var init_structured_output_helpers = __esm({
|
|
2246
|
-
"src/internal/structured-output-helpers.ts"() {
|
|
2247
|
-
init_errors();
|
|
2248
|
-
init_to_json_schema();
|
|
2249
|
-
}
|
|
2250
|
-
});
|
|
2251
|
-
|
|
2252
|
-
// src/generate-object.ts
|
|
2253
|
-
var generate_object_exports = {};
|
|
2254
|
-
__export(generate_object_exports, {
|
|
2255
|
-
GenerateObjectError: () => GenerateObjectError,
|
|
2256
|
-
generateObjectImpl: () => generateObjectImpl
|
|
2257
|
-
});
|
|
2258
|
-
function salvagePartial(schema, raw) {
|
|
2259
|
-
if (typeof raw !== "object" || raw === null) return raw;
|
|
2260
|
-
const shape = schema.shape;
|
|
2261
|
-
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
2262
|
-
const rawObj = raw;
|
|
2263
|
-
const out = {};
|
|
2264
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
2265
|
-
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
2266
|
-
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
2267
|
-
if (parsed.success) out[key] = parsed.data;
|
|
2268
|
-
}
|
|
2269
|
-
return out;
|
|
2270
|
-
}
|
|
2271
|
-
async function generateObjectImpl(options, deps) {
|
|
2272
|
-
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
2273
|
-
options.schema,
|
|
2274
|
-
options.maxRetries
|
|
2275
|
-
);
|
|
2276
|
-
let capturedRaw;
|
|
2277
|
-
let lastUsage = initialUsage;
|
|
2278
|
-
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
2279
|
-
class CaptureSentinel extends Error {
|
|
2280
|
-
constructor(captured) {
|
|
2281
|
-
super("generate-object-capture");
|
|
2282
|
-
this.captured = captured;
|
|
2283
|
-
}
|
|
2284
|
-
captured;
|
|
2285
|
-
[sentinel] = true;
|
|
2286
|
-
}
|
|
2287
|
-
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
2288
|
-
if (capturedRaw === void 0) {
|
|
2289
|
-
capturedRaw = input;
|
|
2290
|
-
}
|
|
2291
|
-
throw new CaptureSentinel(input);
|
|
2292
|
-
});
|
|
2293
|
-
const agentOptions = buildTransientAgentOptions({
|
|
2294
|
-
model: options.model,
|
|
2295
|
-
local: options.local,
|
|
2296
|
-
outputTool,
|
|
2297
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2298
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2299
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2300
|
-
});
|
|
2301
|
-
const agent = await deps.create(agentOptions);
|
|
2287
|
+
taskId,
|
|
2288
|
+
at: Date.now(),
|
|
2289
|
+
payload
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2302
2293
|
try {
|
|
2303
|
-
const
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
lastUsage = extractUsage2(result);
|
|
2310
|
-
if (capturedRaw === void 0) {
|
|
2311
|
-
if (result.status === "error" && result.error !== void 0) {
|
|
2312
|
-
throw new GenerateObjectError(
|
|
2313
|
-
"no_tool_call",
|
|
2314
|
-
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
2315
|
-
result.error
|
|
2316
|
-
);
|
|
2317
|
-
}
|
|
2318
|
-
if (attempt === maxRetries) {
|
|
2319
|
-
throw new GenerateObjectError(
|
|
2320
|
-
"no_tool_call",
|
|
2321
|
-
"The model returned text instead of calling the `output` tool."
|
|
2322
|
-
);
|
|
2323
|
-
}
|
|
2324
|
-
continue;
|
|
2325
|
-
}
|
|
2326
|
-
const parsed = options.schema.safeParse(capturedRaw);
|
|
2327
|
-
if (parsed.success) {
|
|
2328
|
-
return {
|
|
2329
|
-
object: parsed.data,
|
|
2330
|
-
raw: capturedRaw,
|
|
2331
|
-
usage: lastUsage,
|
|
2332
|
-
finishReason: "tool_use"
|
|
2333
|
-
};
|
|
2334
|
-
}
|
|
2335
|
-
lastParseError = parsed.error;
|
|
2294
|
+
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2295
|
+
if (aborter.signal.aborted) {
|
|
2296
|
+
const cancelledAt = Date.now();
|
|
2297
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2298
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2299
|
+
return;
|
|
2336
2300
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
};
|
|
2301
|
+
const finishedAt = Date.now();
|
|
2302
|
+
await transition(taskId, "finished", { finishedAt, result });
|
|
2303
|
+
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2304
|
+
} catch (err) {
|
|
2305
|
+
if (aborter.signal.aborted) {
|
|
2306
|
+
const cancelledAt = Date.now();
|
|
2307
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2308
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2309
|
+
return;
|
|
2344
2310
|
}
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2311
|
+
const erroredAt = Date.now();
|
|
2312
|
+
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2313
|
+
await transition(taskId, "error", { erroredAt, error });
|
|
2314
|
+
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2318
|
+
if (aborter.signal.aborted) return;
|
|
2319
|
+
try {
|
|
2320
|
+
const handle = await state.store.get(taskId);
|
|
2321
|
+
if (handle?.cancelRequested === true) {
|
|
2322
|
+
aborter.abort("cancelRequested");
|
|
2352
2323
|
}
|
|
2353
|
-
|
|
2354
|
-
"parse_failed",
|
|
2355
|
-
"Schema parse failed after all retries.",
|
|
2356
|
-
lastParseError
|
|
2357
|
-
);
|
|
2358
|
-
} finally {
|
|
2359
|
-
await disposeAndDeleteTransient(agent, deps.delete);
|
|
2324
|
+
} catch {
|
|
2360
2325
|
}
|
|
2361
2326
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
init_structured_output_helpers();
|
|
2366
|
-
GenerateObjectError = class extends Error {
|
|
2367
|
-
name = "GenerateObjectError";
|
|
2368
|
-
code;
|
|
2369
|
-
cause;
|
|
2370
|
-
constructor(code, message, cause) {
|
|
2371
|
-
super(message);
|
|
2372
|
-
this.code = code;
|
|
2373
|
-
if (cause !== void 0) this.cause = cause;
|
|
2374
|
-
}
|
|
2327
|
+
async function acquireSlot() {
|
|
2328
|
+
if (reentryAls.getStore() === true) {
|
|
2329
|
+
return () => {
|
|
2375
2330
|
};
|
|
2376
2331
|
}
|
|
2332
|
+
return state.semaphore.acquire();
|
|
2333
|
+
}
|
|
2334
|
+
async function submit(internal) {
|
|
2335
|
+
state.firstSubmitSeen = true;
|
|
2336
|
+
startEvictTimerIfNeeded();
|
|
2337
|
+
const resolvedId = resolveIdInternal(internal);
|
|
2338
|
+
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2339
|
+
const existing = await state.store.get(resolvedId);
|
|
2340
|
+
if (existing !== void 0) {
|
|
2341
|
+
submitSpan.end();
|
|
2342
|
+
return existing;
|
|
2343
|
+
}
|
|
2344
|
+
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2345
|
+
submitSpan.end();
|
|
2346
|
+
if (internal.signal?.aborted === true) {
|
|
2347
|
+
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2348
|
+
}
|
|
2349
|
+
const aborter = new AbortController();
|
|
2350
|
+
state.aborters.set(resolvedId, aborter);
|
|
2351
|
+
if (internal.signal !== void 0) {
|
|
2352
|
+
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2353
|
+
once: true
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2356
|
+
const release = await acquireSlot();
|
|
2357
|
+
void (async () => {
|
|
2358
|
+
try {
|
|
2359
|
+
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2360
|
+
if (aborter.signal.aborted) {
|
|
2361
|
+
const cancelledAt = Date.now();
|
|
2362
|
+
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2363
|
+
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2366
|
+
const startedAt = Date.now();
|
|
2367
|
+
await transition(resolvedId, "running", { startedAt });
|
|
2368
|
+
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2369
|
+
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2370
|
+
} finally {
|
|
2371
|
+
release();
|
|
2372
|
+
state.aborters.delete(resolvedId);
|
|
2373
|
+
}
|
|
2374
|
+
})();
|
|
2375
|
+
return queuedHandle;
|
|
2376
|
+
}
|
|
2377
|
+
async function get(id) {
|
|
2378
|
+
if (!isValidTaskId(id, true)) return void 0;
|
|
2379
|
+
return state.store.get(id);
|
|
2380
|
+
}
|
|
2381
|
+
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2382
|
+
var init_registry = __esm({
|
|
2383
|
+
"src/internal/task/registry.ts"() {
|
|
2384
|
+
init_errors();
|
|
2385
|
+
init_task();
|
|
2386
|
+
init_async_semaphore();
|
|
2387
|
+
init_ring_buffer();
|
|
2388
|
+
init_store();
|
|
2389
|
+
init_subscribe();
|
|
2390
|
+
init_telemetry();
|
|
2391
|
+
DEFAULT_CONCURRENCY = 8;
|
|
2392
|
+
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2393
|
+
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2394
|
+
RING_CAP = 64;
|
|
2395
|
+
reentryAls = new async_hooks.AsyncLocalStorage();
|
|
2396
|
+
state = buildState({});
|
|
2397
|
+
}
|
|
2377
2398
|
});
|
|
2378
2399
|
|
|
2379
2400
|
// src/stream-object.ts
|
|
@@ -2430,7 +2451,7 @@ async function* streamObjectImpl(options, deps) {
|
|
|
2430
2451
|
}
|
|
2431
2452
|
}
|
|
2432
2453
|
const result = await run.wait();
|
|
2433
|
-
lastUsage =
|
|
2454
|
+
lastUsage = extractUsage(result);
|
|
2434
2455
|
if (capturedRaw === void 0) {
|
|
2435
2456
|
if (result.status === "error" && result.error !== void 0) {
|
|
2436
2457
|
throw new StreamObjectError(
|
|
@@ -2776,6 +2797,7 @@ var AgentBuilder = class {
|
|
|
2776
2797
|
constructor(deps) {
|
|
2777
2798
|
this.deps = deps;
|
|
2778
2799
|
}
|
|
2800
|
+
/** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
|
|
2779
2801
|
model(m) {
|
|
2780
2802
|
this.opts.model = m;
|
|
2781
2803
|
return this;
|
|
@@ -3125,6 +3147,69 @@ function isLocalAgentId(id) {
|
|
|
3125
3147
|
return id.startsWith(PREFIX.localAgent);
|
|
3126
3148
|
}
|
|
3127
3149
|
|
|
3150
|
+
// src/internal/runtime/config/default-model.ts
|
|
3151
|
+
var DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
|
|
3152
|
+
|
|
3153
|
+
// src/agent-generate.ts
|
|
3154
|
+
async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
|
|
3155
|
+
const { output, maxRetries, errorStrategy, ...sendOptions } = options;
|
|
3156
|
+
const run = await agent.send(input, sendOptions);
|
|
3157
|
+
const result = await run.wait();
|
|
3158
|
+
const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
|
|
3159
|
+
const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
|
|
3160
|
+
const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
|
|
3161
|
+
const facade = getAgentFacade2();
|
|
3162
|
+
const structured = await generateObjectImpl2(
|
|
3163
|
+
{
|
|
3164
|
+
prompt: answer,
|
|
3165
|
+
schema: output,
|
|
3166
|
+
// `agentModel` arrives already normalized (`this.model` passed through
|
|
3167
|
+
// `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
|
|
3168
|
+
// `string | ModelSelection` field only ever receives a `ModelSelection` here.
|
|
3169
|
+
model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
|
|
3170
|
+
// `local` is required to keep the transient structuring agent local-only;
|
|
3171
|
+
// default to the process cwd when the agent had no explicit local config.
|
|
3172
|
+
local: agentLocal ?? { cwd: process.cwd() },
|
|
3173
|
+
...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
|
|
3174
|
+
...maxRetries !== void 0 ? { maxRetries } : {},
|
|
3175
|
+
...errorStrategy !== void 0 ? { errorStrategy } : {}
|
|
3176
|
+
},
|
|
3177
|
+
{
|
|
3178
|
+
create: (opts) => facade.create(opts),
|
|
3179
|
+
delete: (agentId) => facade.delete(agentId)
|
|
3180
|
+
}
|
|
3181
|
+
);
|
|
3182
|
+
return {
|
|
3183
|
+
object: structured.object,
|
|
3184
|
+
result,
|
|
3185
|
+
raw: structured.raw,
|
|
3186
|
+
usage: structured.usage
|
|
3187
|
+
};
|
|
3188
|
+
}
|
|
3189
|
+
function structurableAnswerOrThrow(result, GenerateObjectError2) {
|
|
3190
|
+
if (result.status === "error") {
|
|
3191
|
+
throw new GenerateObjectError2(
|
|
3192
|
+
"no_tool_call",
|
|
3193
|
+
`Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
|
|
3194
|
+
result.error
|
|
3195
|
+
);
|
|
3196
|
+
}
|
|
3197
|
+
if (result.status === "cancelled") {
|
|
3198
|
+
throw new GenerateObjectError2(
|
|
3199
|
+
"no_tool_call",
|
|
3200
|
+
"Agent run was cancelled before an answer could be structured."
|
|
3201
|
+
);
|
|
3202
|
+
}
|
|
3203
|
+
const answer = result.result;
|
|
3204
|
+
if (answer === void 0 || answer.length === 0) {
|
|
3205
|
+
throw new GenerateObjectError2(
|
|
3206
|
+
"no_tool_call",
|
|
3207
|
+
"The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
|
|
3208
|
+
);
|
|
3209
|
+
}
|
|
3210
|
+
return answer;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3128
3213
|
// src/internal/runtime/cloud/cloud-agent.ts
|
|
3129
3214
|
init_errors();
|
|
3130
3215
|
init_cwd_mutex();
|
|
@@ -3275,8 +3360,19 @@ function safeFilenameForId(id, options) {
|
|
|
3275
3360
|
return `h-${crypto.createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
|
|
3276
3361
|
}
|
|
3277
3362
|
|
|
3278
|
-
// src/internal/runtime/
|
|
3279
|
-
|
|
3363
|
+
// src/internal/runtime/model-selection.ts
|
|
3364
|
+
init_errors();
|
|
3365
|
+
function normalizeModel(m) {
|
|
3366
|
+
if (m === void 0 || typeof m !== "string") return m;
|
|
3367
|
+
const id = m.trim();
|
|
3368
|
+
if (id.length === 0) {
|
|
3369
|
+
throw new ConfigurationError(
|
|
3370
|
+
'model must be a non-empty "provider/model" id string or a ModelSelection object',
|
|
3371
|
+
{ code: "invalid_model_selection" }
|
|
3372
|
+
);
|
|
3373
|
+
}
|
|
3374
|
+
return { id };
|
|
3375
|
+
}
|
|
3280
3376
|
|
|
3281
3377
|
// src/internal/runtime/registry/agent-registry-store.ts
|
|
3282
3378
|
init_cwd_mutex();
|
|
@@ -3353,7 +3449,10 @@ var REGISTRY_RELATIVE_PATH = path.join(".theokit", "agents", "registry.json");
|
|
|
3353
3449
|
function stripSecretsFromOptions(options) {
|
|
3354
3450
|
return assignDefined({
|
|
3355
3451
|
name: options.name,
|
|
3356
|
-
model:
|
|
3452
|
+
model: (() => {
|
|
3453
|
+
const m = normalizeModel(options.model);
|
|
3454
|
+
return m !== void 0 ? { id: m.id } : void 0;
|
|
3455
|
+
})(),
|
|
3357
3456
|
systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
|
|
3358
3457
|
local: serializeLocal(options.local),
|
|
3359
3458
|
cloud: serializeCloud(options.cloud),
|
|
@@ -3638,7 +3737,8 @@ function serializeCloudAgentConfig(options) {
|
|
|
3638
3737
|
cloud: serializeCloud2(options.cloud)
|
|
3639
3738
|
};
|
|
3640
3739
|
if (typeof options.agentId === "string") payload.agentId = options.agentId;
|
|
3641
|
-
|
|
3740
|
+
const cfgModel = normalizeModel(options.model);
|
|
3741
|
+
if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
|
|
3642
3742
|
if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
|
|
3643
3743
|
const skills = serializeSkills(options.skills);
|
|
3644
3744
|
if (skills !== void 0) payload.skills = skills;
|
|
@@ -4534,6 +4634,7 @@ function applyScriptMetrics(base, script) {
|
|
|
4534
4634
|
if (script.cost !== void 0) base.cost = script.cost;
|
|
4535
4635
|
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
4536
4636
|
if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
|
|
4637
|
+
if (script.origin !== void 0) base.origin = script.origin;
|
|
4537
4638
|
}
|
|
4538
4639
|
|
|
4539
4640
|
// src/internal/runtime/cloud/cloud-run.ts
|
|
@@ -4889,7 +4990,7 @@ var CloudAgent = class {
|
|
|
4889
4990
|
disposed = false;
|
|
4890
4991
|
constructor(options, providedAgentId) {
|
|
4891
4992
|
this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
|
|
4892
|
-
this.model = options.model;
|
|
4993
|
+
this.model = normalizeModel(options.model);
|
|
4893
4994
|
this.options = options;
|
|
4894
4995
|
this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
|
|
4895
4996
|
const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
|
|
@@ -4919,6 +5020,17 @@ var CloudAgent = class {
|
|
|
4919
5020
|
const apiKey = resolveApiKey(this.options.apiKey);
|
|
4920
5021
|
return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
|
|
4921
5022
|
}
|
|
5023
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
5024
|
+
generate(message, options) {
|
|
5025
|
+
return agentGenerate(
|
|
5026
|
+
this,
|
|
5027
|
+
this.model,
|
|
5028
|
+
this.options.apiKey,
|
|
5029
|
+
this.options.local,
|
|
5030
|
+
message,
|
|
5031
|
+
options
|
|
5032
|
+
);
|
|
5033
|
+
}
|
|
4922
5034
|
async send(message, options = {}) {
|
|
4923
5035
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
4924
5036
|
throw new ConfigurationError(
|
|
@@ -4949,7 +5061,7 @@ var CloudAgent = class {
|
|
|
4949
5061
|
});
|
|
4950
5062
|
}
|
|
4951
5063
|
async sendLocked(message, options) {
|
|
4952
|
-
const overrideModel = options.model;
|
|
5064
|
+
const overrideModel = normalizeModel(options.model);
|
|
4953
5065
|
if (overrideModel !== void 0) {
|
|
4954
5066
|
this.model = overrideModel;
|
|
4955
5067
|
updateRegisteredAgent(this.agentId, { model: overrideModel });
|
|
@@ -5863,18 +5975,18 @@ var ALL_ADAPTERS = [
|
|
|
5863
5975
|
arizeAdapter,
|
|
5864
5976
|
braintrustAdapter
|
|
5865
5977
|
];
|
|
5866
|
-
var
|
|
5978
|
+
var registered2 = /* @__PURE__ */ new Set();
|
|
5867
5979
|
function tryAutoRegisterAdapters(settings) {
|
|
5868
5980
|
if (settings?.enabled !== true) return;
|
|
5869
5981
|
if (settings.autoDetect === false) return;
|
|
5870
5982
|
const disabled = new Set(settings.disable ?? []);
|
|
5871
5983
|
for (const adapter of ALL_ADAPTERS) {
|
|
5872
|
-
if (
|
|
5984
|
+
if (registered2.has(adapter.moduleName)) continue;
|
|
5873
5985
|
if (disabled.has(adapter.displayName.toLowerCase())) continue;
|
|
5874
5986
|
if (!adapter.detect()) continue;
|
|
5875
5987
|
try {
|
|
5876
5988
|
adapter.register();
|
|
5877
|
-
|
|
5989
|
+
registered2.add(adapter.moduleName);
|
|
5878
5990
|
process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
|
|
5879
5991
|
`);
|
|
5880
5992
|
} catch (cause) {
|
|
@@ -6437,6 +6549,26 @@ function paginate(items, opts) {
|
|
|
6437
6549
|
return items.slice(start, end);
|
|
6438
6550
|
}
|
|
6439
6551
|
|
|
6552
|
+
// src/internal/persistence/session-meta.ts
|
|
6553
|
+
function applyMetaPatch(current, patch) {
|
|
6554
|
+
const next = {};
|
|
6555
|
+
if (current.title !== void 0) next.title = current.title;
|
|
6556
|
+
if (current.tag !== void 0) next.tag = current.tag;
|
|
6557
|
+
if (patch.title === null) delete next.title;
|
|
6558
|
+
else if (patch.title !== void 0) next.title = patch.title;
|
|
6559
|
+
if (patch.tag === null) delete next.tag;
|
|
6560
|
+
else if (patch.tag !== void 0) next.tag = patch.tag;
|
|
6561
|
+
return next;
|
|
6562
|
+
}
|
|
6563
|
+
function coerceSessionMeta(raw) {
|
|
6564
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
6565
|
+
const obj = raw;
|
|
6566
|
+
const meta = {};
|
|
6567
|
+
if (typeof obj.title === "string") meta.title = obj.title;
|
|
6568
|
+
if (typeof obj.tag === "string") meta.tag = obj.tag;
|
|
6569
|
+
return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
|
|
6570
|
+
}
|
|
6571
|
+
|
|
6440
6572
|
// src/internal/persistence/conversation-storage-fs.ts
|
|
6441
6573
|
var FileSystemConversationStorage = class {
|
|
6442
6574
|
#root;
|
|
@@ -6487,6 +6619,37 @@ var FileSystemConversationStorage = class {
|
|
|
6487
6619
|
async compact(conversationId, maxTurns) {
|
|
6488
6620
|
await compactSessionFile(this.#root, conversationId, maxTurns);
|
|
6489
6621
|
}
|
|
6622
|
+
// SE4 — session metadata persisted as a per-conversation sidecar
|
|
6623
|
+
// `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
|
|
6624
|
+
// the transcript). Kept separate from messages.jsonl so a title/tag write does
|
|
6625
|
+
// not rewrite the append-only log.
|
|
6626
|
+
#metaPath(conversationId) {
|
|
6627
|
+
const safe3 = sanitizeIdentifier(conversationId, { maxLen: 128 });
|
|
6628
|
+
return safePathJoin(this.#root, ".theokit", "agents", safe3, "session.json");
|
|
6629
|
+
}
|
|
6630
|
+
async getSessionMeta(conversationId) {
|
|
6631
|
+
try {
|
|
6632
|
+
const raw = await promises.readFile(this.#metaPath(conversationId), "utf8");
|
|
6633
|
+
return coerceSessionMeta(JSON.parse(raw));
|
|
6634
|
+
} catch (cause) {
|
|
6635
|
+
if (cause.code === "ENOENT") return void 0;
|
|
6636
|
+
throw cause;
|
|
6637
|
+
}
|
|
6638
|
+
}
|
|
6639
|
+
async setSessionMeta(conversationId, patch) {
|
|
6640
|
+
const metaPath = this.#metaPath(conversationId);
|
|
6641
|
+
await promises.mkdir(path.dirname(metaPath), { recursive: true });
|
|
6642
|
+
await withFileLock(metaPath, async () => {
|
|
6643
|
+
let current = {};
|
|
6644
|
+
try {
|
|
6645
|
+
current = coerceSessionMeta(JSON.parse(await promises.readFile(metaPath, "utf8"))) ?? {};
|
|
6646
|
+
} catch (cause) {
|
|
6647
|
+
if (cause.code !== "ENOENT") throw cause;
|
|
6648
|
+
}
|
|
6649
|
+
const next = applyMetaPatch(current, patch);
|
|
6650
|
+
await promises.writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
|
|
6651
|
+
});
|
|
6652
|
+
}
|
|
6490
6653
|
async dispose() {
|
|
6491
6654
|
}
|
|
6492
6655
|
};
|
|
@@ -8336,23 +8499,27 @@ function tryParseSkill(raw, fallbackName, source, options) {
|
|
|
8336
8499
|
|
|
8337
8500
|
// src/internal/runtime/skills/skills-manager.ts
|
|
8338
8501
|
var SkillsManager = class {
|
|
8339
|
-
constructor(cwd, _enabled, settingSourcesIncludeProject) {
|
|
8502
|
+
constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
|
|
8340
8503
|
this.cwd = cwd;
|
|
8341
8504
|
this.settingSourcesIncludeProject = settingSourcesIncludeProject;
|
|
8505
|
+
this.skillsDir = skillsDir;
|
|
8506
|
+
this.inline = inline;
|
|
8342
8507
|
}
|
|
8343
8508
|
cwd;
|
|
8344
8509
|
settingSourcesIncludeProject;
|
|
8510
|
+
skillsDir;
|
|
8511
|
+
inline;
|
|
8345
8512
|
skills = [];
|
|
8346
8513
|
async initialize() {
|
|
8347
8514
|
if (!this.settingSourcesIncludeProject) {
|
|
8348
|
-
this.skills = [];
|
|
8515
|
+
this.skills = this.mergeInline([]);
|
|
8349
8516
|
return;
|
|
8350
8517
|
}
|
|
8351
8518
|
await this.refresh();
|
|
8352
8519
|
}
|
|
8353
8520
|
async refresh() {
|
|
8354
|
-
const skillsRoot = path.join(this.cwd, ".theokit", "skills");
|
|
8355
|
-
|
|
8521
|
+
const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
|
|
8522
|
+
const discovered = await discoverSkills(skillsRoot, {
|
|
8356
8523
|
onInvalidSkill: (info) => {
|
|
8357
8524
|
process.stderr.write(
|
|
8358
8525
|
`[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
|
|
@@ -8360,6 +8527,13 @@ var SkillsManager = class {
|
|
|
8360
8527
|
);
|
|
8361
8528
|
}
|
|
8362
8529
|
});
|
|
8530
|
+
this.skills = this.mergeInline(discovered);
|
|
8531
|
+
}
|
|
8532
|
+
/** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
|
|
8533
|
+
mergeInline(discovered) {
|
|
8534
|
+
if (this.inline === void 0 || this.inline.length === 0) return discovered;
|
|
8535
|
+
const inlineNames = new Set(this.inline.map((s) => s.name));
|
|
8536
|
+
return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
|
|
8363
8537
|
}
|
|
8364
8538
|
list() {
|
|
8365
8539
|
return Promise.resolve(this.skills);
|
|
@@ -8395,7 +8569,7 @@ function bootstrapSubmanagers(args) {
|
|
|
8395
8569
|
const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
|
|
8396
8570
|
if (providerCount > 0 || args.options.providers !== void 0) {
|
|
8397
8571
|
out.providers = new ProvidersManagerImpl(
|
|
8398
|
-
args.options.model,
|
|
8572
|
+
normalizeModel(args.options.model),
|
|
8399
8573
|
args.options.providers,
|
|
8400
8574
|
args.options.plugins
|
|
8401
8575
|
);
|
|
@@ -8404,7 +8578,10 @@ function bootstrapSubmanagers(args) {
|
|
|
8404
8578
|
out.skillsManager = new SkillsManager(
|
|
8405
8579
|
args.workspaceCwd,
|
|
8406
8580
|
args.options.skills?.enabled,
|
|
8407
|
-
args.settingSourcesIncludeProject
|
|
8581
|
+
args.settingSourcesIncludeProject,
|
|
8582
|
+
// M22 — custom skills directory + inline (code-defined) skills.
|
|
8583
|
+
args.options.skills?.skillsDir,
|
|
8584
|
+
args.options.skills?.inline
|
|
8408
8585
|
);
|
|
8409
8586
|
const localSkills = out.skillsManager;
|
|
8410
8587
|
out.skills = { list: () => localSkills.list() };
|
|
@@ -8462,6 +8639,7 @@ function createLocalRun(options) {
|
|
|
8462
8639
|
projectMcpServers: options.projectMcpServers,
|
|
8463
8640
|
...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
|
|
8464
8641
|
});
|
|
8642
|
+
if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
|
|
8465
8643
|
const handle = new LocalRun({
|
|
8466
8644
|
id,
|
|
8467
8645
|
agentId: options.agentId,
|
|
@@ -9110,6 +9288,15 @@ async function emitReasoningDeltaCallback(inputs, text) {
|
|
|
9110
9288
|
);
|
|
9111
9289
|
}
|
|
9112
9290
|
|
|
9291
|
+
// src/types/run-events.ts
|
|
9292
|
+
function emitRunEvent(sink, event) {
|
|
9293
|
+
if (sink === void 0) return;
|
|
9294
|
+
try {
|
|
9295
|
+
sink(event);
|
|
9296
|
+
} catch {
|
|
9297
|
+
}
|
|
9298
|
+
}
|
|
9299
|
+
|
|
9113
9300
|
// src/internal/agent-loop/tool-dispatch.ts
|
|
9114
9301
|
init_async_local_storage();
|
|
9115
9302
|
|
|
@@ -9207,6 +9394,22 @@ function coerceArgsToSchema(args, schema) {
|
|
|
9207
9394
|
return { value: out, changed };
|
|
9208
9395
|
}
|
|
9209
9396
|
|
|
9397
|
+
// src/tool-error.ts
|
|
9398
|
+
init_errors();
|
|
9399
|
+
var ToolError = class extends TheokitAgentError {
|
|
9400
|
+
name = "ToolError";
|
|
9401
|
+
/** The error content surfaced to the model: a string, or text/image blocks. */
|
|
9402
|
+
content;
|
|
9403
|
+
constructor(content, options = {}) {
|
|
9404
|
+
super(renderToolErrorMessage(content), { ...options, isRetryable: false });
|
|
9405
|
+
this.content = content;
|
|
9406
|
+
}
|
|
9407
|
+
};
|
|
9408
|
+
function renderToolErrorMessage(content) {
|
|
9409
|
+
if (typeof content === "string") return content;
|
|
9410
|
+
return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
|
|
9411
|
+
}
|
|
9412
|
+
|
|
9210
9413
|
// src/internal/runtime/tools/shell-tool.ts
|
|
9211
9414
|
async function runShell(options) {
|
|
9212
9415
|
if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
|
|
@@ -9260,9 +9463,13 @@ async function runHandlerTool(kind, handler, call, signal, context) {
|
|
|
9260
9463
|
return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
|
|
9261
9464
|
}
|
|
9262
9465
|
try {
|
|
9263
|
-
const
|
|
9264
|
-
return { stdout, stderr: "", exitCode: 0 };
|
|
9466
|
+
const out = await handler(call.input, { signal, context });
|
|
9467
|
+
if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
|
|
9468
|
+
return { stdout: out, stderr: "", exitCode: 0 };
|
|
9265
9469
|
} catch (cause) {
|
|
9470
|
+
if (cause instanceof ToolError) {
|
|
9471
|
+
return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
|
|
9472
|
+
}
|
|
9266
9473
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
9267
9474
|
return { stdout: "", stderr: message, exitCode: 1 };
|
|
9268
9475
|
}
|
|
@@ -9381,6 +9588,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
|
|
|
9381
9588
|
toolSpan?.end();
|
|
9382
9589
|
return fileVeto;
|
|
9383
9590
|
}
|
|
9591
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9592
|
+
type: "tool_progress",
|
|
9593
|
+
toolName: workingCall.name,
|
|
9594
|
+
toolCallId: callId
|
|
9595
|
+
});
|
|
9384
9596
|
const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
|
|
9385
9597
|
await inputs.pluginManager?.runPostToolCallHooks({
|
|
9386
9598
|
name: workingCall.name,
|
|
@@ -9407,6 +9619,13 @@ function applyRepairAndExtractCall(tools, call) {
|
|
|
9407
9619
|
function vetoFromForkWhitelist(inputs, call, callId, events) {
|
|
9408
9620
|
const whitelistDecision = checkToolWhitelist(call.name);
|
|
9409
9621
|
if (whitelistDecision.allowed) return void 0;
|
|
9622
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9623
|
+
type: "permission_denied",
|
|
9624
|
+
toolName: call.name,
|
|
9625
|
+
toolCallId: callId,
|
|
9626
|
+
source: "fork_whitelist",
|
|
9627
|
+
message: whitelistDecision.reason ?? "tool not available in fork"
|
|
9628
|
+
});
|
|
9410
9629
|
events.push(buildToolUseRunning(inputs, callId, call));
|
|
9411
9630
|
events.push(
|
|
9412
9631
|
buildToolUseCompleted(inputs, callId, call, {
|
|
@@ -9443,6 +9662,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
|
|
|
9443
9662
|
runId: inputs.runId
|
|
9444
9663
|
});
|
|
9445
9664
|
if (pluginVeto === void 0) return void 0;
|
|
9665
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9666
|
+
type: "permission_denied",
|
|
9667
|
+
toolName: call.name,
|
|
9668
|
+
toolCallId: callId,
|
|
9669
|
+
source: "plugin",
|
|
9670
|
+
message: pluginVeto.message
|
|
9671
|
+
});
|
|
9446
9672
|
events.push(
|
|
9447
9673
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9448
9674
|
stdout: "",
|
|
@@ -9465,6 +9691,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
|
|
|
9465
9691
|
runId: inputs.runId
|
|
9466
9692
|
});
|
|
9467
9693
|
if (!preDecision.blocked) return void 0;
|
|
9694
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9695
|
+
type: "permission_denied",
|
|
9696
|
+
toolName: call.name,
|
|
9697
|
+
toolCallId: callId,
|
|
9698
|
+
source: "file_hook",
|
|
9699
|
+
message: preDecision.reason ?? "blocked by hook"
|
|
9700
|
+
});
|
|
9468
9701
|
events.push(
|
|
9469
9702
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9470
9703
|
stdout: "",
|
|
@@ -9508,7 +9741,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
|
|
|
9508
9741
|
await safeEmitToolHook(inputs.onToolEnd, {
|
|
9509
9742
|
toolName: call.name,
|
|
9510
9743
|
args: call.input,
|
|
9511
|
-
|
|
9744
|
+
// SE7 — a block-returning handler has empty `stdout`; surface its structured
|
|
9745
|
+
// content to the hook instead of an empty string.
|
|
9746
|
+
result: result.content !== void 0 ? result.content : result.stdout,
|
|
9512
9747
|
conversationId: inputs.agentId,
|
|
9513
9748
|
callId,
|
|
9514
9749
|
durationMs
|
|
@@ -9530,7 +9765,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9530
9765
|
output: {
|
|
9531
9766
|
stdout: result.stdout,
|
|
9532
9767
|
stderr: result.stderr,
|
|
9533
|
-
exitCode: result.exitCode ?? 0
|
|
9768
|
+
exitCode: result.exitCode ?? 0,
|
|
9769
|
+
// SE7 — structured content (text + image blocks) when the handler
|
|
9770
|
+
// returned/threw blocks; absent for the string path.
|
|
9771
|
+
...result.content !== void 0 ? { content: result.content } : {}
|
|
9534
9772
|
},
|
|
9535
9773
|
agentId: inputs.agentId,
|
|
9536
9774
|
runId: inputs.runId
|
|
@@ -9543,7 +9781,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9543
9781
|
return {
|
|
9544
9782
|
type: "tool_result",
|
|
9545
9783
|
toolUseId: call.id,
|
|
9546
|
-
content
|
|
9784
|
+
// SE7 — structured content blocks (handler-returned or ToolError-carried)
|
|
9785
|
+
// are authoritative; otherwise the legacy string rendering.
|
|
9786
|
+
content: result.content !== void 0 ? result.content : renderToolResult(result),
|
|
9547
9787
|
...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
|
|
9548
9788
|
};
|
|
9549
9789
|
}
|
|
@@ -9592,6 +9832,29 @@ function buildToolUseCompleted(inputs, callId, call, result) {
|
|
|
9592
9832
|
};
|
|
9593
9833
|
}
|
|
9594
9834
|
|
|
9835
|
+
// src/internal/llm/tool-result-content.ts
|
|
9836
|
+
init_errors();
|
|
9837
|
+
function toBlockToolResultContent(content) {
|
|
9838
|
+
return content;
|
|
9839
|
+
}
|
|
9840
|
+
function toStringToolResultContent(content, providerName) {
|
|
9841
|
+
if (typeof content === "string") return content;
|
|
9842
|
+
if (content.some((block) => block.type === "image")) {
|
|
9843
|
+
throw new ConfigurationError(
|
|
9844
|
+
`provider "${providerName}" does not support image content in tool results`
|
|
9845
|
+
);
|
|
9846
|
+
}
|
|
9847
|
+
return content.filter(
|
|
9848
|
+
(block) => block.type === "text"
|
|
9849
|
+
).map((block) => block.text).join("\n");
|
|
9850
|
+
}
|
|
9851
|
+
function renderToolResultContentText(content, fn) {
|
|
9852
|
+
if (typeof content === "string") return fn(content);
|
|
9853
|
+
return content.map(
|
|
9854
|
+
(block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
|
|
9855
|
+
);
|
|
9856
|
+
}
|
|
9857
|
+
|
|
9595
9858
|
// src/internal/agent-loop/tool-result-guard.ts
|
|
9596
9859
|
var OPEN = "<untrusted-tool-output>";
|
|
9597
9860
|
var CLOSE = "</untrusted-tool-output>";
|
|
@@ -9617,7 +9880,11 @@ ${CLOSE}`;
|
|
|
9617
9880
|
function applyToolResultGuard(parts, opts) {
|
|
9618
9881
|
if (opts.delimit !== true && opts.redactPii !== true) return parts;
|
|
9619
9882
|
return parts.map(
|
|
9620
|
-
(p) =>
|
|
9883
|
+
(p) => (
|
|
9884
|
+
// SE7 — guard the TEXT of a tool result (string or the text blocks of a
|
|
9885
|
+
// structured content); image blocks pass through untouched.
|
|
9886
|
+
p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
|
|
9887
|
+
)
|
|
9621
9888
|
);
|
|
9622
9889
|
}
|
|
9623
9890
|
|
|
@@ -10534,10 +10801,10 @@ function stripVertexPrefix(modelId) {
|
|
|
10534
10801
|
}
|
|
10535
10802
|
|
|
10536
10803
|
// src/internal/providers/builtin/index.ts
|
|
10537
|
-
var
|
|
10804
|
+
var registered3 = false;
|
|
10538
10805
|
function registerBuiltins() {
|
|
10539
|
-
if (
|
|
10540
|
-
|
|
10806
|
+
if (registered3) return;
|
|
10807
|
+
registered3 = true;
|
|
10541
10808
|
registerProvider(ANTHROPIC);
|
|
10542
10809
|
registerProvider(OPENAI);
|
|
10543
10810
|
registerProvider(OPENROUTER);
|
|
@@ -10765,7 +11032,9 @@ function toAnthropicWireMessage(message) {
|
|
|
10765
11032
|
return {
|
|
10766
11033
|
type: "tool_result",
|
|
10767
11034
|
tool_use_id: part.toolUseId,
|
|
10768
|
-
|
|
11035
|
+
// SE7 — this wire is block-capable: strings pass through, structured
|
|
11036
|
+
// text/image blocks are forwarded natively.
|
|
11037
|
+
content: toBlockToolResultContent(part.content),
|
|
10769
11038
|
...part.isError === true ? { is_error: true } : {}
|
|
10770
11039
|
};
|
|
10771
11040
|
});
|
|
@@ -11557,7 +11826,8 @@ function toOllamaMessages(message) {
|
|
|
11557
11826
|
if (part.type === "tool_result") {
|
|
11558
11827
|
out.push({
|
|
11559
11828
|
role: "tool",
|
|
11560
|
-
|
|
11829
|
+
// SE7 — string-only tool role: text blocks flatten; image fails fast.
|
|
11830
|
+
content: toStringToolResultContent(part.content, "ollama"),
|
|
11561
11831
|
tool_name: part.toolUseId
|
|
11562
11832
|
});
|
|
11563
11833
|
}
|
|
@@ -12094,7 +12364,9 @@ function userOrToolMessages(message) {
|
|
|
12094
12364
|
out.push({
|
|
12095
12365
|
role: "tool",
|
|
12096
12366
|
tool_call_id: part.toolUseId,
|
|
12097
|
-
|
|
12367
|
+
// SE7 — this wire's tool role is string-only: text blocks flatten; an
|
|
12368
|
+
// image block fails fast (ConfigurationError).
|
|
12369
|
+
content: toStringToolResultContent(part.content, "openai")
|
|
12098
12370
|
});
|
|
12099
12371
|
}
|
|
12100
12372
|
}
|
|
@@ -13023,18 +13295,20 @@ function levenshtein(a, b) {
|
|
|
13023
13295
|
function createRealLocalRun(options) {
|
|
13024
13296
|
const { userText, id, startTime } = prepareRunContext(options.message);
|
|
13025
13297
|
const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
|
|
13026
|
-
const
|
|
13298
|
+
const runScript = {
|
|
13027
13299
|
events: [],
|
|
13028
13300
|
finalStatus: "running",
|
|
13029
13301
|
cancellable: false,
|
|
13030
|
-
conversation: []
|
|
13302
|
+
conversation: [],
|
|
13303
|
+
// SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
|
|
13304
|
+
...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
|
|
13031
13305
|
};
|
|
13032
13306
|
const handle = new RealLocalRun(
|
|
13033
13307
|
{
|
|
13034
13308
|
id,
|
|
13035
13309
|
agentId: options.agentId,
|
|
13036
13310
|
model: options.model,
|
|
13037
|
-
script:
|
|
13311
|
+
script: runScript,
|
|
13038
13312
|
supportedOps: supported,
|
|
13039
13313
|
startTime
|
|
13040
13314
|
},
|
|
@@ -13146,6 +13420,8 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
13146
13420
|
// M7 — forward SendOptions.context to the loop so every tool handler receives
|
|
13147
13421
|
// it on `ctx.context` (shared run config set once, e.g. projectRoot).
|
|
13148
13422
|
...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
|
|
13423
|
+
// SE2 — forward the opt-in typed runtime-event sink to the loop.
|
|
13424
|
+
...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
|
|
13149
13425
|
// #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
|
|
13150
13426
|
// can enable them via SendOptions (not only internal AgentLoopInputs).
|
|
13151
13427
|
...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
|
|
@@ -15838,7 +16114,7 @@ function wrapRunWithPostReplyHook(args) {
|
|
|
15838
16114
|
async function executeSendLocked(inputs, message, options) {
|
|
15839
16115
|
if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
|
|
15840
16116
|
await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
|
|
15841
|
-
inputs.applyModelOverride(options.model);
|
|
16117
|
+
inputs.applyModelOverride(normalizeModel(options.model));
|
|
15842
16118
|
const userText = typeof message === "string" ? message : message.text;
|
|
15843
16119
|
if (inputs.options.onBeforeSend !== void 0) {
|
|
15844
16120
|
await inputs.options.onBeforeSend({
|
|
@@ -15990,7 +16266,7 @@ var LocalAgent = class {
|
|
|
15990
16266
|
constructor(options) {
|
|
15991
16267
|
this.agentId = options.agentId ?? generateLocalAgentId();
|
|
15992
16268
|
this._telemetry = createTelemetry(options.telemetry);
|
|
15993
|
-
this.model = options.model;
|
|
16269
|
+
this.model = normalizeModel(options.model);
|
|
15994
16270
|
this.options = options;
|
|
15995
16271
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
15996
16272
|
this.conversationStorage = options.conversationStorage;
|
|
@@ -16057,6 +16333,11 @@ var LocalAgent = class {
|
|
|
16057
16333
|
hooks() {
|
|
16058
16334
|
return this.hooksExecutor;
|
|
16059
16335
|
}
|
|
16336
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
16337
|
+
generate(message, options) {
|
|
16338
|
+
const { apiKey, local } = this.options;
|
|
16339
|
+
return agentGenerate(this, this.model, apiKey, local, message, options);
|
|
16340
|
+
}
|
|
16060
16341
|
async send(message, options = {}) {
|
|
16061
16342
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
16062
16343
|
validateToolCatalog(options.tools);
|
|
@@ -16296,6 +16577,7 @@ function includesSetting(options, source) {
|
|
|
16296
16577
|
|
|
16297
16578
|
// src/agent-helpers.ts
|
|
16298
16579
|
async function runCreateUnderSpan(options, span) {
|
|
16580
|
+
options = { ...options, model: normalizeModel(options.model) };
|
|
16299
16581
|
validateAgentOptions(options);
|
|
16300
16582
|
validateCloudToolParity(options);
|
|
16301
16583
|
await guardAgainstIdCollision(options);
|
|
@@ -16369,7 +16651,10 @@ async function createLocalAgent(options) {
|
|
|
16369
16651
|
const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
|
|
16370
16652
|
const shape = validateApiKeyShape(apiKey, {
|
|
16371
16653
|
strict: willFlowToProvider,
|
|
16372
|
-
|
|
16654
|
+
// `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
|
|
16655
|
+
// here is the idempotent narrowing of the widened public type (`{id}` passes
|
|
16656
|
+
// through by reference) — cleaner than an `as` cast.
|
|
16657
|
+
...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
|
|
16373
16658
|
});
|
|
16374
16659
|
if (shape.malformed) {
|
|
16375
16660
|
throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
|
|
@@ -16435,6 +16720,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
|
|
|
16435
16720
|
...existing.options,
|
|
16436
16721
|
...options,
|
|
16437
16722
|
...mergedLocal !== void 0 ? { local: mergedLocal } : {},
|
|
16723
|
+
// SE8 — normalize a caller-supplied bare-string model override at this resume
|
|
16724
|
+
// boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
|
|
16725
|
+
// honors it; local resume forces the persisted model below.
|
|
16726
|
+
model: normalizeModel(options.model ?? existing.options.model),
|
|
16438
16727
|
mcpServers: void 0,
|
|
16439
16728
|
agentId
|
|
16440
16729
|
};
|
|
@@ -16801,6 +17090,7 @@ async function getOrCreateUncached(agentId, options) {
|
|
|
16801
17090
|
}
|
|
16802
17091
|
setAgentFacade({
|
|
16803
17092
|
create: (options) => Agent.create(options),
|
|
17093
|
+
delete: (agentId) => Agent.delete(agentId),
|
|
16804
17094
|
prompt: (message, options) => Agent.prompt(message, options),
|
|
16805
17095
|
get: (agentId) => Agent.get(agentId),
|
|
16806
17096
|
resume: (agentId, options) => Agent.resume(agentId, options),
|