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