@theokit/sdk 2.19.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -0
- package/dist/a2a/index.cjs +611 -274
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +612 -275
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/types.d.cts +7 -0
- package/dist/a2a/types.d.ts +7 -0
- package/dist/agent-builder.d.ts +2 -1
- package/dist/agent-generate.d.ts +12 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +5 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/theokit-client.d.cts +6 -0
- package/dist/client/theokit-client.d.ts +6 -0
- package/dist/client/types.d.cts +2 -0
- package/dist/client/types.d.ts +2 -0
- package/dist/create-skill.d.ts +29 -0
- package/dist/{cron-D_wK1S-0.d.cts → cron-YrmsszEN.d.cts} +110 -3
- package/dist/{cron-Cep07kTz.d.ts → cron-dpvtRoro.d.ts} +110 -3
- package/dist/cron.cjs +660 -370
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +3 -2
- package/dist/cron.d.ts +3 -2
- package/dist/cron.js +661 -371
- package/dist/cron.js.map +1 -1
- package/dist/{errors-5lj1EWgs.d.ts → errors-C4vZPqXf.d.ts} +2 -2
- package/dist/{errors-CE-lMBi2.d.cts → errors-DrcpYVfZ.d.cts} +2 -2
- package/dist/errors.d.cts +3 -2
- package/dist/eval.cjs +660 -370
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +660 -370
- package/dist/eval.js.map +1 -1
- package/dist/generate-object.d.ts +19 -4
- package/dist/index.cjs +867 -371
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +274 -16
- package/dist/index.d.ts +274 -16
- package/dist/index.js +863 -373
- package/dist/index.js.map +1 -1
- package/dist/internal/agent-loop/loop-types.d.ts +2 -0
- package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
- package/dist/internal/llm/tool-result-content.d.ts +40 -0
- package/dist/internal/llm/types.d.ts +6 -1
- package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
- package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
- package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
- package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
- package/dist/internal/persistence/session-meta.d.cts +13 -0
- package/dist/internal/persistence/session-meta.d.ts +13 -0
- package/dist/internal/runtime/model-selection.d.ts +14 -0
- package/dist/internal/structured-output-helpers.d.ts +1 -1
- package/dist/permission-engine.d.ts +32 -1
- package/dist/{run-BgfBWX-z.d.cts → run-BMo8yRwK.d.cts} +262 -19
- package/dist/{run-BgfBWX-z.d.ts → run-BMo8yRwK.d.ts} +262 -19
- package/dist/stream-object.d.ts +2 -1
- package/dist/tool-error.d.ts +30 -0
- package/dist/types/agent-prims.d.ts +10 -8
- package/dist/types/agent.d.ts +22 -1
- package/dist/types/content-blocks.d.ts +47 -0
- package/dist/types/conversation-storage.d.ts +38 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/messages.d.ts +2 -9
- package/dist/types/run-events.d.ts +84 -0
- package/dist/types/run.d.ts +115 -1
- package/dist/types/session.d.ts +99 -0
- package/dist/types/workflow.d.ts +7 -0
- package/dist/workflow.cjs +7 -2
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +2 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +7 -2
- package/dist/workflow.js.map +1 -1
- package/package.json +3 -23
- package/dist/internal/observability/context.d.cts +0 -23
- package/dist/internal/observability/context.d.ts +0 -23
- package/dist/internal/observability/index.cjs +0 -38
- package/dist/internal/observability/index.cjs.map +0 -1
- package/dist/internal/observability/index.d.cts +0 -8
- package/dist/internal/observability/index.d.ts +0 -8
- package/dist/internal/observability/index.js +0 -33
- package/dist/internal/observability/index.js.map +0 -1
- package/dist/internal/plugins/index.cjs +0 -363
- package/dist/internal/plugins/index.cjs.map +0 -1
- package/dist/internal/plugins/index.js +0 -357
- package/dist/internal/plugins/index.js.map +0 -1
- package/dist/internal/workflow/index.d.ts +0 -12
- package/dist/server/adapter/index.d.cts +0 -8
- package/dist/server/adapter/index.d.ts +0 -8
package/dist/eval.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { z, toJSONSchema } from 'zod';
|
|
2
|
+
import { createRequire } from 'module';
|
|
1
3
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
2
4
|
import { mkdir, writeFile, readFile, unlink, open, rename, statfs, stat, rm, readdir, appendFile, access } from 'fs/promises';
|
|
3
5
|
import { join, dirname, resolve, sep, relative, isAbsolute } from 'path';
|
|
4
|
-
import { z, toJSONSchema } from 'zod';
|
|
5
6
|
import { readFileSync, mkdirSync, appendFileSync, readdirSync, existsSync, realpathSync, lstatSync, readlinkSync } from 'fs';
|
|
6
7
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
7
|
-
import { createRequire } from 'module';
|
|
8
8
|
import { homedir } from 'os';
|
|
9
9
|
import { execFile, spawn } from 'child_process';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
@@ -509,6 +509,256 @@ var init_errors = __esm({
|
|
|
509
509
|
};
|
|
510
510
|
}
|
|
511
511
|
});
|
|
512
|
+
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
513
|
+
return toJSONSchema(schema, options);
|
|
514
|
+
}
|
|
515
|
+
var init_to_json_schema = __esm({
|
|
516
|
+
"src/internal/zod/to-json-schema.ts"() {
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
function requireZod() {
|
|
520
|
+
if (cachedZ !== void 0) return cachedZ;
|
|
521
|
+
const r = createRequire(import.meta.url);
|
|
522
|
+
let mod;
|
|
523
|
+
try {
|
|
524
|
+
mod = r("zod");
|
|
525
|
+
} catch (cause) {
|
|
526
|
+
throw new ConfigurationError(
|
|
527
|
+
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
528
|
+
{ code: "zod_not_installed", cause }
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
cachedZ = mod.z ?? mod;
|
|
532
|
+
return cachedZ;
|
|
533
|
+
}
|
|
534
|
+
function makeOutputTool(jsonSchema, onCapture) {
|
|
535
|
+
return {
|
|
536
|
+
name: "output",
|
|
537
|
+
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
538
|
+
inputSchema: jsonSchema,
|
|
539
|
+
handler: (input) => {
|
|
540
|
+
const out = onCapture(input);
|
|
541
|
+
if (typeof out === "string") return out;
|
|
542
|
+
if (out instanceof Promise) return out;
|
|
543
|
+
return "";
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function buildTransientAgentOptions(params) {
|
|
548
|
+
return {
|
|
549
|
+
model: params.model,
|
|
550
|
+
local: params.local,
|
|
551
|
+
tools: [params.outputTool],
|
|
552
|
+
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
553
|
+
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
554
|
+
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function extractUsage(result) {
|
|
558
|
+
const u = result.usage;
|
|
559
|
+
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
560
|
+
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
561
|
+
}
|
|
562
|
+
function buildToolPrompt(prompt) {
|
|
563
|
+
return `${prompt}
|
|
564
|
+
|
|
565
|
+
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
566
|
+
}
|
|
567
|
+
function setupStructuredOutput(schema, maxRetries) {
|
|
568
|
+
const z7 = requireZod();
|
|
569
|
+
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
570
|
+
return {
|
|
571
|
+
z: z7,
|
|
572
|
+
jsonSchema,
|
|
573
|
+
maxRetries: maxRetries ?? 1,
|
|
574
|
+
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
async function disposeAndDeleteTransient(agent, deletor) {
|
|
578
|
+
await agent.dispose();
|
|
579
|
+
try {
|
|
580
|
+
await deletor(agent.agentId);
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
var cachedZ;
|
|
585
|
+
var init_structured_output_helpers = __esm({
|
|
586
|
+
"src/internal/structured-output-helpers.ts"() {
|
|
587
|
+
init_errors();
|
|
588
|
+
init_to_json_schema();
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// src/generate-object.ts
|
|
593
|
+
var generate_object_exports = {};
|
|
594
|
+
__export(generate_object_exports, {
|
|
595
|
+
GenerateObjectError: () => GenerateObjectError,
|
|
596
|
+
generateObjectImpl: () => generateObjectImpl
|
|
597
|
+
});
|
|
598
|
+
function salvagePartial(schema, raw) {
|
|
599
|
+
if (typeof raw !== "object" || raw === null) return raw;
|
|
600
|
+
const shape = schema.shape;
|
|
601
|
+
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
602
|
+
const rawObj = raw;
|
|
603
|
+
const out = {};
|
|
604
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
605
|
+
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
606
|
+
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
607
|
+
if (parsed.success) out[key] = parsed.data;
|
|
608
|
+
}
|
|
609
|
+
return out;
|
|
610
|
+
}
|
|
611
|
+
async function runReasoningPhase(options, deps) {
|
|
612
|
+
const reasoningOptions = {
|
|
613
|
+
model: options.model,
|
|
614
|
+
local: options.local,
|
|
615
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
616
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
617
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
618
|
+
};
|
|
619
|
+
const reasoningAgent = await deps.create(reasoningOptions);
|
|
620
|
+
try {
|
|
621
|
+
const run = await reasoningAgent.send(options.prompt);
|
|
622
|
+
const result = await run.wait();
|
|
623
|
+
const text = result.result;
|
|
624
|
+
return typeof text === "string" ? text : options.prompt;
|
|
625
|
+
} finally {
|
|
626
|
+
await disposeAndDeleteTransient(reasoningAgent, deps.delete);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
async function generateObjectImpl(options, deps) {
|
|
630
|
+
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
631
|
+
options.schema,
|
|
632
|
+
options.maxRetries
|
|
633
|
+
);
|
|
634
|
+
let capturedRaw;
|
|
635
|
+
let lastUsage = initialUsage;
|
|
636
|
+
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
637
|
+
class CaptureSentinel extends Error {
|
|
638
|
+
constructor(captured) {
|
|
639
|
+
super("generate-object-capture");
|
|
640
|
+
this.captured = captured;
|
|
641
|
+
}
|
|
642
|
+
captured;
|
|
643
|
+
[sentinel] = true;
|
|
644
|
+
}
|
|
645
|
+
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
646
|
+
if (capturedRaw === void 0) {
|
|
647
|
+
capturedRaw = input;
|
|
648
|
+
}
|
|
649
|
+
throw new CaptureSentinel(input);
|
|
650
|
+
});
|
|
651
|
+
const reasoningText = options.structuringModel !== void 0 ? await runReasoningPhase(options, deps) : void 0;
|
|
652
|
+
const structuringModel = options.structuringModel ?? options.model;
|
|
653
|
+
const structuringPrompt = reasoningText ?? options.prompt;
|
|
654
|
+
const agentOptions = buildTransientAgentOptions({
|
|
655
|
+
model: structuringModel,
|
|
656
|
+
local: options.local,
|
|
657
|
+
outputTool,
|
|
658
|
+
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
659
|
+
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
660
|
+
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
661
|
+
});
|
|
662
|
+
const agent = await deps.create(agentOptions);
|
|
663
|
+
try {
|
|
664
|
+
const userMessage = buildToolPrompt(structuringPrompt);
|
|
665
|
+
let lastParseError;
|
|
666
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
667
|
+
capturedRaw = void 0;
|
|
668
|
+
const run = await agent.send(userMessage);
|
|
669
|
+
const result = await run.wait();
|
|
670
|
+
lastUsage = extractUsage(result);
|
|
671
|
+
if (capturedRaw === void 0) {
|
|
672
|
+
if (result.status === "error" && result.error !== void 0) {
|
|
673
|
+
throw new GenerateObjectError(
|
|
674
|
+
"no_tool_call",
|
|
675
|
+
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
676
|
+
result.error
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
if (attempt === maxRetries) {
|
|
680
|
+
throw new GenerateObjectError(
|
|
681
|
+
"no_tool_call",
|
|
682
|
+
"The model returned text instead of calling the `output` tool."
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
const parsed = options.schema.safeParse(capturedRaw);
|
|
688
|
+
if (parsed.success) {
|
|
689
|
+
return {
|
|
690
|
+
object: parsed.data,
|
|
691
|
+
raw: capturedRaw,
|
|
692
|
+
usage: lastUsage,
|
|
693
|
+
finishReason: "tool_use"
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
lastParseError = parsed.error;
|
|
697
|
+
}
|
|
698
|
+
if (options.errorStrategy === "return-raw") {
|
|
699
|
+
return {
|
|
700
|
+
object: capturedRaw,
|
|
701
|
+
raw: capturedRaw,
|
|
702
|
+
usage: lastUsage,
|
|
703
|
+
finishReason: "tool_use"
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
if (options.errorStrategy === "return-partial") {
|
|
707
|
+
return {
|
|
708
|
+
object: salvagePartial(options.schema, capturedRaw),
|
|
709
|
+
raw: capturedRaw,
|
|
710
|
+
usage: lastUsage,
|
|
711
|
+
finishReason: "tool_use"
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
throw new GenerateObjectError(
|
|
715
|
+
"parse_failed",
|
|
716
|
+
"Schema parse failed after all retries.",
|
|
717
|
+
lastParseError
|
|
718
|
+
);
|
|
719
|
+
} finally {
|
|
720
|
+
await disposeAndDeleteTransient(agent, deps.delete);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
var GenerateObjectError;
|
|
724
|
+
var init_generate_object = __esm({
|
|
725
|
+
"src/generate-object.ts"() {
|
|
726
|
+
init_structured_output_helpers();
|
|
727
|
+
GenerateObjectError = class extends Error {
|
|
728
|
+
name = "GenerateObjectError";
|
|
729
|
+
code;
|
|
730
|
+
cause;
|
|
731
|
+
constructor(code, message, cause) {
|
|
732
|
+
super(message);
|
|
733
|
+
this.code = code;
|
|
734
|
+
if (cause !== void 0) this.cause = cause;
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
741
|
+
var agent_factory_registry_exports = {};
|
|
742
|
+
__export(agent_factory_registry_exports, {
|
|
743
|
+
getAgentFacade: () => getAgentFacade,
|
|
744
|
+
setAgentFacade: () => setAgentFacade
|
|
745
|
+
});
|
|
746
|
+
function setAgentFacade(facade) {
|
|
747
|
+
registered = facade;
|
|
748
|
+
}
|
|
749
|
+
function getAgentFacade() {
|
|
750
|
+
if (registered === void 0) {
|
|
751
|
+
throw new Error(
|
|
752
|
+
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
return registered;
|
|
756
|
+
}
|
|
757
|
+
var registered;
|
|
758
|
+
var init_agent_factory_registry = __esm({
|
|
759
|
+
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
760
|
+
}
|
|
761
|
+
});
|
|
512
762
|
|
|
513
763
|
// src/internal/persistence/cwd-mutex.ts
|
|
514
764
|
function withCwdMutex(key, fn) {
|
|
@@ -1426,29 +1676,6 @@ var init_judge_call = __esm({
|
|
|
1426
1676
|
}
|
|
1427
1677
|
});
|
|
1428
1678
|
|
|
1429
|
-
// src/internal/runtime/registry/agent-factory-registry.ts
|
|
1430
|
-
var agent_factory_registry_exports = {};
|
|
1431
|
-
__export(agent_factory_registry_exports, {
|
|
1432
|
-
getAgentFacade: () => getAgentFacade,
|
|
1433
|
-
setAgentFacade: () => setAgentFacade
|
|
1434
|
-
});
|
|
1435
|
-
function setAgentFacade(facade) {
|
|
1436
|
-
registered3 = facade;
|
|
1437
|
-
}
|
|
1438
|
-
function getAgentFacade() {
|
|
1439
|
-
if (registered3 === void 0) {
|
|
1440
|
-
throw new Error(
|
|
1441
|
-
"internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1444
|
-
return registered3;
|
|
1445
|
-
}
|
|
1446
|
-
var registered3;
|
|
1447
|
-
var init_agent_factory_registry = __esm({
|
|
1448
|
-
"src/internal/runtime/registry/agent-factory-registry.ts"() {
|
|
1449
|
-
}
|
|
1450
|
-
});
|
|
1451
|
-
|
|
1452
1679
|
// src/internal/runtime/lifecycle/run-to-completion.ts
|
|
1453
1680
|
var run_to_completion_exports = {};
|
|
1454
1681
|
__export(run_to_completion_exports, {
|
|
@@ -1613,14 +1840,14 @@ async function forkAgentImpl(parent, options, deps) {
|
|
|
1613
1840
|
return {
|
|
1614
1841
|
result: result.result,
|
|
1615
1842
|
toolCalls: [],
|
|
1616
|
-
usage:
|
|
1843
|
+
usage: extractUsage2(result)
|
|
1617
1844
|
};
|
|
1618
1845
|
});
|
|
1619
1846
|
} finally {
|
|
1620
1847
|
await fork.dispose();
|
|
1621
1848
|
}
|
|
1622
1849
|
}
|
|
1623
|
-
function
|
|
1850
|
+
function extractUsage2(result) {
|
|
1624
1851
|
if (typeof result !== "object" || result === null) {
|
|
1625
1852
|
return { inputTokens: 0, outputTokens: 0 };
|
|
1626
1853
|
}
|
|
@@ -2054,323 +2281,117 @@ async function runWorkAndFinalize(taskId, aborter, work) {
|
|
|
2054
2281
|
void checkCancelRequestedAt(taskId, aborter);
|
|
2055
2282
|
emitToSubscribers(taskId, {
|
|
2056
2283
|
type: "progress",
|
|
2057
|
-
taskId,
|
|
2058
|
-
at: Date.now(),
|
|
2059
|
-
payload
|
|
2060
|
-
});
|
|
2061
|
-
}
|
|
2062
|
-
};
|
|
2063
|
-
try {
|
|
2064
|
-
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2065
|
-
if (aborter.signal.aborted) {
|
|
2066
|
-
const cancelledAt = Date.now();
|
|
2067
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2068
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2069
|
-
return;
|
|
2070
|
-
}
|
|
2071
|
-
const finishedAt = Date.now();
|
|
2072
|
-
await transition(taskId, "finished", { finishedAt, result });
|
|
2073
|
-
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2074
|
-
} catch (err) {
|
|
2075
|
-
if (aborter.signal.aborted) {
|
|
2076
|
-
const cancelledAt = Date.now();
|
|
2077
|
-
await transition(taskId, "cancelled", { cancelledAt });
|
|
2078
|
-
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2079
|
-
return;
|
|
2080
|
-
}
|
|
2081
|
-
const erroredAt = Date.now();
|
|
2082
|
-
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2083
|
-
await transition(taskId, "error", { erroredAt, error });
|
|
2084
|
-
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2088
|
-
if (aborter.signal.aborted) return;
|
|
2089
|
-
try {
|
|
2090
|
-
const handle = await state.store.get(taskId);
|
|
2091
|
-
if (handle?.cancelRequested === true) {
|
|
2092
|
-
aborter.abort("cancelRequested");
|
|
2093
|
-
}
|
|
2094
|
-
} catch {
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
async function acquireSlot() {
|
|
2098
|
-
if (reentryAls.getStore() === true) {
|
|
2099
|
-
return () => {
|
|
2100
|
-
};
|
|
2101
|
-
}
|
|
2102
|
-
return state.semaphore.acquire();
|
|
2103
|
-
}
|
|
2104
|
-
async function submit(internal) {
|
|
2105
|
-
state.firstSubmitSeen = true;
|
|
2106
|
-
startEvictTimerIfNeeded();
|
|
2107
|
-
const resolvedId = resolveIdInternal(internal);
|
|
2108
|
-
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2109
|
-
const existing = await state.store.get(resolvedId);
|
|
2110
|
-
if (existing !== void 0) {
|
|
2111
|
-
submitSpan.end();
|
|
2112
|
-
return existing;
|
|
2113
|
-
}
|
|
2114
|
-
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2115
|
-
submitSpan.end();
|
|
2116
|
-
if (internal.signal?.aborted === true) {
|
|
2117
|
-
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2118
|
-
}
|
|
2119
|
-
const aborter = new AbortController();
|
|
2120
|
-
state.aborters.set(resolvedId, aborter);
|
|
2121
|
-
if (internal.signal !== void 0) {
|
|
2122
|
-
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2123
|
-
once: true
|
|
2124
|
-
});
|
|
2125
|
-
}
|
|
2126
|
-
const release = await acquireSlot();
|
|
2127
|
-
void (async () => {
|
|
2128
|
-
try {
|
|
2129
|
-
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2130
|
-
if (aborter.signal.aborted) {
|
|
2131
|
-
const cancelledAt = Date.now();
|
|
2132
|
-
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2133
|
-
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2134
|
-
return;
|
|
2135
|
-
}
|
|
2136
|
-
const startedAt = Date.now();
|
|
2137
|
-
await transition(resolvedId, "running", { startedAt });
|
|
2138
|
-
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2139
|
-
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2140
|
-
} finally {
|
|
2141
|
-
release();
|
|
2142
|
-
state.aborters.delete(resolvedId);
|
|
2143
|
-
}
|
|
2144
|
-
})();
|
|
2145
|
-
return queuedHandle;
|
|
2146
|
-
}
|
|
2147
|
-
async function get(id) {
|
|
2148
|
-
if (!isValidTaskId(id, true)) return void 0;
|
|
2149
|
-
return state.store.get(id);
|
|
2150
|
-
}
|
|
2151
|
-
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2152
|
-
var init_registry = __esm({
|
|
2153
|
-
"src/internal/task/registry.ts"() {
|
|
2154
|
-
init_errors();
|
|
2155
|
-
init_task();
|
|
2156
|
-
init_async_semaphore();
|
|
2157
|
-
init_ring_buffer();
|
|
2158
|
-
init_store();
|
|
2159
|
-
init_subscribe();
|
|
2160
|
-
init_telemetry();
|
|
2161
|
-
DEFAULT_CONCURRENCY = 8;
|
|
2162
|
-
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2163
|
-
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2164
|
-
RING_CAP = 64;
|
|
2165
|
-
reentryAls = new AsyncLocalStorage();
|
|
2166
|
-
state = buildState({});
|
|
2167
|
-
}
|
|
2168
|
-
});
|
|
2169
|
-
function toJsonSchema(schema, options = { unrepresentable: "any" }) {
|
|
2170
|
-
return toJSONSchema(schema, options);
|
|
2171
|
-
}
|
|
2172
|
-
var init_to_json_schema = __esm({
|
|
2173
|
-
"src/internal/zod/to-json-schema.ts"() {
|
|
2174
|
-
}
|
|
2175
|
-
});
|
|
2176
|
-
function requireZod() {
|
|
2177
|
-
if (cachedZ !== void 0) return cachedZ;
|
|
2178
|
-
const r = createRequire(import.meta.url);
|
|
2179
|
-
let mod;
|
|
2180
|
-
try {
|
|
2181
|
-
mod = r("zod");
|
|
2182
|
-
} catch (cause) {
|
|
2183
|
-
throw new ConfigurationError(
|
|
2184
|
-
'Structured output requires the optional peer dependency `zod`. Add `"zod": "^3.25.0 || ^4.0.0"` to your package.json and reinstall.',
|
|
2185
|
-
{ code: "zod_not_installed", cause }
|
|
2186
|
-
);
|
|
2187
|
-
}
|
|
2188
|
-
cachedZ = mod.z ?? mod;
|
|
2189
|
-
return cachedZ;
|
|
2190
|
-
}
|
|
2191
|
-
function makeOutputTool(jsonSchema, onCapture) {
|
|
2192
|
-
return {
|
|
2193
|
-
name: "output",
|
|
2194
|
-
description: "Call this tool with your final structured answer. Match the JSON schema exactly.",
|
|
2195
|
-
inputSchema: jsonSchema,
|
|
2196
|
-
handler: (input) => {
|
|
2197
|
-
const out = onCapture(input);
|
|
2198
|
-
if (typeof out === "string") return out;
|
|
2199
|
-
if (out instanceof Promise) return out;
|
|
2200
|
-
return "";
|
|
2201
|
-
}
|
|
2202
|
-
};
|
|
2203
|
-
}
|
|
2204
|
-
function buildTransientAgentOptions(params) {
|
|
2205
|
-
return {
|
|
2206
|
-
model: params.model,
|
|
2207
|
-
local: params.local,
|
|
2208
|
-
tools: [params.outputTool],
|
|
2209
|
-
systemPrompt: params.systemPrompt ?? "You produce structured output by calling the `output` tool exactly once. Match the JSON schema.",
|
|
2210
|
-
...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
|
|
2211
|
-
...params.providers !== void 0 ? { providers: params.providers } : {}
|
|
2212
|
-
};
|
|
2213
|
-
}
|
|
2214
|
-
function extractUsage2(result) {
|
|
2215
|
-
const u = result.usage;
|
|
2216
|
-
if (u === void 0) return { inputTokens: 0, outputTokens: 0 };
|
|
2217
|
-
return { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 };
|
|
2218
|
-
}
|
|
2219
|
-
function buildToolPrompt(prompt) {
|
|
2220
|
-
return `${prompt}
|
|
2221
|
-
|
|
2222
|
-
Respond by calling the \`output\` tool with the structured answer that matches the schema.`;
|
|
2223
|
-
}
|
|
2224
|
-
function setupStructuredOutput(schema, maxRetries) {
|
|
2225
|
-
const z7 = requireZod();
|
|
2226
|
-
const jsonSchema = toJsonSchema(schema, { unrepresentable: "any" });
|
|
2227
|
-
return {
|
|
2228
|
-
z: z7,
|
|
2229
|
-
jsonSchema,
|
|
2230
|
-
maxRetries: maxRetries ?? 1,
|
|
2231
|
-
initialUsage: { inputTokens: 0, outputTokens: 0 }
|
|
2232
|
-
};
|
|
2233
|
-
}
|
|
2234
|
-
async function disposeAndDeleteTransient(agent, deletor) {
|
|
2235
|
-
await agent.dispose();
|
|
2236
|
-
try {
|
|
2237
|
-
await deletor(agent.agentId);
|
|
2238
|
-
} catch {
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
|
-
var cachedZ;
|
|
2242
|
-
var init_structured_output_helpers = __esm({
|
|
2243
|
-
"src/internal/structured-output-helpers.ts"() {
|
|
2244
|
-
init_errors();
|
|
2245
|
-
init_to_json_schema();
|
|
2246
|
-
}
|
|
2247
|
-
});
|
|
2248
|
-
|
|
2249
|
-
// src/generate-object.ts
|
|
2250
|
-
var generate_object_exports = {};
|
|
2251
|
-
__export(generate_object_exports, {
|
|
2252
|
-
GenerateObjectError: () => GenerateObjectError,
|
|
2253
|
-
generateObjectImpl: () => generateObjectImpl
|
|
2254
|
-
});
|
|
2255
|
-
function salvagePartial(schema, raw) {
|
|
2256
|
-
if (typeof raw !== "object" || raw === null) return raw;
|
|
2257
|
-
const shape = schema.shape;
|
|
2258
|
-
if (shape === void 0 || typeof shape !== "object") return raw;
|
|
2259
|
-
const rawObj = raw;
|
|
2260
|
-
const out = {};
|
|
2261
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
2262
|
-
if (typeof fieldSchema?.safeParse !== "function") continue;
|
|
2263
|
-
const parsed = fieldSchema.safeParse(rawObj[key]);
|
|
2264
|
-
if (parsed.success) out[key] = parsed.data;
|
|
2265
|
-
}
|
|
2266
|
-
return out;
|
|
2267
|
-
}
|
|
2268
|
-
async function generateObjectImpl(options, deps) {
|
|
2269
|
-
const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
|
|
2270
|
-
options.schema,
|
|
2271
|
-
options.maxRetries
|
|
2272
|
-
);
|
|
2273
|
-
let capturedRaw;
|
|
2274
|
-
let lastUsage = initialUsage;
|
|
2275
|
-
const sentinel = /* @__PURE__ */ Symbol("generate-object-sentinel");
|
|
2276
|
-
class CaptureSentinel extends Error {
|
|
2277
|
-
constructor(captured) {
|
|
2278
|
-
super("generate-object-capture");
|
|
2279
|
-
this.captured = captured;
|
|
2280
|
-
}
|
|
2281
|
-
captured;
|
|
2282
|
-
[sentinel] = true;
|
|
2283
|
-
}
|
|
2284
|
-
const outputTool = makeOutputTool(jsonSchema, (input) => {
|
|
2285
|
-
if (capturedRaw === void 0) {
|
|
2286
|
-
capturedRaw = input;
|
|
2287
|
-
}
|
|
2288
|
-
throw new CaptureSentinel(input);
|
|
2289
|
-
});
|
|
2290
|
-
const agentOptions = buildTransientAgentOptions({
|
|
2291
|
-
model: options.model,
|
|
2292
|
-
local: options.local,
|
|
2293
|
-
outputTool,
|
|
2294
|
-
...options.systemPrompt !== void 0 ? { systemPrompt: options.systemPrompt } : {},
|
|
2295
|
-
...options.apiKey !== void 0 ? { apiKey: options.apiKey } : {},
|
|
2296
|
-
...options.providers !== void 0 ? { providers: options.providers } : {}
|
|
2297
|
-
});
|
|
2298
|
-
const agent = await deps.create(agentOptions);
|
|
2284
|
+
taskId,
|
|
2285
|
+
at: Date.now(),
|
|
2286
|
+
payload
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
};
|
|
2299
2290
|
try {
|
|
2300
|
-
const
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
lastUsage = extractUsage2(result);
|
|
2307
|
-
if (capturedRaw === void 0) {
|
|
2308
|
-
if (result.status === "error" && result.error !== void 0) {
|
|
2309
|
-
throw new GenerateObjectError(
|
|
2310
|
-
"no_tool_call",
|
|
2311
|
-
`Agent run failed before the model could reply: ${result.error.message ?? "unknown error"} [${result.error.code ?? "?"}]`,
|
|
2312
|
-
result.error
|
|
2313
|
-
);
|
|
2314
|
-
}
|
|
2315
|
-
if (attempt === maxRetries) {
|
|
2316
|
-
throw new GenerateObjectError(
|
|
2317
|
-
"no_tool_call",
|
|
2318
|
-
"The model returned text instead of calling the `output` tool."
|
|
2319
|
-
);
|
|
2320
|
-
}
|
|
2321
|
-
continue;
|
|
2322
|
-
}
|
|
2323
|
-
const parsed = options.schema.safeParse(capturedRaw);
|
|
2324
|
-
if (parsed.success) {
|
|
2325
|
-
return {
|
|
2326
|
-
object: parsed.data,
|
|
2327
|
-
raw: capturedRaw,
|
|
2328
|
-
usage: lastUsage,
|
|
2329
|
-
finishReason: "tool_use"
|
|
2330
|
-
};
|
|
2331
|
-
}
|
|
2332
|
-
lastParseError = parsed.error;
|
|
2291
|
+
const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
|
|
2292
|
+
if (aborter.signal.aborted) {
|
|
2293
|
+
const cancelledAt = Date.now();
|
|
2294
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2295
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2296
|
+
return;
|
|
2333
2297
|
}
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
};
|
|
2298
|
+
const finishedAt = Date.now();
|
|
2299
|
+
await transition(taskId, "finished", { finishedAt, result });
|
|
2300
|
+
emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
|
|
2301
|
+
} catch (err) {
|
|
2302
|
+
if (aborter.signal.aborted) {
|
|
2303
|
+
const cancelledAt = Date.now();
|
|
2304
|
+
await transition(taskId, "cancelled", { cancelledAt });
|
|
2305
|
+
emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
|
|
2306
|
+
return;
|
|
2341
2307
|
}
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2308
|
+
const erroredAt = Date.now();
|
|
2309
|
+
const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
|
|
2310
|
+
await transition(taskId, "error", { erroredAt, error });
|
|
2311
|
+
emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
async function checkCancelRequestedAt(taskId, aborter) {
|
|
2315
|
+
if (aborter.signal.aborted) return;
|
|
2316
|
+
try {
|
|
2317
|
+
const handle = await state.store.get(taskId);
|
|
2318
|
+
if (handle?.cancelRequested === true) {
|
|
2319
|
+
aborter.abort("cancelRequested");
|
|
2349
2320
|
}
|
|
2350
|
-
|
|
2351
|
-
"parse_failed",
|
|
2352
|
-
"Schema parse failed after all retries.",
|
|
2353
|
-
lastParseError
|
|
2354
|
-
);
|
|
2355
|
-
} finally {
|
|
2356
|
-
await disposeAndDeleteTransient(agent, deps.delete);
|
|
2321
|
+
} catch {
|
|
2357
2322
|
}
|
|
2358
2323
|
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
init_structured_output_helpers();
|
|
2363
|
-
GenerateObjectError = class extends Error {
|
|
2364
|
-
name = "GenerateObjectError";
|
|
2365
|
-
code;
|
|
2366
|
-
cause;
|
|
2367
|
-
constructor(code, message, cause) {
|
|
2368
|
-
super(message);
|
|
2369
|
-
this.code = code;
|
|
2370
|
-
if (cause !== void 0) this.cause = cause;
|
|
2371
|
-
}
|
|
2324
|
+
async function acquireSlot() {
|
|
2325
|
+
if (reentryAls.getStore() === true) {
|
|
2326
|
+
return () => {
|
|
2372
2327
|
};
|
|
2373
2328
|
}
|
|
2329
|
+
return state.semaphore.acquire();
|
|
2330
|
+
}
|
|
2331
|
+
async function submit(internal) {
|
|
2332
|
+
state.firstSubmitSeen = true;
|
|
2333
|
+
startEvictTimerIfNeeded();
|
|
2334
|
+
const resolvedId = resolveIdInternal(internal);
|
|
2335
|
+
const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
|
|
2336
|
+
const existing = await state.store.get(resolvedId);
|
|
2337
|
+
if (existing !== void 0) {
|
|
2338
|
+
submitSpan.end();
|
|
2339
|
+
return existing;
|
|
2340
|
+
}
|
|
2341
|
+
const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
|
|
2342
|
+
submitSpan.end();
|
|
2343
|
+
if (internal.signal?.aborted === true) {
|
|
2344
|
+
return shortCircuitAborted(queuedHandle, internal.signal);
|
|
2345
|
+
}
|
|
2346
|
+
const aborter = new AbortController();
|
|
2347
|
+
state.aborters.set(resolvedId, aborter);
|
|
2348
|
+
if (internal.signal !== void 0) {
|
|
2349
|
+
internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
|
|
2350
|
+
once: true
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
const release = await acquireSlot();
|
|
2354
|
+
void (async () => {
|
|
2355
|
+
try {
|
|
2356
|
+
await checkCancelRequestedAt(resolvedId, aborter);
|
|
2357
|
+
if (aborter.signal.aborted) {
|
|
2358
|
+
const cancelledAt = Date.now();
|
|
2359
|
+
await transition(resolvedId, "cancelled", { cancelledAt });
|
|
2360
|
+
emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2363
|
+
const startedAt = Date.now();
|
|
2364
|
+
await transition(resolvedId, "running", { startedAt });
|
|
2365
|
+
emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
|
|
2366
|
+
await runWorkAndFinalize(resolvedId, aborter, internal.work);
|
|
2367
|
+
} finally {
|
|
2368
|
+
release();
|
|
2369
|
+
state.aborters.delete(resolvedId);
|
|
2370
|
+
}
|
|
2371
|
+
})();
|
|
2372
|
+
return queuedHandle;
|
|
2373
|
+
}
|
|
2374
|
+
async function get(id) {
|
|
2375
|
+
if (!isValidTaskId(id, true)) return void 0;
|
|
2376
|
+
return state.store.get(id);
|
|
2377
|
+
}
|
|
2378
|
+
var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state;
|
|
2379
|
+
var init_registry = __esm({
|
|
2380
|
+
"src/internal/task/registry.ts"() {
|
|
2381
|
+
init_errors();
|
|
2382
|
+
init_task();
|
|
2383
|
+
init_async_semaphore();
|
|
2384
|
+
init_ring_buffer();
|
|
2385
|
+
init_store();
|
|
2386
|
+
init_subscribe();
|
|
2387
|
+
init_telemetry();
|
|
2388
|
+
DEFAULT_CONCURRENCY = 8;
|
|
2389
|
+
DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
|
|
2390
|
+
EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2391
|
+
RING_CAP = 64;
|
|
2392
|
+
reentryAls = new AsyncLocalStorage();
|
|
2393
|
+
state = buildState({});
|
|
2394
|
+
}
|
|
2374
2395
|
});
|
|
2375
2396
|
|
|
2376
2397
|
// src/stream-object.ts
|
|
@@ -2427,7 +2448,7 @@ async function* streamObjectImpl(options, deps) {
|
|
|
2427
2448
|
}
|
|
2428
2449
|
}
|
|
2429
2450
|
const result = await run.wait();
|
|
2430
|
-
lastUsage =
|
|
2451
|
+
lastUsage = extractUsage(result);
|
|
2431
2452
|
if (capturedRaw === void 0) {
|
|
2432
2453
|
if (result.status === "error" && result.error !== void 0) {
|
|
2433
2454
|
throw new StreamObjectError(
|
|
@@ -2773,6 +2794,7 @@ var AgentBuilder = class {
|
|
|
2773
2794
|
constructor(deps) {
|
|
2774
2795
|
this.deps = deps;
|
|
2775
2796
|
}
|
|
2797
|
+
/** SE8 — accepts a bare-string id shorthand (`"openai/gpt-4o-mini"`) or a {@link ModelSelection}. */
|
|
2776
2798
|
model(m) {
|
|
2777
2799
|
this.opts.model = m;
|
|
2778
2800
|
return this;
|
|
@@ -3122,6 +3144,69 @@ function isLocalAgentId(id) {
|
|
|
3122
3144
|
return id.startsWith(PREFIX.localAgent);
|
|
3123
3145
|
}
|
|
3124
3146
|
|
|
3147
|
+
// src/internal/runtime/config/default-model.ts
|
|
3148
|
+
var DEFAULT_AGENTIC_MODEL_ID = "google/gemini-2.0-flash-001";
|
|
3149
|
+
|
|
3150
|
+
// src/agent-generate.ts
|
|
3151
|
+
async function agentGenerate(agent, agentModel, agentApiKey, agentLocal, input, options) {
|
|
3152
|
+
const { output, maxRetries, errorStrategy, ...sendOptions } = options;
|
|
3153
|
+
const run = await agent.send(input, sendOptions);
|
|
3154
|
+
const result = await run.wait();
|
|
3155
|
+
const { generateObjectImpl: generateObjectImpl2, GenerateObjectError: GenerateObjectError2 } = await Promise.resolve().then(() => (init_generate_object(), generate_object_exports));
|
|
3156
|
+
const answer = structurableAnswerOrThrow(result, GenerateObjectError2);
|
|
3157
|
+
const { getAgentFacade: getAgentFacade2 } = await Promise.resolve().then(() => (init_agent_factory_registry(), agent_factory_registry_exports));
|
|
3158
|
+
const facade = getAgentFacade2();
|
|
3159
|
+
const structured = await generateObjectImpl2(
|
|
3160
|
+
{
|
|
3161
|
+
prompt: answer,
|
|
3162
|
+
schema: output,
|
|
3163
|
+
// `agentModel` arrives already normalized (`this.model` passed through
|
|
3164
|
+
// `normalizeModel` in the LocalAgent/CloudAgent constructor), so the widened
|
|
3165
|
+
// `string | ModelSelection` field only ever receives a `ModelSelection` here.
|
|
3166
|
+
model: agentModel ?? { id: DEFAULT_AGENTIC_MODEL_ID },
|
|
3167
|
+
// `local` is required to keep the transient structuring agent local-only;
|
|
3168
|
+
// default to the process cwd when the agent had no explicit local config.
|
|
3169
|
+
local: agentLocal ?? { cwd: process.cwd() },
|
|
3170
|
+
...agentApiKey !== void 0 ? { apiKey: agentApiKey } : {},
|
|
3171
|
+
...maxRetries !== void 0 ? { maxRetries } : {},
|
|
3172
|
+
...errorStrategy !== void 0 ? { errorStrategy } : {}
|
|
3173
|
+
},
|
|
3174
|
+
{
|
|
3175
|
+
create: (opts) => facade.create(opts),
|
|
3176
|
+
delete: (agentId) => facade.delete(agentId)
|
|
3177
|
+
}
|
|
3178
|
+
);
|
|
3179
|
+
return {
|
|
3180
|
+
object: structured.object,
|
|
3181
|
+
result,
|
|
3182
|
+
raw: structured.raw,
|
|
3183
|
+
usage: structured.usage
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
function structurableAnswerOrThrow(result, GenerateObjectError2) {
|
|
3187
|
+
if (result.status === "error") {
|
|
3188
|
+
throw new GenerateObjectError2(
|
|
3189
|
+
"no_tool_call",
|
|
3190
|
+
`Agent run failed before an answer could be structured: ${result.error?.message ?? "unknown error"} [${result.error?.code ?? "?"}]`,
|
|
3191
|
+
result.error
|
|
3192
|
+
);
|
|
3193
|
+
}
|
|
3194
|
+
if (result.status === "cancelled") {
|
|
3195
|
+
throw new GenerateObjectError2(
|
|
3196
|
+
"no_tool_call",
|
|
3197
|
+
"Agent run was cancelled before an answer could be structured."
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
const answer = result.result;
|
|
3201
|
+
if (answer === void 0 || answer.length === 0) {
|
|
3202
|
+
throw new GenerateObjectError2(
|
|
3203
|
+
"no_tool_call",
|
|
3204
|
+
"The tool loop finished with no text answer (tool-only completion) \u2014 there is nothing to structure."
|
|
3205
|
+
);
|
|
3206
|
+
}
|
|
3207
|
+
return answer;
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3125
3210
|
// src/internal/runtime/cloud/cloud-agent.ts
|
|
3126
3211
|
init_errors();
|
|
3127
3212
|
init_cwd_mutex();
|
|
@@ -3272,8 +3357,19 @@ function safeFilenameForId(id, options) {
|
|
|
3272
3357
|
return `h-${createHash("sha256").update(id).digest("hex").slice(0, 16)}`;
|
|
3273
3358
|
}
|
|
3274
3359
|
|
|
3275
|
-
// src/internal/runtime/
|
|
3276
|
-
|
|
3360
|
+
// src/internal/runtime/model-selection.ts
|
|
3361
|
+
init_errors();
|
|
3362
|
+
function normalizeModel(m) {
|
|
3363
|
+
if (m === void 0 || typeof m !== "string") return m;
|
|
3364
|
+
const id = m.trim();
|
|
3365
|
+
if (id.length === 0) {
|
|
3366
|
+
throw new ConfigurationError(
|
|
3367
|
+
'model must be a non-empty "provider/model" id string or a ModelSelection object',
|
|
3368
|
+
{ code: "invalid_model_selection" }
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
return { id };
|
|
3372
|
+
}
|
|
3277
3373
|
|
|
3278
3374
|
// src/internal/runtime/registry/agent-registry-store.ts
|
|
3279
3375
|
init_cwd_mutex();
|
|
@@ -3350,7 +3446,10 @@ var REGISTRY_RELATIVE_PATH = join(".theokit", "agents", "registry.json");
|
|
|
3350
3446
|
function stripSecretsFromOptions(options) {
|
|
3351
3447
|
return assignDefined({
|
|
3352
3448
|
name: options.name,
|
|
3353
|
-
model:
|
|
3449
|
+
model: (() => {
|
|
3450
|
+
const m = normalizeModel(options.model);
|
|
3451
|
+
return m !== void 0 ? { id: m.id } : void 0;
|
|
3452
|
+
})(),
|
|
3354
3453
|
systemPrompt: typeof options.systemPrompt === "string" ? options.systemPrompt : void 0,
|
|
3355
3454
|
local: serializeLocal(options.local),
|
|
3356
3455
|
cloud: serializeCloud(options.cloud),
|
|
@@ -3635,7 +3734,8 @@ function serializeCloudAgentConfig(options) {
|
|
|
3635
3734
|
cloud: serializeCloud2(options.cloud)
|
|
3636
3735
|
};
|
|
3637
3736
|
if (typeof options.agentId === "string") payload.agentId = options.agentId;
|
|
3638
|
-
|
|
3737
|
+
const cfgModel = normalizeModel(options.model);
|
|
3738
|
+
if (cfgModel !== void 0) payload.model = { id: cfgModel.id };
|
|
3639
3739
|
if (typeof options.systemPrompt === "string") payload.systemPrompt = options.systemPrompt;
|
|
3640
3740
|
const skills = serializeSkills(options.skills);
|
|
3641
3741
|
if (skills !== void 0) payload.skills = skills;
|
|
@@ -4531,6 +4631,7 @@ function applyScriptMetrics(base, script) {
|
|
|
4531
4631
|
if (script.cost !== void 0) base.cost = script.cost;
|
|
4532
4632
|
if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
|
|
4533
4633
|
if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
|
|
4634
|
+
if (script.origin !== void 0) base.origin = script.origin;
|
|
4534
4635
|
}
|
|
4535
4636
|
|
|
4536
4637
|
// src/internal/runtime/cloud/cloud-run.ts
|
|
@@ -4886,7 +4987,7 @@ var CloudAgent = class {
|
|
|
4886
4987
|
disposed = false;
|
|
4887
4988
|
constructor(options, providedAgentId) {
|
|
4888
4989
|
this.agentId = providedAgentId ?? options.agentId ?? generateCloudAgentId();
|
|
4889
|
-
this.model = options.model;
|
|
4990
|
+
this.model = normalizeModel(options.model);
|
|
4890
4991
|
this.options = options;
|
|
4891
4992
|
this.cloudPayload = serializeCloudAgentConfig({ ...options, agentId: this.agentId });
|
|
4892
4993
|
const repoUrls = (options.cloud?.repos ?? []).map((repo) => repo.url);
|
|
@@ -4916,6 +5017,17 @@ var CloudAgent = class {
|
|
|
4916
5017
|
const apiKey = resolveApiKey(this.options.apiKey);
|
|
4917
5018
|
return isFixtureApiKey(apiKey) && getConfiguredBaseUrl() === void 0;
|
|
4918
5019
|
}
|
|
5020
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
5021
|
+
generate(message, options) {
|
|
5022
|
+
return agentGenerate(
|
|
5023
|
+
this,
|
|
5024
|
+
this.model,
|
|
5025
|
+
this.options.apiKey,
|
|
5026
|
+
this.options.local,
|
|
5027
|
+
message,
|
|
5028
|
+
options
|
|
5029
|
+
);
|
|
5030
|
+
}
|
|
4919
5031
|
async send(message, options = {}) {
|
|
4920
5032
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
4921
5033
|
throw new ConfigurationError(
|
|
@@ -4946,7 +5058,7 @@ var CloudAgent = class {
|
|
|
4946
5058
|
});
|
|
4947
5059
|
}
|
|
4948
5060
|
async sendLocked(message, options) {
|
|
4949
|
-
const overrideModel = options.model;
|
|
5061
|
+
const overrideModel = normalizeModel(options.model);
|
|
4950
5062
|
if (overrideModel !== void 0) {
|
|
4951
5063
|
this.model = overrideModel;
|
|
4952
5064
|
updateRegisteredAgent(this.agentId, { model: overrideModel });
|
|
@@ -5860,18 +5972,18 @@ var ALL_ADAPTERS = [
|
|
|
5860
5972
|
arizeAdapter,
|
|
5861
5973
|
braintrustAdapter
|
|
5862
5974
|
];
|
|
5863
|
-
var
|
|
5975
|
+
var registered2 = /* @__PURE__ */ new Set();
|
|
5864
5976
|
function tryAutoRegisterAdapters(settings) {
|
|
5865
5977
|
if (settings?.enabled !== true) return;
|
|
5866
5978
|
if (settings.autoDetect === false) return;
|
|
5867
5979
|
const disabled = new Set(settings.disable ?? []);
|
|
5868
5980
|
for (const adapter of ALL_ADAPTERS) {
|
|
5869
|
-
if (
|
|
5981
|
+
if (registered2.has(adapter.moduleName)) continue;
|
|
5870
5982
|
if (disabled.has(adapter.displayName.toLowerCase())) continue;
|
|
5871
5983
|
if (!adapter.detect()) continue;
|
|
5872
5984
|
try {
|
|
5873
5985
|
adapter.register();
|
|
5874
|
-
|
|
5986
|
+
registered2.add(adapter.moduleName);
|
|
5875
5987
|
process.stderr.write(`[theokit-sdk] telemetry: ${adapter.displayName} auto-instrumented.
|
|
5876
5988
|
`);
|
|
5877
5989
|
} catch (cause) {
|
|
@@ -6434,6 +6546,26 @@ function paginate(items, opts) {
|
|
|
6434
6546
|
return items.slice(start, end);
|
|
6435
6547
|
}
|
|
6436
6548
|
|
|
6549
|
+
// src/internal/persistence/session-meta.ts
|
|
6550
|
+
function applyMetaPatch(current, patch) {
|
|
6551
|
+
const next = {};
|
|
6552
|
+
if (current.title !== void 0) next.title = current.title;
|
|
6553
|
+
if (current.tag !== void 0) next.tag = current.tag;
|
|
6554
|
+
if (patch.title === null) delete next.title;
|
|
6555
|
+
else if (patch.title !== void 0) next.title = patch.title;
|
|
6556
|
+
if (patch.tag === null) delete next.tag;
|
|
6557
|
+
else if (patch.tag !== void 0) next.tag = patch.tag;
|
|
6558
|
+
return next;
|
|
6559
|
+
}
|
|
6560
|
+
function coerceSessionMeta(raw) {
|
|
6561
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
6562
|
+
const obj = raw;
|
|
6563
|
+
const meta = {};
|
|
6564
|
+
if (typeof obj.title === "string") meta.title = obj.title;
|
|
6565
|
+
if (typeof obj.tag === "string") meta.tag = obj.tag;
|
|
6566
|
+
return meta.title === void 0 && meta.tag === void 0 ? void 0 : meta;
|
|
6567
|
+
}
|
|
6568
|
+
|
|
6437
6569
|
// src/internal/persistence/conversation-storage-fs.ts
|
|
6438
6570
|
var FileSystemConversationStorage = class {
|
|
6439
6571
|
#root;
|
|
@@ -6484,6 +6616,37 @@ var FileSystemConversationStorage = class {
|
|
|
6484
6616
|
async compact(conversationId, maxTurns) {
|
|
6485
6617
|
await compactSessionFile(this.#root, conversationId, maxTurns);
|
|
6486
6618
|
}
|
|
6619
|
+
// SE4 — session metadata persisted as a per-conversation sidecar
|
|
6620
|
+
// `<root>/.theokit/agents/<safeId>/session.json` (same sanitized perimeter as
|
|
6621
|
+
// the transcript). Kept separate from messages.jsonl so a title/tag write does
|
|
6622
|
+
// not rewrite the append-only log.
|
|
6623
|
+
#metaPath(conversationId) {
|
|
6624
|
+
const safe3 = sanitizeIdentifier(conversationId, { maxLen: 128 });
|
|
6625
|
+
return safePathJoin(this.#root, ".theokit", "agents", safe3, "session.json");
|
|
6626
|
+
}
|
|
6627
|
+
async getSessionMeta(conversationId) {
|
|
6628
|
+
try {
|
|
6629
|
+
const raw = await readFile(this.#metaPath(conversationId), "utf8");
|
|
6630
|
+
return coerceSessionMeta(JSON.parse(raw));
|
|
6631
|
+
} catch (cause) {
|
|
6632
|
+
if (cause.code === "ENOENT") return void 0;
|
|
6633
|
+
throw cause;
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
async setSessionMeta(conversationId, patch) {
|
|
6637
|
+
const metaPath = this.#metaPath(conversationId);
|
|
6638
|
+
await mkdir(dirname(metaPath), { recursive: true });
|
|
6639
|
+
await withFileLock(metaPath, async () => {
|
|
6640
|
+
let current = {};
|
|
6641
|
+
try {
|
|
6642
|
+
current = coerceSessionMeta(JSON.parse(await readFile(metaPath, "utf8"))) ?? {};
|
|
6643
|
+
} catch (cause) {
|
|
6644
|
+
if (cause.code !== "ENOENT") throw cause;
|
|
6645
|
+
}
|
|
6646
|
+
const next = applyMetaPatch(current, patch);
|
|
6647
|
+
await writeFile(metaPath, redactSecrets(JSON.stringify(next)), "utf8");
|
|
6648
|
+
});
|
|
6649
|
+
}
|
|
6487
6650
|
async dispose() {
|
|
6488
6651
|
}
|
|
6489
6652
|
};
|
|
@@ -8333,23 +8496,27 @@ function tryParseSkill(raw, fallbackName, source, options) {
|
|
|
8333
8496
|
|
|
8334
8497
|
// src/internal/runtime/skills/skills-manager.ts
|
|
8335
8498
|
var SkillsManager = class {
|
|
8336
|
-
constructor(cwd, _enabled, settingSourcesIncludeProject) {
|
|
8499
|
+
constructor(cwd, _enabled, settingSourcesIncludeProject, skillsDir, inline) {
|
|
8337
8500
|
this.cwd = cwd;
|
|
8338
8501
|
this.settingSourcesIncludeProject = settingSourcesIncludeProject;
|
|
8502
|
+
this.skillsDir = skillsDir;
|
|
8503
|
+
this.inline = inline;
|
|
8339
8504
|
}
|
|
8340
8505
|
cwd;
|
|
8341
8506
|
settingSourcesIncludeProject;
|
|
8507
|
+
skillsDir;
|
|
8508
|
+
inline;
|
|
8342
8509
|
skills = [];
|
|
8343
8510
|
async initialize() {
|
|
8344
8511
|
if (!this.settingSourcesIncludeProject) {
|
|
8345
|
-
this.skills = [];
|
|
8512
|
+
this.skills = this.mergeInline([]);
|
|
8346
8513
|
return;
|
|
8347
8514
|
}
|
|
8348
8515
|
await this.refresh();
|
|
8349
8516
|
}
|
|
8350
8517
|
async refresh() {
|
|
8351
|
-
const skillsRoot = join(this.cwd, ".theokit", "skills");
|
|
8352
|
-
|
|
8518
|
+
const skillsRoot = this.skillsDir ?? join(this.cwd, ".theokit", "skills");
|
|
8519
|
+
const discovered = await discoverSkills(skillsRoot, {
|
|
8353
8520
|
onInvalidSkill: (info) => {
|
|
8354
8521
|
process.stderr.write(
|
|
8355
8522
|
`[theokit-sdk] skill ${info.name} skipped (${info.code}): ${info.message}
|
|
@@ -8357,6 +8524,13 @@ var SkillsManager = class {
|
|
|
8357
8524
|
);
|
|
8358
8525
|
}
|
|
8359
8526
|
});
|
|
8527
|
+
this.skills = this.mergeInline(discovered);
|
|
8528
|
+
}
|
|
8529
|
+
/** M22 — merge inline skills over discovered ones; inline wins on a name conflict. */
|
|
8530
|
+
mergeInline(discovered) {
|
|
8531
|
+
if (this.inline === void 0 || this.inline.length === 0) return discovered;
|
|
8532
|
+
const inlineNames = new Set(this.inline.map((s) => s.name));
|
|
8533
|
+
return [...discovered.filter((s) => !inlineNames.has(s.name)), ...this.inline];
|
|
8360
8534
|
}
|
|
8361
8535
|
list() {
|
|
8362
8536
|
return Promise.resolve(this.skills);
|
|
@@ -8392,7 +8566,7 @@ function bootstrapSubmanagers(args) {
|
|
|
8392
8566
|
const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
|
|
8393
8567
|
if (providerCount > 0 || args.options.providers !== void 0) {
|
|
8394
8568
|
out.providers = new ProvidersManagerImpl(
|
|
8395
|
-
args.options.model,
|
|
8569
|
+
normalizeModel(args.options.model),
|
|
8396
8570
|
args.options.providers,
|
|
8397
8571
|
args.options.plugins
|
|
8398
8572
|
);
|
|
@@ -8401,7 +8575,10 @@ function bootstrapSubmanagers(args) {
|
|
|
8401
8575
|
out.skillsManager = new SkillsManager(
|
|
8402
8576
|
args.workspaceCwd,
|
|
8403
8577
|
args.options.skills?.enabled,
|
|
8404
|
-
args.settingSourcesIncludeProject
|
|
8578
|
+
args.settingSourcesIncludeProject,
|
|
8579
|
+
// M22 — custom skills directory + inline (code-defined) skills.
|
|
8580
|
+
args.options.skills?.skillsDir,
|
|
8581
|
+
args.options.skills?.inline
|
|
8405
8582
|
);
|
|
8406
8583
|
const localSkills = out.skillsManager;
|
|
8407
8584
|
out.skills = { list: () => localSkills.list() };
|
|
@@ -8459,6 +8636,7 @@ function createLocalRun(options) {
|
|
|
8459
8636
|
projectMcpServers: options.projectMcpServers,
|
|
8460
8637
|
...options.persistMemoryFact !== void 0 ? { persistMemoryFact: options.persistMemoryFact } : {}
|
|
8461
8638
|
});
|
|
8639
|
+
if (options.sendOptions.origin !== void 0) script.origin = options.sendOptions.origin;
|
|
8462
8640
|
const handle = new LocalRun({
|
|
8463
8641
|
id,
|
|
8464
8642
|
agentId: options.agentId,
|
|
@@ -9107,6 +9285,15 @@ async function emitReasoningDeltaCallback(inputs, text) {
|
|
|
9107
9285
|
);
|
|
9108
9286
|
}
|
|
9109
9287
|
|
|
9288
|
+
// src/types/run-events.ts
|
|
9289
|
+
function emitRunEvent(sink, event) {
|
|
9290
|
+
if (sink === void 0) return;
|
|
9291
|
+
try {
|
|
9292
|
+
sink(event);
|
|
9293
|
+
} catch {
|
|
9294
|
+
}
|
|
9295
|
+
}
|
|
9296
|
+
|
|
9110
9297
|
// src/internal/agent-loop/tool-dispatch.ts
|
|
9111
9298
|
init_async_local_storage();
|
|
9112
9299
|
|
|
@@ -9204,6 +9391,22 @@ function coerceArgsToSchema(args, schema) {
|
|
|
9204
9391
|
return { value: out, changed };
|
|
9205
9392
|
}
|
|
9206
9393
|
|
|
9394
|
+
// src/tool-error.ts
|
|
9395
|
+
init_errors();
|
|
9396
|
+
var ToolError = class extends TheokitAgentError {
|
|
9397
|
+
name = "ToolError";
|
|
9398
|
+
/** The error content surfaced to the model: a string, or text/image blocks. */
|
|
9399
|
+
content;
|
|
9400
|
+
constructor(content, options = {}) {
|
|
9401
|
+
super(renderToolErrorMessage(content), { ...options, isRetryable: false });
|
|
9402
|
+
this.content = content;
|
|
9403
|
+
}
|
|
9404
|
+
};
|
|
9405
|
+
function renderToolErrorMessage(content) {
|
|
9406
|
+
if (typeof content === "string") return content;
|
|
9407
|
+
return content.map((block) => block.type === "text" ? block.text : `[${block.source.media_type} image]`).join("\n");
|
|
9408
|
+
}
|
|
9409
|
+
|
|
9207
9410
|
// src/internal/runtime/tools/shell-tool.ts
|
|
9208
9411
|
async function runShell(options) {
|
|
9209
9412
|
if (options.sandbox === true && isObviouslyUnsafe(options.command)) {
|
|
@@ -9257,9 +9460,13 @@ async function runHandlerTool(kind, handler, call, signal, context) {
|
|
|
9257
9460
|
return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
|
|
9258
9461
|
}
|
|
9259
9462
|
try {
|
|
9260
|
-
const
|
|
9261
|
-
return { stdout, stderr: "", exitCode: 0 };
|
|
9463
|
+
const out = await handler(call.input, { signal, context });
|
|
9464
|
+
if (typeof out !== "string") return { stdout: "", stderr: "", exitCode: 0, content: out };
|
|
9465
|
+
return { stdout: out, stderr: "", exitCode: 0 };
|
|
9262
9466
|
} catch (cause) {
|
|
9467
|
+
if (cause instanceof ToolError) {
|
|
9468
|
+
return { stdout: "", stderr: cause.message, exitCode: 1, content: cause.content };
|
|
9469
|
+
}
|
|
9263
9470
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
9264
9471
|
return { stdout: "", stderr: message, exitCode: 1 };
|
|
9265
9472
|
}
|
|
@@ -9378,6 +9585,11 @@ async function dispatchSingleCall(inputs, tools, call, events, parentSpan) {
|
|
|
9378
9585
|
toolSpan?.end();
|
|
9379
9586
|
return fileVeto;
|
|
9380
9587
|
}
|
|
9588
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9589
|
+
type: "tool_progress",
|
|
9590
|
+
toolName: workingCall.name,
|
|
9591
|
+
toolCallId: callId
|
|
9592
|
+
});
|
|
9381
9593
|
const result = await runToolWithLifecycle(inputs, resolved, workingCall, callId);
|
|
9382
9594
|
await inputs.pluginManager?.runPostToolCallHooks({
|
|
9383
9595
|
name: workingCall.name,
|
|
@@ -9404,6 +9616,13 @@ function applyRepairAndExtractCall(tools, call) {
|
|
|
9404
9616
|
function vetoFromForkWhitelist(inputs, call, callId, events) {
|
|
9405
9617
|
const whitelistDecision = checkToolWhitelist(call.name);
|
|
9406
9618
|
if (whitelistDecision.allowed) return void 0;
|
|
9619
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9620
|
+
type: "permission_denied",
|
|
9621
|
+
toolName: call.name,
|
|
9622
|
+
toolCallId: callId,
|
|
9623
|
+
source: "fork_whitelist",
|
|
9624
|
+
message: whitelistDecision.reason ?? "tool not available in fork"
|
|
9625
|
+
});
|
|
9407
9626
|
events.push(buildToolUseRunning(inputs, callId, call));
|
|
9408
9627
|
events.push(
|
|
9409
9628
|
buildToolUseCompleted(inputs, callId, call, {
|
|
@@ -9440,6 +9659,13 @@ async function vetoFromPluginPreHook(inputs, call, callId, events) {
|
|
|
9440
9659
|
runId: inputs.runId
|
|
9441
9660
|
});
|
|
9442
9661
|
if (pluginVeto === void 0) return void 0;
|
|
9662
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9663
|
+
type: "permission_denied",
|
|
9664
|
+
toolName: call.name,
|
|
9665
|
+
toolCallId: callId,
|
|
9666
|
+
source: "plugin",
|
|
9667
|
+
message: pluginVeto.message
|
|
9668
|
+
});
|
|
9443
9669
|
events.push(
|
|
9444
9670
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9445
9671
|
stdout: "",
|
|
@@ -9462,6 +9688,13 @@ async function vetoFromFileHookPreDecision(inputs, call, callId, events) {
|
|
|
9462
9688
|
runId: inputs.runId
|
|
9463
9689
|
});
|
|
9464
9690
|
if (!preDecision.blocked) return void 0;
|
|
9691
|
+
emitRunEvent(inputs.runEventSink, {
|
|
9692
|
+
type: "permission_denied",
|
|
9693
|
+
toolName: call.name,
|
|
9694
|
+
toolCallId: callId,
|
|
9695
|
+
source: "file_hook",
|
|
9696
|
+
message: preDecision.reason ?? "blocked by hook"
|
|
9697
|
+
});
|
|
9465
9698
|
events.push(
|
|
9466
9699
|
buildToolUseCompleted(inputs, callId, call, {
|
|
9467
9700
|
stdout: "",
|
|
@@ -9505,7 +9738,9 @@ async function runToolWithLifecycle(inputs, resolved, call, callId) {
|
|
|
9505
9738
|
await safeEmitToolHook(inputs.onToolEnd, {
|
|
9506
9739
|
toolName: call.name,
|
|
9507
9740
|
args: call.input,
|
|
9508
|
-
|
|
9741
|
+
// SE7 — a block-returning handler has empty `stdout`; surface its structured
|
|
9742
|
+
// content to the hook instead of an empty string.
|
|
9743
|
+
result: result.content !== void 0 ? result.content : result.stdout,
|
|
9509
9744
|
conversationId: inputs.agentId,
|
|
9510
9745
|
callId,
|
|
9511
9746
|
durationMs
|
|
@@ -9527,7 +9762,10 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9527
9762
|
output: {
|
|
9528
9763
|
stdout: result.stdout,
|
|
9529
9764
|
stderr: result.stderr,
|
|
9530
|
-
exitCode: result.exitCode ?? 0
|
|
9765
|
+
exitCode: result.exitCode ?? 0,
|
|
9766
|
+
// SE7 — structured content (text + image blocks) when the handler
|
|
9767
|
+
// returned/threw blocks; absent for the string path.
|
|
9768
|
+
...result.content !== void 0 ? { content: result.content } : {}
|
|
9531
9769
|
},
|
|
9532
9770
|
agentId: inputs.agentId,
|
|
9533
9771
|
runId: inputs.runId
|
|
@@ -9540,7 +9778,9 @@ function finalizeSpanAndPostHook(inputs, call, callId, result, events, toolSpan)
|
|
|
9540
9778
|
return {
|
|
9541
9779
|
type: "tool_result",
|
|
9542
9780
|
toolUseId: call.id,
|
|
9543
|
-
content
|
|
9781
|
+
// SE7 — structured content blocks (handler-returned or ToolError-carried)
|
|
9782
|
+
// are authoritative; otherwise the legacy string rendering.
|
|
9783
|
+
content: result.content !== void 0 ? result.content : renderToolResult(result),
|
|
9544
9784
|
...result.exitCode !== 0 && result.exitCode !== void 0 ? { isError: true } : {}
|
|
9545
9785
|
};
|
|
9546
9786
|
}
|
|
@@ -9589,6 +9829,29 @@ function buildToolUseCompleted(inputs, callId, call, result) {
|
|
|
9589
9829
|
};
|
|
9590
9830
|
}
|
|
9591
9831
|
|
|
9832
|
+
// src/internal/llm/tool-result-content.ts
|
|
9833
|
+
init_errors();
|
|
9834
|
+
function toBlockToolResultContent(content) {
|
|
9835
|
+
return content;
|
|
9836
|
+
}
|
|
9837
|
+
function toStringToolResultContent(content, providerName) {
|
|
9838
|
+
if (typeof content === "string") return content;
|
|
9839
|
+
if (content.some((block) => block.type === "image")) {
|
|
9840
|
+
throw new ConfigurationError(
|
|
9841
|
+
`provider "${providerName}" does not support image content in tool results`
|
|
9842
|
+
);
|
|
9843
|
+
}
|
|
9844
|
+
return content.filter(
|
|
9845
|
+
(block) => block.type === "text"
|
|
9846
|
+
).map((block) => block.text).join("\n");
|
|
9847
|
+
}
|
|
9848
|
+
function renderToolResultContentText(content, fn) {
|
|
9849
|
+
if (typeof content === "string") return fn(content);
|
|
9850
|
+
return content.map(
|
|
9851
|
+
(block) => block.type === "text" ? { type: "text", text: fn(block.text) } : block
|
|
9852
|
+
);
|
|
9853
|
+
}
|
|
9854
|
+
|
|
9592
9855
|
// src/internal/agent-loop/tool-result-guard.ts
|
|
9593
9856
|
var OPEN = "<untrusted-tool-output>";
|
|
9594
9857
|
var CLOSE = "</untrusted-tool-output>";
|
|
@@ -9614,7 +9877,11 @@ ${CLOSE}`;
|
|
|
9614
9877
|
function applyToolResultGuard(parts, opts) {
|
|
9615
9878
|
if (opts.delimit !== true && opts.redactPii !== true) return parts;
|
|
9616
9879
|
return parts.map(
|
|
9617
|
-
(p) =>
|
|
9880
|
+
(p) => (
|
|
9881
|
+
// SE7 — guard the TEXT of a tool result (string or the text blocks of a
|
|
9882
|
+
// structured content); image blocks pass through untouched.
|
|
9883
|
+
p.type === "tool_result" ? { ...p, content: renderToolResultContentText(p.content, (t) => guardText(t, opts)) } : p
|
|
9884
|
+
)
|
|
9618
9885
|
);
|
|
9619
9886
|
}
|
|
9620
9887
|
|
|
@@ -10531,10 +10798,10 @@ function stripVertexPrefix(modelId) {
|
|
|
10531
10798
|
}
|
|
10532
10799
|
|
|
10533
10800
|
// src/internal/providers/builtin/index.ts
|
|
10534
|
-
var
|
|
10801
|
+
var registered3 = false;
|
|
10535
10802
|
function registerBuiltins() {
|
|
10536
|
-
if (
|
|
10537
|
-
|
|
10803
|
+
if (registered3) return;
|
|
10804
|
+
registered3 = true;
|
|
10538
10805
|
registerProvider(ANTHROPIC);
|
|
10539
10806
|
registerProvider(OPENAI);
|
|
10540
10807
|
registerProvider(OPENROUTER);
|
|
@@ -10762,7 +11029,9 @@ function toAnthropicWireMessage(message) {
|
|
|
10762
11029
|
return {
|
|
10763
11030
|
type: "tool_result",
|
|
10764
11031
|
tool_use_id: part.toolUseId,
|
|
10765
|
-
|
|
11032
|
+
// SE7 — this wire is block-capable: strings pass through, structured
|
|
11033
|
+
// text/image blocks are forwarded natively.
|
|
11034
|
+
content: toBlockToolResultContent(part.content),
|
|
10766
11035
|
...part.isError === true ? { is_error: true } : {}
|
|
10767
11036
|
};
|
|
10768
11037
|
});
|
|
@@ -11554,7 +11823,8 @@ function toOllamaMessages(message) {
|
|
|
11554
11823
|
if (part.type === "tool_result") {
|
|
11555
11824
|
out.push({
|
|
11556
11825
|
role: "tool",
|
|
11557
|
-
|
|
11826
|
+
// SE7 — string-only tool role: text blocks flatten; image fails fast.
|
|
11827
|
+
content: toStringToolResultContent(part.content, "ollama"),
|
|
11558
11828
|
tool_name: part.toolUseId
|
|
11559
11829
|
});
|
|
11560
11830
|
}
|
|
@@ -12091,7 +12361,9 @@ function userOrToolMessages(message) {
|
|
|
12091
12361
|
out.push({
|
|
12092
12362
|
role: "tool",
|
|
12093
12363
|
tool_call_id: part.toolUseId,
|
|
12094
|
-
|
|
12364
|
+
// SE7 — this wire's tool role is string-only: text blocks flatten; an
|
|
12365
|
+
// image block fails fast (ConfigurationError).
|
|
12366
|
+
content: toStringToolResultContent(part.content, "openai")
|
|
12095
12367
|
});
|
|
12096
12368
|
}
|
|
12097
12369
|
}
|
|
@@ -13020,18 +13292,20 @@ function levenshtein(a, b) {
|
|
|
13020
13292
|
function createRealLocalRun(options) {
|
|
13021
13293
|
const { userText, id, startTime } = prepareRunContext(options.message);
|
|
13022
13294
|
const supported = /* @__PURE__ */ new Set(["stream", "wait", "cancel", "conversation"]);
|
|
13023
|
-
const
|
|
13295
|
+
const runScript = {
|
|
13024
13296
|
events: [],
|
|
13025
13297
|
finalStatus: "running",
|
|
13026
13298
|
cancellable: false,
|
|
13027
|
-
conversation: []
|
|
13299
|
+
conversation: [],
|
|
13300
|
+
// SE3 — carry the turn's provenance so buildResult forwards it onto RunResult.origin.
|
|
13301
|
+
...options.sendOptions.origin !== void 0 ? { origin: options.sendOptions.origin } : {}
|
|
13028
13302
|
};
|
|
13029
13303
|
const handle = new RealLocalRun(
|
|
13030
13304
|
{
|
|
13031
13305
|
id,
|
|
13032
13306
|
agentId: options.agentId,
|
|
13033
13307
|
model: options.model,
|
|
13034
|
-
script:
|
|
13308
|
+
script: runScript,
|
|
13035
13309
|
supportedOps: supported,
|
|
13036
13310
|
startTime
|
|
13037
13311
|
},
|
|
@@ -13143,6 +13417,8 @@ function buildLoopInputs(options, runId, userText) {
|
|
|
13143
13417
|
// M7 — forward SendOptions.context to the loop so every tool handler receives
|
|
13144
13418
|
// it on `ctx.context` (shared run config set once, e.g. projectRoot).
|
|
13145
13419
|
...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
|
|
13420
|
+
// SE2 — forward the opt-in typed runtime-event sink to the loop.
|
|
13421
|
+
...options.sendOptions.onRunEvent !== void 0 ? { runEventSink: options.sendOptions.onRunEvent } : {},
|
|
13146
13422
|
// #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
|
|
13147
13423
|
// can enable them via SendOptions (not only internal AgentLoopInputs).
|
|
13148
13424
|
...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},
|
|
@@ -15835,7 +16111,7 @@ function wrapRunWithPostReplyHook(args) {
|
|
|
15835
16111
|
async function executeSendLocked(inputs, message, options) {
|
|
15836
16112
|
if (inputs.disposed) throw new AgentDisposedError(inputs.agentId);
|
|
15837
16113
|
await consumePending(inputs.agentId, inputs.invalidationPending, inputs.clearInvalidation, inputs.reload);
|
|
15838
|
-
inputs.applyModelOverride(options.model);
|
|
16114
|
+
inputs.applyModelOverride(normalizeModel(options.model));
|
|
15839
16115
|
const userText = typeof message === "string" ? message : message.text;
|
|
15840
16116
|
if (inputs.options.onBeforeSend !== void 0) {
|
|
15841
16117
|
await inputs.options.onBeforeSend({
|
|
@@ -15987,7 +16263,7 @@ var LocalAgent = class {
|
|
|
15987
16263
|
constructor(options) {
|
|
15988
16264
|
this.agentId = options.agentId ?? generateLocalAgentId();
|
|
15989
16265
|
this._telemetry = createTelemetry(options.telemetry);
|
|
15990
|
-
this.model = options.model;
|
|
16266
|
+
this.model = normalizeModel(options.model);
|
|
15991
16267
|
this.options = options;
|
|
15992
16268
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
15993
16269
|
this.conversationStorage = options.conversationStorage;
|
|
@@ -16054,6 +16330,11 @@ var LocalAgent = class {
|
|
|
16054
16330
|
hooks() {
|
|
16055
16331
|
return this.hooksExecutor;
|
|
16056
16332
|
}
|
|
16333
|
+
// SE9 — integrated structured output; delegates to the shared helper.
|
|
16334
|
+
generate(message, options) {
|
|
16335
|
+
const { apiKey, local } = this.options;
|
|
16336
|
+
return agentGenerate(this, this.model, apiKey, local, message, options);
|
|
16337
|
+
}
|
|
16057
16338
|
async send(message, options = {}) {
|
|
16058
16339
|
if (options.tools !== void 0 && options.tools.length > 0) {
|
|
16059
16340
|
validateToolCatalog(options.tools);
|
|
@@ -16293,6 +16574,7 @@ function includesSetting(options, source) {
|
|
|
16293
16574
|
|
|
16294
16575
|
// src/agent-helpers.ts
|
|
16295
16576
|
async function runCreateUnderSpan(options, span) {
|
|
16577
|
+
options = { ...options, model: normalizeModel(options.model) };
|
|
16296
16578
|
validateAgentOptions(options);
|
|
16297
16579
|
validateCloudToolParity(options);
|
|
16298
16580
|
await guardAgainstIdCollision(options);
|
|
@@ -16366,7 +16648,10 @@ async function createLocalAgent(options) {
|
|
|
16366
16648
|
const willFlowToProvider = !isFixtureApiKey(apiKey) && !shouldUseRealLocalRuntime(apiKey);
|
|
16367
16649
|
const shape = validateApiKeyShape(apiKey, {
|
|
16368
16650
|
strict: willFlowToProvider,
|
|
16369
|
-
|
|
16651
|
+
// `options.model` is already normalized by `runCreateUnderSpan`; `normalizeModel`
|
|
16652
|
+
// here is the idempotent narrowing of the widened public type (`{id}` passes
|
|
16653
|
+
// through by reference) — cleaner than an `as` cast.
|
|
16654
|
+
...willFlowToProvider ? { provider: providerFromModelId(normalizeModel(options.model)?.id) } : {}
|
|
16370
16655
|
});
|
|
16371
16656
|
if (shape.malformed) {
|
|
16372
16657
|
throw new AuthenticationError(shape.message, { code: "malformed_api_key" });
|
|
@@ -16432,6 +16717,10 @@ async function rehydrateExistingAgent(agentId, existing, options) {
|
|
|
16432
16717
|
...existing.options,
|
|
16433
16718
|
...options,
|
|
16434
16719
|
...mergedLocal !== void 0 ? { local: mergedLocal } : {},
|
|
16720
|
+
// SE8 — normalize a caller-supplied bare-string model override at this resume
|
|
16721
|
+
// boundary (Agent.resume never flows through runCreateUnderSpan). Cloud resume
|
|
16722
|
+
// honors it; local resume forces the persisted model below.
|
|
16723
|
+
model: normalizeModel(options.model ?? existing.options.model),
|
|
16435
16724
|
mcpServers: void 0,
|
|
16436
16725
|
agentId
|
|
16437
16726
|
};
|
|
@@ -16798,6 +17087,7 @@ async function getOrCreateUncached(agentId, options) {
|
|
|
16798
17087
|
}
|
|
16799
17088
|
setAgentFacade({
|
|
16800
17089
|
create: (options) => Agent.create(options),
|
|
17090
|
+
delete: (agentId) => Agent.delete(agentId),
|
|
16801
17091
|
prompt: (message, options) => Agent.prompt(message, options),
|
|
16802
17092
|
get: (agentId) => Agent.get(agentId),
|
|
16803
17093
|
resume: (agentId, options) => Agent.resume(agentId, options),
|