@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/cron.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');
|
|
@@ -513,6 +513,256 @@ var init_errors = __esm({
|
|
|
513
513
|
};
|
|
514
514
|
}
|
|
515
515
|
});
|
|
516
|
+
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
517
|
+
return zod.toJSONSchema(schema, options);
|
|
518
|
+
}
|
|
519
|
+
var init_to_json_schema = __esm({
|
|
520
|
+
"src/internal/zod/to-json-schema.ts"() {
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
function requireZod() {
|
|
524
|
+
if (cachedZ !== void 0) return cachedZ;
|
|
525
|
+
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cron.cjs', document.baseURI).href)));
|
|
526
|
+
let mod;
|
|
527
|
+
try {
|
|
528
|
+
mod = r("zod");
|
|
529
|
+
} catch (cause) {
|
|
530
|
+
throw new ConfigurationError(
|
|
531
|
+
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
532
|
+
{ code: "zod_not_installed", cause }
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
cachedZ = mod.z ?? mod;
|
|
536
|
+
return cachedZ;
|
|
537
|
+
}
|
|
538
|
+
function makeOutputTool(jsonSchema, onCapture) {
|
|
539
|
+
return {
|
|
540
|
+
name: "output",
|
|
541
|
+
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
542
|
+
inputSchema: jsonSchema,
|
|
543
|
+
handler: (input) => {
|
|
544
|
+
const out = onCapture(input);
|
|
545
|
+
if (typeof out === "string") return out;
|
|
546
|
+
if (out instanceof Promise) return out;
|
|
547
|
+
return "";
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
function buildTransientAgentOptions(params) {
|
|
552
|
+
return {
|
|
553
|
+
model: params.model,
|
|
554
|
+
local: params.local,
|
|
555
|
+
tools: [params.outputTool],
|
|
556
|
+
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
557
|
+
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
558
|
+
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
function extractUsage(result) {
|
|
562
|
+
const u = result.usage;
|
|
563
|
+
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
564
|
+
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
565
|
+
}
|
|
566
|
+
function buildToolPrompt(prompt) {
|
|
567
|
+
return `${prompt}
|
|
568
|
+
|
|
569
|
+
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
570
|
+
}
|
|
571
|
+
function setupStructuredOutput(schema, maxRetries) {
|
|
572
|
+
const z6 = requireZod();
|
|
573
|
+
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
574
|
+
return {
|
|
575
|
+
z: z6,
|
|
576
|
+
jsonSchema,
|
|
577
|
+
maxRetries: maxRetries ?? 1,
|
|
578
|
+
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
async function disposeAndDeleteTransient(agent, deletor) {
|
|
582
|
+
await agent.dispose();
|
|
583
|
+
try {
|
|
584
|
+
await deletor(agent.agentId);
|
|
585
|
+
} catch {
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
var cachedZ;
|
|
589
|
+
var init_structured_output_helpers = __esm({
|
|
590
|
+
"src/internal/structured-output-helpers.ts"() {
|
|
591
|
+
init_errors();
|
|
592
|
+
init_to_json_schema();
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// src/generate-object.ts
|
|
597
|
+
var generate_object_exports = {};
|
|
598
|
+
__export(generate_object_exports, {
|
|
599
|
+
GenerateObjectError: () => GenerateObjectError,
|
|
600
|
+
generateObjectImpl: () => generateObjectImpl
|
|
601
|
+
});
|
|
602
|
+
function salvagePartial(schema, raw) {
|
|
603
|
+
if (typeof raw !== "object" || raw === null) return raw;
|
|
604
|
+
const shape = schema.shape;
|
|
605
|
+
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
606
|
+
const rawObj = raw;
|
|
607
|
+
const out = {};
|
|
608
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
609
|
+
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
610
|
+
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
611
|
+
if (parsed.success) out[key] = parsed.data;
|
|
612
|
+
}
|
|
613
|
+
return out;
|
|
614
|
+
}
|
|
615
|
+
async function runReasoningPhase(options, deps) {
|
|
616
|
+
const reasoningOptions = {
|
|
617
|
+
model: options.model,
|
|
618
|
+
local: options.local,
|
|
619
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
620
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
621
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
622
|
+
};
|
|
623
|
+
const reasoningAgent = await deps.create(reasoningOptions);
|
|
624
|
+
try {
|
|
625
|
+
const run = await reasoningAgent.send(options.prompt);
|
|
626
|
+
const result = await run.wait();
|
|
627
|
+
const text = result.result;
|
|
628
|
+
return typeof text === "string" ? text : options.prompt;
|
|
629
|
+
} finally {
|
|
630
|
+
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
async function generateObjectImpl(options, deps) {
|
|
634
|
+
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
635
|
+
options.schema,
|
|
636
|
+
options.maxRetries
|
|
637
|
+
);
|
|
638
|
+
let capturedRaw;
|
|
639
|
+
let lastUsage = initialUsage;
|
|
640
|
+
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
641
|
+
class CaptureSentinel extends Error {
|
|
642
|
+
constructor(captured) {
|
|
643
|
+
super("generate-object-capture");
|
|
644
|
+
this.captured = captured;
|
|
645
|
+
}
|
|
646
|
+
captured;
|
|
647
|
+
[sentinel] = true;
|
|
648
|
+
}
|
|
649
|
+
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
650
|
+
if (capturedRaw === void 0) {
|
|
651
|
+
capturedRaw = input;
|
|
652
|
+
}
|
|
653
|
+
throw new CaptureSentinel(input);
|
|
654
|
+
});
|
|
655
|
+
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
656
|
+
const structuringModel = options.structuringModel ?? options.model;
|
|
657
|
+
const structuringPrompt = reasoningText ?? options.prompt;
|
|
658
|
+
const agentOptions = buildTransientAgentOptions({
|
|
659
|
+
model: structuringModel,
|
|
660
|
+
local: options.local,
|
|
661
|
+
outputTool,
|
|
662
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
663
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
664
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
665
|
+
});
|
|
666
|
+
const agent = await deps.create(agentOptions);
|
|
667
|
+
try {
|
|
668
|
+
const userMessage = buildToolPrompt(structuringPrompt);
|
|
669
|
+
let lastParseError;
|
|
670
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
671
|
+
capturedRaw = void 0;
|
|
672
|
+
const run = await agent.send(userMessage);
|
|
673
|
+
const result = await run.wait();
|
|
674
|
+
lastUsage = extractUsage(result);
|
|
675
|
+
if (capturedRaw === void 0) {
|
|
676
|
+
if (result.status === "error" && result.error !== void 0) {
|
|
677
|
+
throw new GenerateObjectError(
|
|
678
|
+
"no_tool_call",
|
|
679
|
+
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
680
|
+
result.error
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
if (attempt === maxRetries) {
|
|
684
|
+
throw new GenerateObjectError(
|
|
685
|
+
"no_tool_call",
|
|
686
|
+
"The model returned text instead of calling the `output` tool."
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
const parsed = options.schema.safeParse(capturedRaw);
|
|
692
|
+
if (parsed.success) {
|
|
693
|
+
return {
|
|
694
|
+
object: parsed.data,
|
|
695
|
+
raw: capturedRaw,
|
|
696
|
+
usage: lastUsage,
|
|
697
|
+
finishReason: "tool_use"
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
lastParseError = parsed.error;
|
|
701
|
+
}
|
|
702
|
+
if (options.errorStrategy === "return-raw") {
|
|
703
|
+
return {
|
|
704
|
+
object: capturedRaw,
|
|
705
|
+
raw: capturedRaw,
|
|
706
|
+
usage: lastUsage,
|
|
707
|
+
finishReason: "tool_use"
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
if (options.errorStrategy === "return-partial") {
|
|
711
|
+
return {
|
|
712
|
+
object: salvagePartial(options.schema, capturedRaw),
|
|
713
|
+
raw: capturedRaw,
|
|
714
|
+
usage: lastUsage,
|
|
715
|
+
finishReason: "tool_use"
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
throw new GenerateObjectError(
|
|
719
|
+
"parse_failed",
|
|
720
|
+
"Schema parse failed after all retries.",
|
|
721
|
+
lastParseError
|
|
722
|
+
);
|
|
723
|
+
} finally {
|
|
724
|
+
await disposeAndDeleteTransient(agent, deps.delete);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
var GenerateObjectError;
|
|
728
|
+
var init_generate_object = __esm({
|
|
729
|
+
"src/generate-object.ts"() {
|
|
730
|
+
init_structured_output_helpers();
|
|
731
|
+
GenerateObjectError = class extends Error {
|
|
732
|
+
name = "GenerateObjectError";
|
|
733
|
+
code;
|
|
734
|
+
cause;
|
|
735
|
+
constructor(code, message, cause) {
|
|
736
|
+
super(message);
|
|
737
|
+
this.code = code;
|
|
738
|
+
if (cause !== void 0) this.cause = cause;
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
745
|
+
var agent_factory_registry_exports = {};
|
|
746
|
+
__export(agent_factory_registry_exports, {
|
|
747
|
+
getAgentFacade: () => getAgentFacade,
|
|
748
|
+
setAgentFacade: () => setAgentFacade
|
|
749
|
+
});
|
|
750
|
+
function setAgentFacade(facade) {
|
|
751
|
+
registered = facade;
|
|
752
|
+
}
|
|
753
|
+
function getAgentFacade() {
|
|
754
|
+
if (registered === void 0) {
|
|
755
|
+
throw new Error(
|
|
756
|
+
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
return registered;
|
|
760
|
+
}
|
|
761
|
+
var registered;
|
|
762
|
+
var init_agent_factory_registry = __esm({
|
|
763
|
+
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
764
|
+
}
|
|
765
|
+
});
|
|
516
766
|
|
|
517
767
|
// src/internal/persistence/cwd-mutex.ts
|
|
518
768
|
function withCwdMutex(key, fn) {
|
|
@@ -1430,29 +1680,6 @@ var init_judge_call = __esm({
|
|
|
1430
1680
|
}
|
|
1431
1681
|
});
|
|
1432
1682
|
|
|
1433
|
-
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
1434
|
-
var agent_factory_registry_exports = {};
|
|
1435
|
-
__export(agent_factory_registry_exports, {
|
|
1436
|
-
getAgentFacade: () => getAgentFacade,
|
|
1437
|
-
setAgentFacade: () => setAgentFacade
|
|
1438
|
-
});
|
|
1439
|
-
function setAgentFacade(facade) {
|
|
1440
|
-
registered3 = facade;
|
|
1441
|
-
}
|
|
1442
|
-
function getAgentFacade() {
|
|
1443
|
-
if (registered3 === void 0) {
|
|
1444
|
-
throw new Error(
|
|
1445
|
-
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
1446
|
-
);
|
|
1447
|
-
}
|
|
1448
|
-
return registered3;
|
|
1449
|
-
}
|
|
1450
|
-
var registered3;
|
|
1451
|
-
var init_agent_factory_registry = __esm({
|
|
1452
|
-
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
1453
|
-
}
|
|
1454
|
-
});
|
|
1455
|
-
|
|
1456
1683
|
// src/internal/runtime/lifecycle/run-to-completion.ts
|
|
1457
1684
|
var run_to_completion_exports = {};
|
|
1458
1685
|
__export(run_to_completion_exports, {
|
|
@@ -1617,14 +1844,14 @@ async function forkAgentImpl(parent, options, deps) {
|
|
|
1617
1844
|
return {
|
|
1618
1845
|
result: result.result,
|
|
1619
1846
|
toolCalls: [],
|
|
1620
|
-
usage:
|
|
1847
|
+
usage: extractUsage2(result)
|
|
1621
1848
|
};
|
|
1622
1849
|
});
|
|
1623
1850
|
} finally {
|
|
1624
1851
|
await fork.dispose();
|
|
1625
1852
|
}
|
|
1626
1853
|
}
|
|
1627
|
-
function
|
|
1854
|
+
function extractUsage2(result) {
|
|
1628
1855
|
if (typeof result !== "object" || result === null) {
|
|
1629
1856
|
return { inputTokens: 0, outputTokens: 0 };
|
|
1630
1857
|
}
|
|
@@ -2058,323 +2285,117 @@ async function runWorkAndFinalize(taskId, aborter, work) {
|
|
|
2058
2285
|
void checkCancelRequestedAt(taskId, aborter);
|
|
2059
2286
|
emitToSubscribers(taskId, {
|
|
2060
2287
|
type: "progress",
|
|
2061
|
-
taskId,
|
|
2062
|
-
at: Date.now(),
|
|
2063
|
-
payload
|
|
2064
|
-
});
|
|
2065
|
-
}
|
|
2066
|
-
};
|
|
2067
|
-
try {
|
|
2068
|
-
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2069
|
-
if (aborter.signal.aborted) {
|
|
2070
|
-
const cancelledAt = Date.now();
|
|
2071
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2072
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2073
|
-
return;
|
|
2074
|
-
}
|
|
2075
|
-
const finishedAt = Date.now();
|
|
2076
|
-
await transition(taskId, "finished", { finishedAt, result });
|
|
2077
|
-
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2078
|
-
} catch (err) {
|
|
2079
|
-
if (aborter.signal.aborted) {
|
|
2080
|
-
const cancelledAt = Date.now();
|
|
2081
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2082
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2083
|
-
return;
|
|
2084
|
-
}
|
|
2085
|
-
const erroredAt = Date.now();
|
|
2086
|
-
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2087
|
-
await transition(taskId, "error", { erroredAt, error });
|
|
2088
|
-
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2092
|
-
if (aborter.signal.aborted) return;
|
|
2093
|
-
try {
|
|
2094
|
-
const handle = await state.store.get(taskId);
|
|
2095
|
-
if (handle?.cancelRequested === true) {
|
|
2096
|
-
aborter.abort("cancelRequested");
|
|
2097
|
-
}
|
|
2098
|
-
} catch {
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
async function acquireSlot() {
|
|
2102
|
-
if (reentryAls.getStore() === true) {
|
|
2103
|
-
return () => {
|
|
2104
|
-
};
|
|
2105
|
-
}
|
|
2106
|
-
return state.semaphore.acquire();
|
|
2107
|
-
}
|
|
2108
|
-
async function submit(internal) {
|
|
2109
|
-
state.firstSubmitSeen = true;
|
|
2110
|
-
startEvictTimerIfNeeded();
|
|
2111
|
-
const resolvedId = resolveIdInternal(internal);
|
|
2112
|
-
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2113
|
-
const existing = await state.store.get(resolvedId);
|
|
2114
|
-
if (existing !== void 0) {
|
|
2115
|
-
submitSpan.end();
|
|
2116
|
-
return existing;
|
|
2117
|
-
}
|
|
2118
|
-
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2119
|
-
submitSpan.end();
|
|
2120
|
-
if (internal.signal?.aborted === true) {
|
|
2121
|
-
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2122
|
-
}
|
|
2123
|
-
const aborter = new AbortController();
|
|
2124
|
-
state.aborters.set(resolvedId, aborter);
|
|
2125
|
-
if (internal.signal !== void 0) {
|
|
2126
|
-
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2127
|
-
once: true
|
|
2128
|
-
});
|
|
2129
|
-
}
|
|
2130
|
-
const release = await acquireSlot();
|
|
2131
|
-
void (async () => {
|
|
2132
|
-
try {
|
|
2133
|
-
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2134
|
-
if (aborter.signal.aborted) {
|
|
2135
|
-
const cancelledAt = Date.now();
|
|
2136
|
-
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2137
|
-
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2138
|
-
return;
|
|
2139
|
-
}
|
|
2140
|
-
const startedAt = Date.now();
|
|
2141
|
-
await transition(resolvedId, "running", { startedAt });
|
|
2142
|
-
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2143
|
-
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2144
|
-
} finally {
|
|
2145
|
-
release();
|
|
2146
|
-
state.aborters.delete(resolvedId);
|
|
2147
|
-
}
|
|
2148
|
-
})();
|
|
2149
|
-
return queuedHandle;
|
|
2150
|
-
}
|
|
2151
|
-
async function get(id) {
|
|
2152
|
-
if (!isValidTaskId(id, true)) return void 0;
|
|
2153
|
-
return state.store.get(id);
|
|
2154
|
-
}
|
|
2155
|
-
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2156
|
-
var init_registry = __esm({
|
|
2157
|
-
"src/internal/task/registry.ts"() {
|
|
2158
|
-
init_errors();
|
|
2159
|
-
init_task();
|
|
2160
|
-
init_async_semaphore();
|
|
2161
|
-
init_ring_buffer();
|
|
2162
|
-
init_store();
|
|
2163
|
-
init_subscribe();
|
|
2164
|
-
init_telemetry();
|
|
2165
|
-
DEFAULT_CONCURRENCY = 8;
|
|
2166
|
-
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2167
|
-
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2168
|
-
RING_CAP = 64;
|
|
2169
|
-
reentryAls = new async_hooks.AsyncLocalStorage();
|
|
2170
|
-
state = buildState({});
|
|
2171
|
-
}
|
|
2172
|
-
});
|
|
2173
|
-
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
2174
|
-
return zod.toJSONSchema(schema, options);
|
|
2175
|
-
}
|
|
2176
|
-
var init_to_json_schema = __esm({
|
|
2177
|
-
"src/internal/zod/to-json-schema.ts"() {
|
|
2178
|
-
}
|
|
2179
|
-
});
|
|
2180
|
-
function requireZod() {
|
|
2181
|
-
if (cachedZ !== void 0) return cachedZ;
|
|
2182
|
-
const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cron.cjs', document.baseURI).href)));
|
|
2183
|
-
let mod;
|
|
2184
|
-
try {
|
|
2185
|
-
mod = r("zod");
|
|
2186
|
-
} catch (cause) {
|
|
2187
|
-
throw new ConfigurationError(
|
|
2188
|
-
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
2189
|
-
{ code: "zod_not_installed", cause }
|
|
2190
|
-
);
|
|
2191
|
-
}
|
|
2192
|
-
cachedZ = mod.z ?? mod;
|
|
2193
|
-
return cachedZ;
|
|
2194
|
-
}
|
|
2195
|
-
function makeOutputTool(jsonSchema, onCapture) {
|
|
2196
|
-
return {
|
|
2197
|
-
name: "output",
|
|
2198
|
-
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
2199
|
-
inputSchema: jsonSchema,
|
|
2200
|
-
handler: (input) => {
|
|
2201
|
-
const out = onCapture(input);
|
|
2202
|
-
if (typeof out === "string") return out;
|
|
2203
|
-
if (out instanceof Promise) return out;
|
|
2204
|
-
return "";
|
|
2205
|
-
}
|
|
2206
|
-
};
|
|
2207
|
-
}
|
|
2208
|
-
function buildTransientAgentOptions(params) {
|
|
2209
|
-
return {
|
|
2210
|
-
model: params.model,
|
|
2211
|
-
local: params.local,
|
|
2212
|
-
tools: [params.outputTool],
|
|
2213
|
-
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
2214
|
-
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
2215
|
-
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
2216
|
-
};
|
|
2217
|
-
}
|
|
2218
|
-
function extractUsage2(result) {
|
|
2219
|
-
const u = result.usage;
|
|
2220
|
-
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
2221
|
-
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
2222
|
-
}
|
|
2223
|
-
function buildToolPrompt(prompt) {
|
|
2224
|
-
return `${prompt}
|
|
2225
|
-
|
|
2226
|
-
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
2227
|
-
}
|
|
2228
|
-
function setupStructuredOutput(schema, maxRetries) {
|
|
2229
|
-
const z6 = requireZod();
|
|
2230
|
-
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
2231
|
-
return {
|
|
2232
|
-
z: z6,
|
|
2233
|
-
jsonSchema,
|
|
2234
|
-
maxRetries: maxRetries ?? 1,
|
|
2235
|
-
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
2236
|
-
};
|
|
2237
|
-
}
|
|
2238
|
-
async function disposeAndDeleteTransient(agent, deletor) {
|
|
2239
|
-
await agent.dispose();
|
|
2240
|
-
try {
|
|
2241
|
-
await deletor(agent.agentId);
|
|
2242
|
-
} catch {
|
|
2243
|
-
}
|
|
2244
|
-
}
|
|
2245
|
-
var cachedZ;
|
|
2246
|
-
var init_structured_output_helpers = __esm({
|
|
2247
|
-
"src/internal/structured-output-helpers.ts"() {
|
|
2248
|
-
init_errors();
|
|
2249
|
-
init_to_json_schema();
|
|
2250
|
-
}
|
|
2251
|
-
});
|
|
2252
|
-
|
|
2253
|
-
// src/generate-object.ts
|
|
2254
|
-
var generate_object_exports = {};
|
|
2255
|
-
__export(generate_object_exports, {
|
|
2256
|
-
GenerateObjectError: () => GenerateObjectError,
|
|
2257
|
-
generateObjectImpl: () => generateObjectImpl
|
|
2258
|
-
});
|
|
2259
|
-
function salvagePartial(schema, raw) {
|
|
2260
|
-
if (typeof raw !== "object" || raw === null) return raw;
|
|
2261
|
-
const shape = schema.shape;
|
|
2262
|
-
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
2263
|
-
const rawObj = raw;
|
|
2264
|
-
const out = {};
|
|
2265
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
2266
|
-
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
2267
|
-
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
2268
|
-
if (parsed.success) out[key] = parsed.data;
|
|
2269
|
-
}
|
|
2270
|
-
return out;
|
|
2271
|
-
}
|
|
2272
|
-
async function generateObjectImpl(options, deps) {
|
|
2273
|
-
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
2274
|
-
options.schema,
|
|
2275
|
-
options.maxRetries
|
|
2276
|
-
);
|
|
2277
|
-
let capturedRaw;
|
|
2278
|
-
let lastUsage = initialUsage;
|
|
2279
|
-
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
2280
|
-
class CaptureSentinel extends Error {
|
|
2281
|
-
constructor(captured) {
|
|
2282
|
-
super("generate-object-capture");
|
|
2283
|
-
this.captured = captured;
|
|
2284
|
-
}
|
|
2285
|
-
captured;
|
|
2286
|
-
[sentinel] = true;
|
|
2287
|
-
}
|
|
2288
|
-
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
2289
|
-
if (capturedRaw === void 0) {
|
|
2290
|
-
capturedRaw = input;
|
|
2291
|
-
}
|
|
2292
|
-
throw new CaptureSentinel(input);
|
|
2293
|
-
});
|
|
2294
|
-
const agentOptions = buildTransientAgentOptions({
|
|
2295
|
-
model: options.model,
|
|
2296
|
-
local: options.local,
|
|
2297
|
-
outputTool,
|
|
2298
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2299
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2300
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2301
|
-
});
|
|
2302
|
-
const agent = await deps.create(agentOptions);
|
|
2288
|
+
taskId,
|
|
2289
|
+
at: Date.now(),
|
|
2290
|
+
payload
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
};
|
|
2303
2294
|
try {
|
|
2304
|
-
const
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
lastUsage = extractUsage2(result);
|
|
2311
|
-
if (capturedRaw === void 0) {
|
|
2312
|
-
if (result.status === "error" && result.error !== void 0) {
|
|
2313
|
-
throw new GenerateObjectError(
|
|
2314
|
-
"no_tool_call",
|
|
2315
|
-
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
2316
|
-
result.error
|
|
2317
|
-
);
|
|
2318
|
-
}
|
|
2319
|
-
if (attempt === maxRetries) {
|
|
2320
|
-
throw new GenerateObjectError(
|
|
2321
|
-
"no_tool_call",
|
|
2322
|
-
"The model returned text instead of calling the `output` tool."
|
|
2323
|
-
);
|
|
2324
|
-
}
|
|
2325
|
-
continue;
|
|
2326
|
-
}
|
|
2327
|
-
const parsed = options.schema.safeParse(capturedRaw);
|
|
2328
|
-
if (parsed.success) {
|
|
2329
|
-
return {
|
|
2330
|
-
object: parsed.data,
|
|
2331
|
-
raw: capturedRaw,
|
|
2332
|
-
usage: lastUsage,
|
|
2333
|
-
finishReason: "tool_use"
|
|
2334
|
-
};
|
|
2335
|
-
}
|
|
2336
|
-
lastParseError = parsed.error;
|
|
2295
|
+
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2296
|
+
if (aborter.signal.aborted) {
|
|
2297
|
+
const cancelledAt = Date.now();
|
|
2298
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2299
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2300
|
+
return;
|
|
2337
2301
|
}
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
};
|
|
2302
|
+
const finishedAt = Date.now();
|
|
2303
|
+
await transition(taskId, "finished", { finishedAt, result });
|
|
2304
|
+
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2305
|
+
} catch (err) {
|
|
2306
|
+
if (aborter.signal.aborted) {
|
|
2307
|
+
const cancelledAt = Date.now();
|
|
2308
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2309
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2310
|
+
return;
|
|
2345
2311
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2312
|
+
const erroredAt = Date.now();
|
|
2313
|
+
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2314
|
+
await transition(taskId, "error", { erroredAt, error });
|
|
2315
|
+
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2319
|
+
if (aborter.signal.aborted) return;
|
|
2320
|
+
try {
|
|
2321
|
+
const handle = await state.store.get(taskId);
|
|
2322
|
+
if (handle?.cancelRequested === true) {
|
|
2323
|
+
aborter.abort("cancelRequested");
|
|
2353
2324
|
}
|
|
2354
|
-
|
|
2355
|
-
"parse_failed",
|
|
2356
|
-
"Schema parse failed after all retries.",
|
|
2357
|
-
lastParseError
|
|
2358
|
-
);
|
|
2359
|
-
} finally {
|
|
2360
|
-
await disposeAndDeleteTransient(agent, deps.delete);
|
|
2325
|
+
} catch {
|
|
2361
2326
|
}
|
|
2362
2327
|
}
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
init_structured_output_helpers();
|
|
2367
|
-
GenerateObjectError = class extends Error {
|
|
2368
|
-
name = "GenerateObjectError";
|
|
2369
|
-
code;
|
|
2370
|
-
cause;
|
|
2371
|
-
constructor(code, message, cause) {
|
|
2372
|
-
super(message);
|
|
2373
|
-
this.code = code;
|
|
2374
|
-
if (cause !== void 0) this.cause = cause;
|
|
2375
|
-
}
|
|
2328
|
+
async function acquireSlot() {
|
|
2329
|
+
if (reentryAls.getStore() === true) {
|
|
2330
|
+
return () => {
|
|
2376
2331
|
};
|
|
2377
2332
|
}
|
|
2333
|
+
return state.semaphore.acquire();
|
|
2334
|
+
}
|
|
2335
|
+
async function submit(internal) {
|
|
2336
|
+
state.firstSubmitSeen = true;
|
|
2337
|
+
startEvictTimerIfNeeded();
|
|
2338
|
+
const resolvedId = resolveIdInternal(internal);
|
|
2339
|
+
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2340
|
+
const existing = await state.store.get(resolvedId);
|
|
2341
|
+
if (existing !== void 0) {
|
|
2342
|
+
submitSpan.end();
|
|
2343
|
+
return existing;
|
|
2344
|
+
}
|
|
2345
|
+
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2346
|
+
submitSpan.end();
|
|
2347
|
+
if (internal.signal?.aborted === true) {
|
|
2348
|
+
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2349
|
+
}
|
|
2350
|
+
const aborter = new AbortController();
|
|
2351
|
+
state.aborters.set(resolvedId, aborter);
|
|
2352
|
+
if (internal.signal !== void 0) {
|
|
2353
|
+
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2354
|
+
once: true
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2357
|
+
const release = await acquireSlot();
|
|
2358
|
+
void (async () => {
|
|
2359
|
+
try {
|
|
2360
|
+
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2361
|
+
if (aborter.signal.aborted) {
|
|
2362
|
+
const cancelledAt = Date.now();
|
|
2363
|
+
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2364
|
+
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
const startedAt = Date.now();
|
|
2368
|
+
await transition(resolvedId, "running", { startedAt });
|
|
2369
|
+
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2370
|
+
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2371
|
+
} finally {
|
|
2372
|
+
release();
|
|
2373
|
+
state.aborters.delete(resolvedId);
|
|
2374
|
+
}
|
|
2375
|
+
})();
|
|
2376
|
+
return queuedHandle;
|
|
2377
|
+
}
|
|
2378
|
+
async function get(id) {
|
|
2379
|
+
if (!isValidTaskId(id, true)) return void 0;
|
|
2380
|
+
return state.store.get(id);
|
|
2381
|
+
}
|
|
2382
|
+
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2383
|
+
var init_registry = __esm({
|
|
2384
|
+
"src/internal/task/registry.ts"() {
|
|
2385
|
+
init_errors();
|
|
2386
|
+
init_task();
|
|
2387
|
+
init_async_semaphore();
|
|
2388
|
+
init_ring_buffer();
|
|
2389
|
+
init_store();
|
|
2390
|
+
init_subscribe();
|
|
2391
|
+
init_telemetry();
|
|
2392
|
+
DEFAULT_CONCURRENCY = 8;
|
|
2393
|
+
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2394
|
+
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2395
|
+
RING_CAP = 64;
|
|
2396
|
+
reentryAls = new async_hooks.AsyncLocalStorage();
|
|
2397
|
+
state = buildState({});
|
|
2398
|
+
}
|
|
2378
2399
|
});
|
|
2379
2400
|
|
|
2380
2401
|
// src/stream-object.ts
|
|
@@ -2431,7 +2452,7 @@ async function* streamObjectImpl(options, deps) {
|
|
|
2431
2452
|
}
|
|
2432
2453
|
}
|
|
2433
2454
|
const result = await run.wait();
|
|
2434
|
-
lastUsage =
|
|
2455
|
+
lastUsage = extractUsage(result);
|
|
2435
2456
|
if (capturedRaw === void 0) {
|
|
2436
2457
|
if (result.status === "error" && result.error !== void 0) {
|
|
2437
2458
|
throw new StreamObjectError(
|
|
@@ -2777,6 +2798,7 @@ var AgentBuilder = class {
|
|
|
2777
2798
|
constructor(deps) {
|
|
2778
2799
|
this.deps = deps;
|
|
2779
2800
|
}
|
|
2801
|
+
/** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
|
|
2780
2802
|
model(m) {
|
|
2781
2803
|
this.opts.model = m;
|
|
2782
2804
|
return this;
|
|
@@ -3130,6 +3152,69 @@ function isLocalAgentId(id) {
|
|
|
3130
3152
|
return id.startsWith(PREFIX.localAgent);
|
|
3131
3153
|
}
|
|
3132
3154
|
|
|
3155
|
+
// src/internal/runtime/config/default-model.ts
|
|
3156
|
+
var DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
|
|
3157
|
+
|
|
3158
|
+
// src/agent-generate.ts
|
|
3159
|
+
async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
|
|
3160
|
+
const { output, maxRetries, errorStrategy, ...sendOptions } = options;
|
|
3161
|
+
const run = await agent.send(input, sendOptions);
|
|
3162
|
+
const result = await run.wait();
|
|
3163
|
+
const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
|
|
3164
|
+
const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
|
|
3165
|
+
const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
|
|
3166
|
+
const facade = getAgentFacade2();
|
|
3167
|
+
const structured = await generateObjectImpl2(
|
|
3168
|
+
{
|
|
3169
|
+
prompt: answer,
|
|
3170
|
+
schema: output,
|
|
3171
|
+
// `agentModel` arrives already normalized (`this.model` passed through
|
|
3172
|
+
// `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
|
|
3173
|
+
// `string | ModelSelection` field only ever receives a `ModelSelection` here.
|
|
3174
|
+
model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
|
|
3175
|
+
// `local` is required to keep the transient structuring agent local-only;
|
|
3176
|
+
// default to the process cwd when the agent had no explicit local config.
|
|
3177
|
+
local: agentLocal ?? { cwd: process.cwd() },
|
|
3178
|
+
...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
|
|
3179
|
+
...maxRetries !== void 0 ? { maxRetries } : {},
|
|
3180
|
+
...errorStrategy !== void 0 ? { errorStrategy } : {}
|
|
3181
|
+
},
|
|
3182
|
+
{
|
|
3183
|
+
create: (opts) => facade.create(opts),
|
|
3184
|
+
delete: (agentId) => facade.delete(agentId)
|
|
3185
|
+
}
|
|
3186
|
+
);
|
|
3187
|
+
return {
|
|
3188
|
+
object: structured.object,
|
|
3189
|
+
result,
|
|
3190
|
+
raw: structured.raw,
|
|
3191
|
+
usage: structured.usage
|
|
3192
|
+
};
|
|
3193
|
+
}
|
|
3194
|
+
function structurableAnswerOrThrow(result, GenerateObjectError2) {
|
|
3195
|
+
if (result.status === "error") {
|
|
3196
|
+
throw new GenerateObjectError2(
|
|
3197
|
+
"no_tool_call",
|
|
3198
|
+
`Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
|
|
3199
|
+
result.error
|
|
3200
|
+
);
|
|
3201
|
+
}
|
|
3202
|
+
if (result.status === "cancelled") {
|
|
3203
|
+
throw new GenerateObjectError2(
|
|
3204
|
+
"no_tool_call",
|
|
3205
|
+
"Agent run was cancelled before an answer could be structured."
|
|
3206
|
+
);
|
|
3207
|
+
}
|
|
3208
|
+
const answer = result.result;
|
|
3209
|
+
if (answer === void 0 || answer.length === 0) {
|
|
3210
|
+
throw new GenerateObjectError2(
|
|
3211
|
+
"no_tool_call",
|
|
3212
|
+
"The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
|
|
3213
|
+
);
|
|
3214
|
+
}
|
|
3215
|
+
return answer;
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3133
3218
|
// src/internal/runtime/cloud/cloud-agent.ts
|
|
3134
3219
|
init_errors();
|
|
3135
3220
|
init_cwd_mutex();
|
|
@@ -3280,8 +3365,19 @@ function safeFilenameForId(id, options) {
|
|
|
3280
3365
|
return `h-${crypto.createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
|
|
3281
3366
|
}
|
|
3282
3367
|
|
|
3283
|
-
// src/internal/runtime/
|
|
3284
|
-
|
|
3368
|
+
// src/internal/runtime/model-selection.ts
|
|
3369
|
+
init_errors();
|
|
3370
|
+
function normalizeModel(m) {
|
|
3371
|
+
if (m === void 0 || typeof m !== "string") return m;
|
|
3372
|
+
const id = m.trim();
|
|
3373
|
+
if (id.length === 0) {
|
|
3374
|
+
throw new ConfigurationError(
|
|
3375
|
+
'model must be a non-empty "provider/model" id string or a ModelSelection object',
|
|
3376
|
+
{ code: "invalid_model_selection" }
|
|
3377
|
+
);
|
|
3378
|
+
}
|
|
3379
|
+
return { id };
|
|
3380
|
+
}
|
|
3285
3381
|
|
|
3286
3382
|
// src/internal/runtime/registry/agent-registry-store.ts
|
|
3287
3383
|
init_cwd_mutex();
|
|
@@ -3358,7 +3454,10 @@ var REGISTRY_RELATIVE_PATH = path.join(".theokit", "agents", "registry.json");
|
|
|
3358
3454
|
function stripSecretsFromOptions(options) {
|
|
3359
3455
|
return assignDefined({
|
|
3360
3456
|
name: options.name,
|
|
3361
|
-
model:
|
|
3457
|
+
model: (() => {
|
|
3458
|
+
const m = normalizeModel(options.model);
|
|
3459
|
+
return m !== void 0 ? { id: m.id } : void 0;
|
|
3460
|
+
})(),
|
|
3362
3461
|
systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
|
|
3363
3462
|
local: serializeLocal(options.local),
|
|
3364
3463
|
cloud: serializeCloud(options.cloud),
|
|
@@ -3643,7 +3742,8 @@ function serializeCloudAgentConfig(options) {
|
|
|
3643
3742
|
cloud: serializeCloud2(options.cloud)
|
|
3644
3743
|
};
|
|
3645
3744
|
if (typeof options.agentId === "string") payload.agentId = options.agentId;
|
|
3646
|
-
|
|
3745
|
+
const cfgModel = normalizeModel(options.model);
|
|
3746
|
+
if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
|
|
3647
3747
|
if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
|
|
3648
3748
|
const skills = serializeSkills(options.skills);
|
|
3649
3749
|
if (skills !== void 0) payload.skills = skills;
|
|
@@ -4539,6 +4639,7 @@ function applyScriptMetrics(base, script) {
|
|
|
4539
4639
|
if (script.cost !== void 0) base.cost = script.cost;
|
|
4540
4640
|
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
4541
4641
|
if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
|
|
4642
|
+
if (script.origin !== void 0) base.origin = script.origin;
|
|
4542
4643
|
}
|
|
4543
4644
|
|
|
4544
4645
|
// src/internal/runtime/cloud/cloud-run.ts
|
|
@@ -4894,7 +4995,7 @@ var CloudAgent = class {
|
|
|
4894
4995
|
disposed = false;
|
|
4895
4996
|
constructor(options, providedAgentId) {
|
|
4896
4997
|
this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
|
|
4897
|
-
this.model = options.model;
|
|
4998
|
+
this.model = normalizeModel(options.model);
|
|
4898
4999
|
this.options = options;
|
|
4899
5000
|
this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
|
|
4900
5001
|
const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
|
|
@@ -4924,6 +5025,17 @@ var CloudAgent = class {
|
|
|
4924
5025
|
const apiKey = resolveApiKey(this.options.apiKey);
|
|
4925
5026
|
return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
|
|
4926
5027
|
}
|
|
5028
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
5029
|
+
generate(message, options) {
|
|
5030
|
+
return agentGenerate(
|
|
5031
|
+
this,
|
|
5032
|
+
this.model,
|
|
5033
|
+
this.options.apiKey,
|
|
5034
|
+
this.options.local,
|
|
5035
|
+
message,
|
|
5036
|
+
options
|
|
5037
|
+
);
|
|
5038
|
+
}
|
|
4927
5039
|
async send(message, options = {}) {
|
|
4928
5040
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
4929
5041
|
throw new ConfigurationError(
|
|
@@ -4954,7 +5066,7 @@ var CloudAgent = class {
|
|
|
4954
5066
|
});
|
|
4955
5067
|
}
|
|
4956
5068
|
async sendLocked(message, options) {
|
|
4957
|
-
const overrideModel = options.model;
|
|
5069
|
+
const overrideModel = normalizeModel(options.model);
|
|
4958
5070
|
if (overrideModel !== void 0) {
|
|
4959
5071
|
this.model = overrideModel;
|
|
4960
5072
|
updateRegisteredAgent(this.agentId, { model: overrideModel });
|
|
@@ -5868,18 +5980,18 @@ var ALL_ADAPTERS = [
|
|
|
5868
5980
|
arizeAdapter,
|
|
5869
5981
|
braintrustAdapter
|
|
5870
5982
|
];
|
|
5871
|
-
var
|
|
5983
|
+
var registered2 = /* @__PURE__ */ new Set();
|
|
5872
5984
|
function tryAutoRegisterAdapters(settings) {
|
|
5873
5985
|
if (settings?.enabled !== true) return;
|
|
5874
5986
|
if (settings.autoDetect === false) return;
|
|
5875
5987
|
const disabled = new Set(settings.disable ?? []);
|
|
5876
5988
|
for (const adapter of ALL_ADAPTERS) {
|
|
5877
|
-
if (
|
|
5989
|
+
if (registered2.has(adapter.moduleName)) continue;
|
|
5878
5990
|
if (disabled.has(adapter.displayName.toLowerCase())) continue;
|
|
5879
5991
|
if (!adapter.detect()) continue;
|
|
5880
5992
|
try {
|
|
5881
5993
|
adapter.register();
|
|
5882
|
-
|
|
5994
|
+
registered2.add(adapter.moduleName);
|
|
5883
5995
|
process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
|
|
5884
5996
|
`);
|
|
5885
5997
|
} catch (cause) {
|
|
@@ -6442,6 +6554,26 @@ function paginate(items, opts) {
|
|
|
6442
6554
|
return items.slice(start, end);
|
|
6443
6555
|
}
|
|
6444
6556
|
|
|
6557
|
+
// src/internal/persistence/session-meta.ts
|
|
6558
|
+
function applyMetaPatch(current, patch) {
|
|
6559
|
+
const next = {};
|
|
6560
|
+
if (current.title !== void 0) next.title = current.title;
|
|
6561
|
+
if (current.tag !== void 0) next.tag = current.tag;
|
|
6562
|
+
if (patch.title === null) delete next.title;
|
|
6563
|
+
else if (patch.title !== void 0) next.title = patch.title;
|
|
6564
|
+
if (patch.tag === null) delete next.tag;
|
|
6565
|
+
else if (patch.tag !== void 0) next.tag = patch.tag;
|
|
6566
|
+
return next;
|
|
6567
|
+
}
|
|
6568
|
+
function coerceSessionMeta(raw) {
|
|
6569
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
6570
|
+
const obj = raw;
|
|
6571
|
+
const meta = {};
|
|
6572
|
+
if (typeof obj.title === "string") meta.title = obj.title;
|
|
6573
|
+
if (typeof obj.tag === "string") meta.tag = obj.tag;
|
|
6574
|
+
return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
|
|
6575
|
+
}
|
|
6576
|
+
|
|
6445
6577
|
// src/internal/persistence/conversation-storage-fs.ts
|
|
6446
6578
|
var FileSystemConversationStorage = class {
|
|
6447
6579
|
#root;
|
|
@@ -6492,6 +6624,37 @@ var FileSystemConversationStorage = class {
|
|
|
6492
6624
|
async compact(conversationId, maxTurns) {
|
|
6493
6625
|
await compactSessionFile(this.#root, conversationId, maxTurns);
|
|
6494
6626
|
}
|
|
6627
|
+
// SE4 — session metadata persisted as a per-conversation sidecar
|
|
6628
|
+
// `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
|
|
6629
|
+
// the transcript). Kept separate from messages.jsonl so a title/tag write does
|
|
6630
|
+
// not rewrite the append-only log.
|
|
6631
|
+
#metaPath(conversationId) {
|
|
6632
|
+
const safe2 = sanitizeIdentifier(conversationId, { maxLen: 128 });
|
|
6633
|
+
return safePathJoin(this.#root, ".theokit", "agents", safe2, "session.json");
|
|
6634
|
+
}
|
|
6635
|
+
async getSessionMeta(conversationId) {
|
|
6636
|
+
try {
|
|
6637
|
+
const raw = await promises.readFile(this.#metaPath(conversationId), "utf8");
|
|
6638
|
+
return coerceSessionMeta(JSON.parse(raw));
|
|
6639
|
+
} catch (cause) {
|
|
6640
|
+
if (cause.code === "ENOENT") return void 0;
|
|
6641
|
+
throw cause;
|
|
6642
|
+
}
|
|
6643
|
+
}
|
|
6644
|
+
async setSessionMeta(conversationId, patch) {
|
|
6645
|
+
const metaPath = this.#metaPath(conversationId);
|
|
6646
|
+
await promises.mkdir(path.dirname(metaPath), { recursive: true });
|
|
6647
|
+
await withFileLock(metaPath, async () => {
|
|
6648
|
+
let current = {};
|
|
6649
|
+
try {
|
|
6650
|
+
current = coerceSessionMeta(JSON.parse(await promises.readFile(metaPath, "utf8"))) ?? {};
|
|
6651
|
+
} catch (cause) {
|
|
6652
|
+
if (cause.code !== "ENOENT") throw cause;
|
|
6653
|
+
}
|
|
6654
|
+
const next = applyMetaPatch(current, patch);
|
|
6655
|
+
await promises.writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
|
|
6656
|
+
});
|
|
6657
|
+
}
|
|
6495
6658
|
async dispose() {
|
|
6496
6659
|
}
|
|
6497
6660
|
};
|
|
@@ -8341,23 +8504,27 @@ function tryParseSkill(raw, fallbackName, source, options) {
|
|
|
8341
8504
|
|
|
8342
8505
|
// src/internal/runtime/skills/skills-manager.ts
|
|
8343
8506
|
var SkillsManager = class {
|
|
8344
|
-
constructor(cwd, _enabled, settingSourcesIncludeProject) {
|
|
8507
|
+
constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
|
|
8345
8508
|
this.cwd = cwd;
|
|
8346
8509
|
this.settingSourcesIncludeProject = settingSourcesIncludeProject;
|
|
8510
|
+
this.skillsDir = skillsDir;
|
|
8511
|
+
this.inline = inline;
|
|
8347
8512
|
}
|
|
8348
8513
|
cwd;
|
|
8349
8514
|
settingSourcesIncludeProject;
|
|
8515
|
+
skillsDir;
|
|
8516
|
+
inline;
|
|
8350
8517
|
skills = [];
|
|
8351
8518
|
async initialize() {
|
|
8352
8519
|
if (!this.settingSourcesIncludeProject) {
|
|
8353
|
-
this.skills = [];
|
|
8520
|
+
this.skills = this.mergeInline([]);
|
|
8354
8521
|
return;
|
|
8355
8522
|
}
|
|
8356
8523
|
await this.refresh();
|
|
8357
8524
|
}
|
|
8358
8525
|
async refresh() {
|
|
8359
|
-
const skillsRoot = path.join(this.cwd, ".theokit", "skills");
|
|
8360
|
-
|
|
8526
|
+
const skillsRoot = this.skillsDir ?? path.join(this.cwd, ".theokit", "skills");
|
|
8527
|
+
const discovered = await discoverSkills(skillsRoot, {
|
|
8361
8528
|
onInvalidSkill: (info) => {
|
|
8362
8529
|
process.stderr.write(
|
|
8363
8530
|
`[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
|
|
@@ -8365,6 +8532,13 @@ var SkillsManager = class {
|
|
|
8365
8532
|
);
|
|
8366
8533
|
}
|
|
8367
8534
|
});
|
|
8535
|
+
this.skills = this.mergeInline(discovered);
|
|
8536
|
+
}
|
|
8537
|
+
/** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
|
|
8538
|
+
mergeInline(discovered) {
|
|
8539
|
+
if (this.inline === void 0 || this.inline.length === 0) return discovered;
|
|
8540
|
+
const inlineNames = new Set(this.inline.map((s) => s.name));
|
|
8541
|
+
return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
|
|
8368
8542
|
}
|
|
8369
8543
|
list() {
|
|
8370
8544
|
return Promise.resolve(this.skills);
|
|
@@ -8400,7 +8574,7 @@ function bootstrapSubmanagers(args) {
|
|
|
8400
8574
|
const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
|
|
8401
8575
|
if (providerCount > 0 || args.options.providers !== void 0) {
|
|
8402
8576
|
out.providers = new ProvidersManagerImpl(
|
|
8403
|
-
args.options.model,
|
|
8577
|
+
normalizeModel(args.options.model),
|
|
8404
8578
|
args.options.providers,
|
|
8405
8579
|
args.options.plugins
|
|
8406
8580
|
);
|
|
@@ -8409,7 +8583,10 @@ function bootstrapSubmanagers(args) {
|
|
|
8409
8583
|
out.skillsManager = new SkillsManager(
|
|
8410
8584
|
args.workspaceCwd,
|
|
8411
8585
|
args.options.skills?.enabled,
|
|
8412
|
-
args.settingSourcesIncludeProject
|
|
8586
|
+
args.settingSourcesIncludeProject,
|
|
8587
|
+
// M22 — custom skills directory + inline (code-defined) skills.
|
|
8588
|
+
args.options.skills?.skillsDir,
|
|
8589
|
+
args.options.skills?.inline
|
|
8413
8590
|
);
|
|
8414
8591
|
const localSkills = out.skillsManager;
|
|
8415
8592
|
out.skills = { list: () => localSkills.list() };
|
|
@@ -8467,6 +8644,7 @@ function createLocalRun(options) {
|
|
|
8467
8644
|
projectMcpServers: options.projectMcpServers,
|
|
8468
8645
|
...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
|
|
8469
8646
|
});
|
|
8647
|
+
if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
|
|
8470
8648
|
const handle = new LocalRun({
|
|
8471
8649
|
id,
|
|
8472
8650
|
agentId: options.agentId,
|
|
@@ -9115,6 +9293,15 @@ async function emitReasoningDeltaCallback(inputs, text) {
|
|
|
9115
9293
|
);
|
|
9116
9294
|
}
|
|
9117
9295
|
|
|
9296
|
+
// src/types/run-events.ts
|
|
9297
|
+
function emitRunEvent(sink, event) {
|
|
9298
|
+
if (sink === void 0) return;
|
|
9299
|
+
try {
|
|
9300
|
+
sink(event);
|
|
9301
|
+
} catch {
|
|
9302
|
+
}
|
|
9303
|
+
}
|
|
9304
|
+
|
|
9118
9305
|
// src/internal/agent-loop/tool-dispatch.ts
|
|
9119
9306
|
init_async_local_storage();
|
|
9120
9307
|
|
|
@@ -9212,6 +9399,22 @@ function coerceArgsToSchema(args, schema) {
|
|
|
9212
9399
|
return { value: out, changed };
|
|
9213
9400
|
}
|
|
9214
9401
|
|
|
9402
|
+
// src/tool-error.ts
|
|
9403
|
+
init_errors();
|
|
9404
|
+
var ToolError = class extends TheokitAgentError {
|
|
9405
|
+
name = "ToolError";
|
|
9406
|
+
/** The error content surfaced to the model: a string, or text/image blocks. */
|
|
9407
|
+
content;
|
|
9408
|
+
constructor(content, options = {}) {
|
|
9409
|
+
super(renderToolErrorMessage(content), { ...options, isRetryable: false });
|
|
9410
|
+
this.content = content;
|
|
9411
|
+
}
|
|
9412
|
+
};
|
|
9413
|
+
function renderToolErrorMessage(content) {
|
|
9414
|
+
if (typeof content === "string") return content;
|
|
9415
|
+
return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
|
|
9416
|
+
}
|
|
9417
|
+
|
|
9215
9418
|
// src/internal/runtime/tools/shell-tool.ts
|
|
9216
9419
|
async function runShell(options) {
|
|
9217
9420
|
if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
|
|
@@ -9265,9 +9468,13 @@ async function runHandlerTool(kind, handler, call, signal, context) {
|
|
|
9265
9468
|
return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
|
|
9266
9469
|
}
|
|
9267
9470
|
try {
|
|
9268
|
-
const
|
|
9269
|
-
return { stdout, stderr: "", exitCode: 0 };
|
|
9471
|
+
const out = await handler(call.input, { signal, context });
|
|
9472
|
+
if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
|
|
9473
|
+
return { stdout: out, stderr: "", exitCode: 0 };
|
|
9270
9474
|
} catch (cause) {
|
|
9475
|
+
if (cause instanceof ToolError) {
|
|
9476
|
+
return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
|
|
9477
|
+
}
|
|
9271
9478
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
9272
9479
|
return { stdout: "", stderr: message, exitCode: 1 };
|
|
9273
9480
|
}
|
|
@@ -9386,6 +9593,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
|
|
|
9386
9593
|
toolSpan?.end();
|
|
9387
9594
|
return fileVeto;
|
|
9388
9595
|
}
|
|
9596
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9597
|
+
type: "tool_progress",
|
|
9598
|
+
toolName: workingCall.name,
|
|
9599
|
+
toolCallId: callId
|
|
9600
|
+
});
|
|
9389
9601
|
const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
|
|
9390
9602
|
await inputs.pluginManager?.runPostToolCallHooks({
|
|
9391
9603
|
name: workingCall.name,
|
|
@@ -9412,6 +9624,13 @@ function applyRepairAndExtractCall(tools, call) {
|
|
|
9412
9624
|
function vetoFromForkWhitelist(inputs, call, callId, events) {
|
|
9413
9625
|
const whitelistDecision = checkToolWhitelist(call.name);
|
|
9414
9626
|
if (whitelistDecision.allowed) return void 0;
|
|
9627
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9628
|
+
type: "permission_denied",
|
|
9629
|
+
toolName: call.name,
|
|
9630
|
+
toolCallId: callId,
|
|
9631
|
+
source: "fork_whitelist",
|
|
9632
|
+
message: whitelistDecision.reason ?? "tool not available in fork"
|
|
9633
|
+
});
|
|
9415
9634
|
events.push(buildToolUseRunning(inputs, callId, call));
|
|
9416
9635
|
events.push(
|
|
9417
9636
|
buildToolUseCompleted(inputs, callId, call, {
|
|
@@ -9448,6 +9667,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
|
|
|
9448
9667
|
runId: inputs.runId
|
|
9449
9668
|
});
|
|
9450
9669
|
if (pluginVeto === void 0) return void 0;
|
|
9670
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9671
|
+
type: "permission_denied",
|
|
9672
|
+
toolName: call.name,
|
|
9673
|
+
toolCallId: callId,
|
|
9674
|
+
source: "plugin",
|
|
9675
|
+
message: pluginVeto.message
|
|
9676
|
+
});
|
|
9451
9677
|
events.push(
|
|
9452
9678
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9453
9679
|
stdout: "",
|
|
@@ -9470,6 +9696,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
|
|
|
9470
9696
|
runId: inputs.runId
|
|
9471
9697
|
});
|
|
9472
9698
|
if (!preDecision.blocked) return void 0;
|
|
9699
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9700
|
+
type: "permission_denied",
|
|
9701
|
+
toolName: call.name,
|
|
9702
|
+
toolCallId: callId,
|
|
9703
|
+
source: "file_hook",
|
|
9704
|
+
message: preDecision.reason ?? "blocked by hook"
|
|
9705
|
+
});
|
|
9473
9706
|
events.push(
|
|
9474
9707
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9475
9708
|
stdout: "",
|
|
@@ -9513,7 +9746,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
|
|
|
9513
9746
|
await safeEmitToolHook(inputs.onToolEnd, {
|
|
9514
9747
|
toolName: call.name,
|
|
9515
9748
|
args: call.input,
|
|
9516
|
-
|
|
9749
|
+
// SE7 — a block-returning handler has empty `stdout`; surface its structured
|
|
9750
|
+
// content to the hook instead of an empty string.
|
|
9751
|
+
result: result.content !== void 0 ? result.content : result.stdout,
|
|
9517
9752
|
conversationId: inputs.agentId,
|
|
9518
9753
|
callId,
|
|
9519
9754
|
durationMs
|
|
@@ -9535,7 +9770,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9535
9770
|
output: {
|
|
9536
9771
|
stdout: result.stdout,
|
|
9537
9772
|
stderr: result.stderr,
|
|
9538
|
-
exitCode: result.exitCode ?? 0
|
|
9773
|
+
exitCode: result.exitCode ?? 0,
|
|
9774
|
+
// SE7 — structured content (text + image blocks) when the handler
|
|
9775
|
+
// returned/threw blocks; absent for the string path.
|
|
9776
|
+
...result.content !== void 0 ? { content: result.content } : {}
|
|
9539
9777
|
},
|
|
9540
9778
|
agentId: inputs.agentId,
|
|
9541
9779
|
runId: inputs.runId
|
|
@@ -9548,7 +9786,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9548
9786
|
return {
|
|
9549
9787
|
type: "tool_result",
|
|
9550
9788
|
toolUseId: call.id,
|
|
9551
|
-
content
|
|
9789
|
+
// SE7 — structured content blocks (handler-returned or ToolError-carried)
|
|
9790
|
+
// are authoritative; otherwise the legacy string rendering.
|
|
9791
|
+
content: result.content !== void 0 ? result.content : renderToolResult(result),
|
|
9552
9792
|
...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
|
|
9553
9793
|
};
|
|
9554
9794
|
}
|
|
@@ -9597,6 +9837,29 @@ function buildToolUseCompleted(inputs, callId, call, result) {
|
|
|
9597
9837
|
};
|
|
9598
9838
|
}
|
|
9599
9839
|
|
|
9840
|
+
// src/internal/llm/tool-result-content.ts
|
|
9841
|
+
init_errors();
|
|
9842
|
+
function toBlockToolResultContent(content) {
|
|
9843
|
+
return content;
|
|
9844
|
+
}
|
|
9845
|
+
function toStringToolResultContent(content, providerName) {
|
|
9846
|
+
if (typeof content === "string") return content;
|
|
9847
|
+
if (content.some((block) => block.type === "image")) {
|
|
9848
|
+
throw new ConfigurationError(
|
|
9849
|
+
`provider "${providerName}" does not support image content in tool results`
|
|
9850
|
+
);
|
|
9851
|
+
}
|
|
9852
|
+
return content.filter(
|
|
9853
|
+
(block) => block.type === "text"
|
|
9854
|
+
).map((block) => block.text).join("\n");
|
|
9855
|
+
}
|
|
9856
|
+
function renderToolResultContentText(content, fn) {
|
|
9857
|
+
if (typeof content === "string") return fn(content);
|
|
9858
|
+
return content.map(
|
|
9859
|
+
(block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
|
|
9860
|
+
);
|
|
9861
|
+
}
|
|
9862
|
+
|
|
9600
9863
|
// src/internal/agent-loop/tool-result-guard.ts
|
|
9601
9864
|
var OPEN = "<untrusted-tool-output>";
|
|
9602
9865
|
var CLOSE = "</untrusted-tool-output>";
|
|
@@ -9622,7 +9885,11 @@ ${CLOSE}`;
|
|
|
9622
9885
|
function applyToolResultGuard(parts, opts) {
|
|
9623
9886
|
if (opts.delimit !== true && opts.redactPii !== true) return parts;
|
|
9624
9887
|
return parts.map(
|
|
9625
|
-
(p) =>
|
|
9888
|
+
(p) => (
|
|
9889
|
+
// SE7 — guard the TEXT of a tool result (string or the text blocks of a
|
|
9890
|
+
// structured content); image blocks pass through untouched.
|
|
9891
|
+
p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
|
|
9892
|
+
)
|
|
9626
9893
|
);
|
|
9627
9894
|
}
|
|
9628
9895
|
|
|
@@ -10539,10 +10806,10 @@ function stripVertexPrefix(modelId) {
|
|
|
10539
10806
|
}
|
|
10540
10807
|
|
|
10541
10808
|
// src/internal/providers/builtin/index.ts
|
|
10542
|
-
var
|
|
10809
|
+
var registered3 = false;
|
|
10543
10810
|
function registerBuiltins() {
|
|
10544
|
-
if (
|
|
10545
|
-
|
|
10811
|
+
if (registered3) return;
|
|
10812
|
+
registered3 = true;
|
|
10546
10813
|
registerProvider(ANTHROPIC);
|
|
10547
10814
|
registerProvider(OPENAI);
|
|
10548
10815
|
registerProvider(OPENROUTER);
|
|
@@ -10770,7 +11037,9 @@ function toAnthropicWireMessage(message) {
|
|
|
10770
11037
|
return {
|
|
10771
11038
|
type: "tool_result",
|
|
10772
11039
|
tool_use_id: part.toolUseId,
|
|
10773
|
-
|
|
11040
|
+
// SE7 — this wire is block-capable: strings pass through, structured
|
|
11041
|
+
// text/image blocks are forwarded natively.
|
|
11042
|
+
content: toBlockToolResultContent(part.content),
|
|
10774
11043
|
...part.isError === true ? { is_error: true } : {}
|
|
10775
11044
|
};
|
|
10776
11045
|
});
|
|
@@ -11562,7 +11831,8 @@ function toOllamaMessages(message) {
|
|
|
11562
11831
|
if (part.type === "tool_result") {
|
|
11563
11832
|
out.push({
|
|
11564
11833
|
role: "tool",
|
|
11565
|
-
|
|
11834
|
+
// SE7 — string-only tool role: text blocks flatten; image fails fast.
|
|
11835
|
+
content: toStringToolResultContent(part.content, "ollama"),
|
|
11566
11836
|
tool_name: part.toolUseId
|
|
11567
11837
|
});
|
|
11568
11838
|
}
|
|
@@ -12099,7 +12369,9 @@ function userOrToolMessages(message) {
|
|
|
12099
12369
|
out.push({
|
|
12100
12370
|
role: "tool",
|
|
12101
12371
|
tool_call_id: part.toolUseId,
|
|
12102
|
-
|
|
12372
|
+
// SE7 — this wire's tool role is string-only: text blocks flatten; an
|
|
12373
|
+
// image block fails fast (ConfigurationError).
|
|
12374
|
+
content: toStringToolResultContent(part.content, "openai")
|
|
12103
12375
|
});
|
|
12104
12376
|
}
|
|
12105
12377
|
}
|
|
@@ -13028,18 +13300,20 @@ function levenshtein(a, b) {
|
|
|
13028
13300
|
function createRealLocalRun(options) {
|
|
13029
13301
|
const { userText, id, startTime } = prepareRunContext(options.message);
|
|
13030
13302
|
const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
|
|
13031
|
-
const
|
|
13303
|
+
const runScript = {
|
|
13032
13304
|
events: [],
|
|
13033
13305
|
finalStatus: "running",
|
|
13034
13306
|
cancellable: false,
|
|
13035
|
-
conversation: []
|
|
13307
|
+
conversation: [],
|
|
13308
|
+
// SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
|
|
13309
|
+
...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
|
|
13036
13310
|
};
|
|
13037
13311
|
const handle = new RealLocalRun(
|
|
13038
13312
|
{
|
|
13039
13313
|
id,
|
|
13040
13314
|
agentId: options.agentId,
|
|
13041
13315
|
model: options.model,
|
|
13042
|
-
script:
|
|
13316
|
+
script: runScript,
|
|
13043
13317
|
supportedOps: supported,
|
|
13044
13318
|
startTime
|
|
13045
13319
|
},
|
|
@@ -13151,6 +13425,8 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
13151
13425
|
// M7 — forward SendOptions.context to the loop so every tool handler receives
|
|
13152
13426
|
// it on `ctx.context` (shared run config set once, e.g. projectRoot).
|
|
13153
13427
|
...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
|
|
13428
|
+
// SE2 — forward the opt-in typed runtime-event sink to the loop.
|
|
13429
|
+
...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
|
|
13154
13430
|
// #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
|
|
13155
13431
|
// can enable them via SendOptions (not only internal AgentLoopInputs).
|
|
13156
13432
|
...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
|
|
@@ -15843,7 +16119,7 @@ function wrapRunWithPostReplyHook(args) {
|
|
|
15843
16119
|
async function executeSendLocked(inputs, message, options) {
|
|
15844
16120
|
if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
|
|
15845
16121
|
await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
|
|
15846
|
-
inputs.applyModelOverride(options.model);
|
|
16122
|
+
inputs.applyModelOverride(normalizeModel(options.model));
|
|
15847
16123
|
const userText = typeof message === "string" ? message : message.text;
|
|
15848
16124
|
if (inputs.options.onBeforeSend !== void 0) {
|
|
15849
16125
|
await inputs.options.onBeforeSend({
|
|
@@ -15995,7 +16271,7 @@ var LocalAgent = class {
|
|
|
15995
16271
|
constructor(options) {
|
|
15996
16272
|
this.agentId = options.agentId ?? generateLocalAgentId();
|
|
15997
16273
|
this._telemetry = createTelemetry(options.telemetry);
|
|
15998
|
-
this.model = options.model;
|
|
16274
|
+
this.model = normalizeModel(options.model);
|
|
15999
16275
|
this.options = options;
|
|
16000
16276
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
16001
16277
|
this.conversationStorage = options.conversationStorage;
|
|
@@ -16062,6 +16338,11 @@ var LocalAgent = class {
|
|
|
16062
16338
|
hooks() {
|
|
16063
16339
|
return this.hooksExecutor;
|
|
16064
16340
|
}
|
|
16341
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
16342
|
+
generate(message, options) {
|
|
16343
|
+
const { apiKey, local } = this.options;
|
|
16344
|
+
return agentGenerate(this, this.model, apiKey, local, message, options);
|
|
16345
|
+
}
|
|
16065
16346
|
async send(message, options = {}) {
|
|
16066
16347
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
16067
16348
|
validateToolCatalog(options.tools);
|
|
@@ -16301,6 +16582,7 @@ function includesSetting(options, source) {
|
|
|
16301
16582
|
|
|
16302
16583
|
// src/agent-helpers.ts
|
|
16303
16584
|
async function runCreateUnderSpan(options, span) {
|
|
16585
|
+
options = { ...options, model: normalizeModel(options.model) };
|
|
16304
16586
|
validateAgentOptions(options);
|
|
16305
16587
|
validateCloudToolParity(options);
|
|
16306
16588
|
await guardAgainstIdCollision(options);
|
|
@@ -16374,7 +16656,10 @@ async function createLocalAgent(options) {
|
|
|
16374
16656
|
const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
|
|
16375
16657
|
const shape = validateApiKeyShape(apiKey, {
|
|
16376
16658
|
strict: willFlowToProvider,
|
|
16377
|
-
|
|
16659
|
+
// `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
|
|
16660
|
+
// here is the idempotent narrowing of the widened public type (`{id}` passes
|
|
16661
|
+
// through by reference) — cleaner than an `as` cast.
|
|
16662
|
+
...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
|
|
16378
16663
|
});
|
|
16379
16664
|
if (shape.malformed) {
|
|
16380
16665
|
throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
|
|
@@ -16440,6 +16725,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
|
|
|
16440
16725
|
...existing.options,
|
|
16441
16726
|
...options,
|
|
16442
16727
|
...mergedLocal !== void 0 ? { local: mergedLocal } : {},
|
|
16728
|
+
// SE8 — normalize a caller-supplied bare-string model override at this resume
|
|
16729
|
+
// boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
|
|
16730
|
+
// honors it; local resume forces the persisted model below.
|
|
16731
|
+
model: normalizeModel(options.model ?? existing.options.model),
|
|
16443
16732
|
mcpServers: void 0,
|
|
16444
16733
|
agentId
|
|
16445
16734
|
};
|
|
@@ -16806,6 +17095,7 @@ async function getOrCreateUncached(agentId, options) {
|
|
|
16806
17095
|
}
|
|
16807
17096
|
setAgentFacade({
|
|
16808
17097
|
create: (options) => Agent.create(options),
|
|
17098
|
+
delete: (agentId) => Agent.delete(agentId),
|
|
16809
17099
|
prompt: (message, options) => Agent.prompt(message, options),
|
|
16810
17100
|
get: (agentId) => Agent.get(agentId),
|
|
16811
17101
|
resume: (agentId, options) => Agent.resume(agentId, options),
|