@prompty/core 2.0.0-alpha.4 → 2.0.0-alpha.6
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/dist/index.cjs +593 -259
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +288 -9
- package/dist/index.d.ts +288 -9
- package/dist/index.js +576 -256
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -4499,6 +4499,9 @@ var init_common = __esm({
|
|
|
4499
4499
|
|
|
4500
4500
|
// src/core/tool-dispatch.ts
|
|
4501
4501
|
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
4502
|
+
function registerTool(name, handler) {
|
|
4503
|
+
nameRegistry.set(name, handler);
|
|
4504
|
+
}
|
|
4502
4505
|
function getTool(name) {
|
|
4503
4506
|
return nameRegistry.get(name);
|
|
4504
4507
|
}
|
|
@@ -4522,12 +4525,12 @@ async function dispatchTool(toolName, args, userTools, agent, parentInputs) {
|
|
|
4522
4525
|
const result = await registeredFn(args);
|
|
4523
4526
|
return typeof result === "string" ? result : JSON.stringify(result);
|
|
4524
4527
|
}
|
|
4525
|
-
const
|
|
4526
|
-
if (!
|
|
4528
|
+
const tool2 = agent.tools?.find((t) => t.name === toolName);
|
|
4529
|
+
if (!tool2) {
|
|
4527
4530
|
const available = Object.keys(userTools).sort().join(", ") || "(none)";
|
|
4528
4531
|
return `Error: tool "${toolName}" not found in userTools or agent.tools. Available user tools: ${available}`;
|
|
4529
4532
|
}
|
|
4530
|
-
const kind =
|
|
4533
|
+
const kind = tool2.kind || "*";
|
|
4531
4534
|
let handler;
|
|
4532
4535
|
try {
|
|
4533
4536
|
handler = getToolHandler(kind);
|
|
@@ -4539,7 +4542,7 @@ async function dispatchTool(toolName, args, userTools, agent, parentInputs) {
|
|
|
4539
4542
|
}
|
|
4540
4543
|
}
|
|
4541
4544
|
return await handler.executeTool(
|
|
4542
|
-
|
|
4545
|
+
tool2,
|
|
4543
4546
|
args,
|
|
4544
4547
|
agent,
|
|
4545
4548
|
parentInputs
|
|
@@ -4564,36 +4567,36 @@ var init_tool_dispatch = __esm({
|
|
|
4564
4567
|
nameRegistry = /* @__PURE__ */ new Map();
|
|
4565
4568
|
toolHandlers = /* @__PURE__ */ new Map();
|
|
4566
4569
|
FunctionToolHandler = class {
|
|
4567
|
-
async executeTool(
|
|
4568
|
-
const name =
|
|
4570
|
+
async executeTool(tool2, _args, _agent, _parentInputs) {
|
|
4571
|
+
const name = tool2.name ?? "unknown";
|
|
4569
4572
|
throw new Error(
|
|
4570
|
-
`Function tool '${name}' declared but no callable provided. Pass it via tools: { '${name}': fn } in
|
|
4573
|
+
`Function tool '${name}' declared but no callable provided. Pass it via tools: { '${name}': fn } in invokeAgent().`
|
|
4571
4574
|
);
|
|
4572
4575
|
}
|
|
4573
4576
|
};
|
|
4574
4577
|
PromptyToolHandler = class {
|
|
4575
|
-
async executeTool(
|
|
4578
|
+
async executeTool(tool2, args, agent, _parentInputs) {
|
|
4576
4579
|
const { load: load2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
4577
|
-
const { prepare: prepare2, run: run2,
|
|
4580
|
+
const { prepare: prepare2, run: run2, invokeAgent: invokeAgent2 } = await Promise.resolve().then(() => (init_pipeline(), pipeline_exports));
|
|
4578
4581
|
const parentPath = (agent.metadata ?? {}).__source_path;
|
|
4579
4582
|
if (!parentPath) {
|
|
4580
|
-
return `Error: cannot resolve PromptyTool '${
|
|
4583
|
+
return `Error: cannot resolve PromptyTool '${tool2.name}': parent has no __source_path`;
|
|
4581
4584
|
}
|
|
4582
|
-
const childPath = resolve2(dirname2(parentPath),
|
|
4585
|
+
const childPath = resolve2(dirname2(parentPath), tool2.path);
|
|
4583
4586
|
const stack = (agent.metadata ?? {}).__prompty_tool_stack ?? [];
|
|
4584
4587
|
const normalizedChild = resolve2(childPath);
|
|
4585
4588
|
const visited = /* @__PURE__ */ new Set([...stack.map((p) => resolve2(p)), resolve2(parentPath)]);
|
|
4586
4589
|
if (visited.has(normalizedChild)) {
|
|
4587
4590
|
const chain = [...stack, parentPath, childPath].join(" \u2192 ");
|
|
4588
|
-
return `Error executing PromptyTool '${
|
|
4591
|
+
return `Error executing PromptyTool '${tool2.name}': circular reference detected: ${chain}`;
|
|
4589
4592
|
}
|
|
4590
4593
|
try {
|
|
4591
4594
|
const child = load2(childPath);
|
|
4592
4595
|
if (!child.metadata) child.metadata = {};
|
|
4593
4596
|
child.metadata.__prompty_tool_stack = [...stack, parentPath];
|
|
4594
|
-
const mode =
|
|
4597
|
+
const mode = tool2.mode ?? "single";
|
|
4595
4598
|
if (mode === "agentic") {
|
|
4596
|
-
const result = await
|
|
4599
|
+
const result = await invokeAgent2(child, args);
|
|
4597
4600
|
return typeof result === "string" ? result : JSON.stringify(result);
|
|
4598
4601
|
} else {
|
|
4599
4602
|
const messages = await prepare2(child, args);
|
|
@@ -4601,7 +4604,7 @@ var init_tool_dispatch = __esm({
|
|
|
4601
4604
|
return typeof result === "string" ? result : JSON.stringify(result);
|
|
4602
4605
|
}
|
|
4603
4606
|
} catch (err) {
|
|
4604
|
-
return `Error executing PromptyTool '${
|
|
4607
|
+
return `Error executing PromptyTool '${tool2.name}': ${err instanceof Error ? err.message : String(err)}`;
|
|
4605
4608
|
}
|
|
4606
4609
|
}
|
|
4607
4610
|
};
|
|
@@ -4628,18 +4631,216 @@ var init_tool_dispatch = __esm({
|
|
|
4628
4631
|
}
|
|
4629
4632
|
});
|
|
4630
4633
|
|
|
4634
|
+
// src/core/agent-events.ts
|
|
4635
|
+
function emitEvent(callback, eventType, data) {
|
|
4636
|
+
if (!callback) return;
|
|
4637
|
+
try {
|
|
4638
|
+
callback(eventType, data);
|
|
4639
|
+
} catch (err) {
|
|
4640
|
+
if (typeof globalThis.console?.debug === "function") {
|
|
4641
|
+
globalThis.console.debug(`Event callback error for ${eventType}:`, err);
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
}
|
|
4645
|
+
var init_agent_events = __esm({
|
|
4646
|
+
"src/core/agent-events.ts"() {
|
|
4647
|
+
"use strict";
|
|
4648
|
+
}
|
|
4649
|
+
});
|
|
4650
|
+
|
|
4651
|
+
// src/core/cancellation.ts
|
|
4652
|
+
function checkCancellation(signal) {
|
|
4653
|
+
if (signal?.aborted) {
|
|
4654
|
+
throw new CancelledError();
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
var CancelledError;
|
|
4658
|
+
var init_cancellation = __esm({
|
|
4659
|
+
"src/core/cancellation.ts"() {
|
|
4660
|
+
"use strict";
|
|
4661
|
+
CancelledError = class extends Error {
|
|
4662
|
+
constructor(message = "Agent loop cancelled") {
|
|
4663
|
+
super(message);
|
|
4664
|
+
this.name = "CancelledError";
|
|
4665
|
+
}
|
|
4666
|
+
};
|
|
4667
|
+
}
|
|
4668
|
+
});
|
|
4669
|
+
|
|
4670
|
+
// src/core/context.ts
|
|
4671
|
+
function estimateChars(messages) {
|
|
4672
|
+
let total = 0;
|
|
4673
|
+
for (const msg of messages) {
|
|
4674
|
+
total += msg.role.length + 4;
|
|
4675
|
+
for (const part of msg.parts) {
|
|
4676
|
+
if (part.kind === "text") {
|
|
4677
|
+
total += part.value.length;
|
|
4678
|
+
} else {
|
|
4679
|
+
total += 200;
|
|
4680
|
+
}
|
|
4681
|
+
}
|
|
4682
|
+
const toolCalls = msg.metadata?.tool_calls;
|
|
4683
|
+
if (toolCalls) {
|
|
4684
|
+
total += JSON.stringify(toolCalls).length;
|
|
4685
|
+
}
|
|
4686
|
+
}
|
|
4687
|
+
return total;
|
|
4688
|
+
}
|
|
4689
|
+
function truncate(text2, maxLen = 200) {
|
|
4690
|
+
return text2.length <= maxLen ? text2 : text2.slice(0, maxLen) + "\u2026";
|
|
4691
|
+
}
|
|
4692
|
+
function summarizeDropped(messages) {
|
|
4693
|
+
const lines = [];
|
|
4694
|
+
for (const msg of messages) {
|
|
4695
|
+
const msgText = msg.text.trim();
|
|
4696
|
+
if (msg.role === "user" && msgText) {
|
|
4697
|
+
lines.push(`User asked: ${truncate(msgText)}`);
|
|
4698
|
+
} else if (msg.role === "assistant") {
|
|
4699
|
+
if (msgText) lines.push(`Assistant: ${truncate(msgText)}`);
|
|
4700
|
+
const toolCalls = msg.metadata?.tool_calls;
|
|
4701
|
+
if (Array.isArray(toolCalls)) {
|
|
4702
|
+
const names = toolCalls.map(
|
|
4703
|
+
(tc) => tc.name ?? (tc.function?.name ?? "?")
|
|
4704
|
+
);
|
|
4705
|
+
lines.push(` Called tools: ${names.join(", ")}`);
|
|
4706
|
+
}
|
|
4707
|
+
}
|
|
4708
|
+
}
|
|
4709
|
+
if (lines.length === 0) return "";
|
|
4710
|
+
let result = "[Context summary: ";
|
|
4711
|
+
for (const line of lines) {
|
|
4712
|
+
if (result.length + line.length > 4e3) {
|
|
4713
|
+
result += "\n... (older messages omitted)";
|
|
4714
|
+
break;
|
|
4715
|
+
}
|
|
4716
|
+
result += line + "\n";
|
|
4717
|
+
}
|
|
4718
|
+
return result.trimEnd() + "]";
|
|
4719
|
+
}
|
|
4720
|
+
function trimToContextWindow(messages, budgetChars) {
|
|
4721
|
+
if (estimateChars(messages) <= budgetChars) {
|
|
4722
|
+
return [0, []];
|
|
4723
|
+
}
|
|
4724
|
+
let systemEnd = 0;
|
|
4725
|
+
for (let i = 0; i < messages.length; i++) {
|
|
4726
|
+
if (messages[i].role !== "system") {
|
|
4727
|
+
systemEnd = i;
|
|
4728
|
+
break;
|
|
4729
|
+
}
|
|
4730
|
+
if (i === messages.length - 1) systemEnd = messages.length;
|
|
4731
|
+
}
|
|
4732
|
+
const systemMsgs = messages.slice(0, systemEnd);
|
|
4733
|
+
const rest = messages.slice(systemEnd);
|
|
4734
|
+
const summaryBudget = Math.min(5e3, Math.floor(budgetChars * 0.05));
|
|
4735
|
+
const dropped = [];
|
|
4736
|
+
while (estimateChars([...systemMsgs, ...rest]) > budgetChars - summaryBudget && rest.length > 2) {
|
|
4737
|
+
dropped.push(rest.shift());
|
|
4738
|
+
}
|
|
4739
|
+
const droppedCount = dropped.length;
|
|
4740
|
+
messages.length = 0;
|
|
4741
|
+
messages.push(...systemMsgs);
|
|
4742
|
+
if (droppedCount > 0) {
|
|
4743
|
+
const summaryText = summarizeDropped(dropped);
|
|
4744
|
+
if (summaryText) {
|
|
4745
|
+
messages.push(new Message("user", [{ kind: "text", value: summaryText }]));
|
|
4746
|
+
}
|
|
4747
|
+
}
|
|
4748
|
+
messages.push(...rest);
|
|
4749
|
+
return [droppedCount, dropped];
|
|
4750
|
+
}
|
|
4751
|
+
var init_context2 = __esm({
|
|
4752
|
+
"src/core/context.ts"() {
|
|
4753
|
+
"use strict";
|
|
4754
|
+
init_types();
|
|
4755
|
+
}
|
|
4756
|
+
});
|
|
4757
|
+
|
|
4758
|
+
// src/core/guardrails.ts
|
|
4759
|
+
var GuardrailError, Guardrails;
|
|
4760
|
+
var init_guardrails = __esm({
|
|
4761
|
+
"src/core/guardrails.ts"() {
|
|
4762
|
+
"use strict";
|
|
4763
|
+
GuardrailError = class extends Error {
|
|
4764
|
+
reason;
|
|
4765
|
+
constructor(reason) {
|
|
4766
|
+
super(`Guardrail denied: ${reason}`);
|
|
4767
|
+
this.name = "GuardrailError";
|
|
4768
|
+
this.reason = reason;
|
|
4769
|
+
}
|
|
4770
|
+
};
|
|
4771
|
+
Guardrails = class {
|
|
4772
|
+
inputHook;
|
|
4773
|
+
outputHook;
|
|
4774
|
+
toolHook;
|
|
4775
|
+
constructor(options) {
|
|
4776
|
+
this.inputHook = options?.input;
|
|
4777
|
+
this.outputHook = options?.output;
|
|
4778
|
+
this.toolHook = options?.tool;
|
|
4779
|
+
}
|
|
4780
|
+
checkInput(messages) {
|
|
4781
|
+
if (!this.inputHook) return { allowed: true };
|
|
4782
|
+
return this.inputHook(messages);
|
|
4783
|
+
}
|
|
4784
|
+
checkOutput(message) {
|
|
4785
|
+
if (!this.outputHook) return { allowed: true };
|
|
4786
|
+
return this.outputHook(message);
|
|
4787
|
+
}
|
|
4788
|
+
checkTool(name, args) {
|
|
4789
|
+
if (!this.toolHook) return { allowed: true };
|
|
4790
|
+
return this.toolHook(name, args);
|
|
4791
|
+
}
|
|
4792
|
+
};
|
|
4793
|
+
}
|
|
4794
|
+
});
|
|
4795
|
+
|
|
4796
|
+
// src/core/structured.ts
|
|
4797
|
+
function createStructuredResult(data, rawJson) {
|
|
4798
|
+
const result = { ...data };
|
|
4799
|
+
Object.defineProperty(result, StructuredResultSymbol, {
|
|
4800
|
+
value: rawJson,
|
|
4801
|
+
writable: false,
|
|
4802
|
+
enumerable: false,
|
|
4803
|
+
configurable: false
|
|
4804
|
+
});
|
|
4805
|
+
return result;
|
|
4806
|
+
}
|
|
4807
|
+
function isStructuredResult(value) {
|
|
4808
|
+
return typeof value === "object" && value !== null && StructuredResultSymbol in value;
|
|
4809
|
+
}
|
|
4810
|
+
function cast(result, validator) {
|
|
4811
|
+
let jsonStr;
|
|
4812
|
+
if (isStructuredResult(result)) {
|
|
4813
|
+
jsonStr = result[StructuredResultSymbol];
|
|
4814
|
+
} else if (typeof result === "string") {
|
|
4815
|
+
jsonStr = result;
|
|
4816
|
+
} else {
|
|
4817
|
+
jsonStr = JSON.stringify(result);
|
|
4818
|
+
}
|
|
4819
|
+
const parsed = JSON.parse(jsonStr);
|
|
4820
|
+
if (validator) {
|
|
4821
|
+
return validator(parsed);
|
|
4822
|
+
}
|
|
4823
|
+
return parsed;
|
|
4824
|
+
}
|
|
4825
|
+
var StructuredResultSymbol;
|
|
4826
|
+
var init_structured = __esm({
|
|
4827
|
+
"src/core/structured.ts"() {
|
|
4828
|
+
"use strict";
|
|
4829
|
+
StructuredResultSymbol = /* @__PURE__ */ Symbol("prompty.rawJson");
|
|
4830
|
+
}
|
|
4831
|
+
});
|
|
4832
|
+
|
|
4631
4833
|
// src/core/pipeline.ts
|
|
4632
4834
|
var pipeline_exports = {};
|
|
4633
4835
|
__export(pipeline_exports, {
|
|
4634
|
-
|
|
4635
|
-
|
|
4836
|
+
invoke: () => invoke,
|
|
4837
|
+
invokeAgent: () => invokeAgent,
|
|
4636
4838
|
parse: () => parse,
|
|
4637
4839
|
prepare: () => prepare,
|
|
4638
4840
|
process: () => process2,
|
|
4639
4841
|
render: () => render,
|
|
4640
4842
|
resolveBindings: () => resolveBindings,
|
|
4641
4843
|
run: () => run,
|
|
4642
|
-
runAgent: () => runAgent,
|
|
4643
4844
|
validateInputs: () => validateInputs
|
|
4644
4845
|
});
|
|
4645
4846
|
function sanitizeNonces(value) {
|
|
@@ -4816,8 +5017,8 @@ async function run(agent, messages, options) {
|
|
|
4816
5017
|
return result;
|
|
4817
5018
|
});
|
|
4818
5019
|
}
|
|
4819
|
-
async function
|
|
4820
|
-
return traceSpan("
|
|
5020
|
+
async function invoke(prompt, inputs, options) {
|
|
5021
|
+
return traceSpan("invoke", async (emit) => {
|
|
4821
5022
|
const agent = typeof prompt === "string" ? await traceSpan("load", async (loadEmit) => {
|
|
4822
5023
|
loadEmit("signature", "prompty.load");
|
|
4823
5024
|
loadEmit("description", "Load a prompty file.");
|
|
@@ -4826,12 +5027,15 @@ async function execute(prompt, inputs, options) {
|
|
|
4826
5027
|
loadEmit("result", serializeAgent(loaded));
|
|
4827
5028
|
return loaded;
|
|
4828
5029
|
}) : prompt;
|
|
4829
|
-
emit("signature", "prompty.
|
|
4830
|
-
emit("description", "
|
|
5030
|
+
emit("signature", "prompty.invoke");
|
|
5031
|
+
emit("description", "Invoke a prompty");
|
|
4831
5032
|
emit("inputs", { prompt: serializeAgent(agent), inputs: inputs ?? {} });
|
|
4832
5033
|
const messages = await prepare(agent, inputs);
|
|
4833
5034
|
const result = await run(agent, messages, options);
|
|
4834
5035
|
emit("result", result);
|
|
5036
|
+
if (options?.validator) {
|
|
5037
|
+
return cast(result, options.validator);
|
|
5038
|
+
}
|
|
4835
5039
|
return result;
|
|
4836
5040
|
});
|
|
4837
5041
|
}
|
|
@@ -4853,7 +5057,7 @@ function isAsyncIterable(value) {
|
|
|
4853
5057
|
function isToolCallLike(item) {
|
|
4854
5058
|
return typeof item === "object" && item !== null && "id" in item && "name" in item && "arguments" in item;
|
|
4855
5059
|
}
|
|
4856
|
-
async function consumeStream(agent, response) {
|
|
5060
|
+
async function consumeStream(agent, response, onEvent) {
|
|
4857
5061
|
const processed = await process2(agent, response);
|
|
4858
5062
|
const toolCalls = [];
|
|
4859
5063
|
const textParts = [];
|
|
@@ -4863,96 +5067,17 @@ async function consumeStream(agent, response) {
|
|
|
4863
5067
|
toolCalls.push(item);
|
|
4864
5068
|
} else if (typeof item === "string") {
|
|
4865
5069
|
textParts.push(item);
|
|
5070
|
+
emitEvent(onEvent, "token", { token: item });
|
|
4866
5071
|
}
|
|
4867
5072
|
}
|
|
4868
5073
|
} else if (typeof processed === "string") {
|
|
4869
5074
|
textParts.push(processed);
|
|
5075
|
+
emitEvent(onEvent, "token", { token: processed });
|
|
4870
5076
|
}
|
|
4871
5077
|
return { toolCalls, content: textParts.join("") };
|
|
4872
5078
|
}
|
|
4873
|
-
async function
|
|
4874
|
-
const
|
|
4875
|
-
const apiType = agent.model?.apiType || "chat";
|
|
4876
|
-
const messages = [];
|
|
4877
|
-
const toolInputs = [];
|
|
4878
|
-
if (provider === "anthropic") {
|
|
4879
|
-
const rawContent = [];
|
|
4880
|
-
if (textContent) rawContent.push({ type: "text", text: textContent });
|
|
4881
|
-
for (const tc of toolCalls) {
|
|
4882
|
-
rawContent.push({
|
|
4883
|
-
type: "tool_use",
|
|
4884
|
-
id: tc.id,
|
|
4885
|
-
name: tc.name,
|
|
4886
|
-
input: JSON.parse(tc.arguments)
|
|
4887
|
-
});
|
|
4888
|
-
}
|
|
4889
|
-
messages.push(
|
|
4890
|
-
new Message("assistant", textContent ? [text(textContent)] : [], { content: rawContent })
|
|
4891
|
-
);
|
|
4892
|
-
} else if (apiType === "responses") {
|
|
4893
|
-
for (const tc of toolCalls) {
|
|
4894
|
-
messages.push(
|
|
4895
|
-
new Message("assistant", [], {
|
|
4896
|
-
responses_function_call: {
|
|
4897
|
-
type: "function_call",
|
|
4898
|
-
call_id: tc.id,
|
|
4899
|
-
name: tc.name,
|
|
4900
|
-
arguments: tc.arguments
|
|
4901
|
-
}
|
|
4902
|
-
})
|
|
4903
|
-
);
|
|
4904
|
-
}
|
|
4905
|
-
} else {
|
|
4906
|
-
const rawToolCalls = toolCalls.map((tc) => ({
|
|
4907
|
-
id: tc.id,
|
|
4908
|
-
type: "function",
|
|
4909
|
-
function: { name: tc.name, arguments: tc.arguments }
|
|
4910
|
-
}));
|
|
4911
|
-
messages.push(
|
|
4912
|
-
new Message("assistant", textContent ? [text(textContent)] : [], {
|
|
4913
|
-
tool_calls: rawToolCalls
|
|
4914
|
-
})
|
|
4915
|
-
);
|
|
4916
|
-
}
|
|
4917
|
-
const toolResultBlocks = [];
|
|
4918
|
-
for (const tc of toolCalls) {
|
|
4919
|
-
let result;
|
|
4920
|
-
let parsedArgs;
|
|
4921
|
-
try {
|
|
4922
|
-
parsedArgs = JSON.parse(tc.arguments);
|
|
4923
|
-
if (parentInputs && typeof parsedArgs === "object" && parsedArgs !== null && !Array.isArray(parsedArgs)) {
|
|
4924
|
-
parsedArgs = resolveBindings(agent, tc.name, parsedArgs, parentInputs);
|
|
4925
|
-
}
|
|
4926
|
-
result = await traceSpan(tc.name, async (toolEmit) => {
|
|
4927
|
-
toolEmit("signature", `prompty.tool.${tc.name}`);
|
|
4928
|
-
toolEmit("description", `Execute tool: ${tc.name}`);
|
|
4929
|
-
toolEmit("inputs", { arguments: parsedArgs, id: tc.id });
|
|
4930
|
-
const r = await dispatchTool(tc.name, parsedArgs, tools, agent, parentInputs ?? {});
|
|
4931
|
-
toolEmit("result", r);
|
|
4932
|
-
return r;
|
|
4933
|
-
});
|
|
4934
|
-
} catch (err) {
|
|
4935
|
-
result = `Error: ${err instanceof Error ? err.message : String(err)}`;
|
|
4936
|
-
}
|
|
4937
|
-
toolInputs.push({ name: tc.name, arguments: parsedArgs, id: tc.id, result });
|
|
4938
|
-
if (provider === "anthropic") {
|
|
4939
|
-
toolResultBlocks.push({ type: "tool_result", tool_use_id: tc.id, content: result });
|
|
4940
|
-
} else {
|
|
4941
|
-
messages.push(
|
|
4942
|
-
new Message("tool", [text(result)], { tool_call_id: tc.id, name: tc.name })
|
|
4943
|
-
);
|
|
4944
|
-
}
|
|
4945
|
-
}
|
|
4946
|
-
if (provider === "anthropic" && toolResultBlocks.length > 0) {
|
|
4947
|
-
messages.push(new Message("user", [], { tool_results: toolResultBlocks }));
|
|
4948
|
-
}
|
|
4949
|
-
if (parentEmit) {
|
|
4950
|
-
parentEmit("inputs", { tool_calls: toolInputs });
|
|
4951
|
-
}
|
|
4952
|
-
return messages;
|
|
4953
|
-
}
|
|
4954
|
-
async function executeAgent(prompt, inputs, options) {
|
|
4955
|
-
return traceSpan("executeAgent", async (emit) => {
|
|
5079
|
+
async function invokeAgent(prompt, inputs, options) {
|
|
5080
|
+
const rawResult = await traceSpan("invokeAgent", async (emit) => {
|
|
4956
5081
|
const agent = typeof prompt === "string" ? await traceSpan("load", async (loadEmit) => {
|
|
4957
5082
|
loadEmit("signature", "prompty.load");
|
|
4958
5083
|
loadEmit("description", "Load a prompty file.");
|
|
@@ -4963,21 +5088,72 @@ async function executeAgent(prompt, inputs, options) {
|
|
|
4963
5088
|
}) : prompt;
|
|
4964
5089
|
const tools = options?.tools ?? {};
|
|
4965
5090
|
const maxIterations = options?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
4966
|
-
|
|
4967
|
-
|
|
5091
|
+
const onEvent = options?.onEvent;
|
|
5092
|
+
const signal = options?.signal;
|
|
5093
|
+
const contextBudget = options?.contextBudget;
|
|
5094
|
+
const guardrails = options?.guardrails;
|
|
5095
|
+
const steering = options?.steering;
|
|
5096
|
+
const parallelToolCalls = options?.parallelToolCalls ?? false;
|
|
5097
|
+
emit("signature", "prompty.invokeAgent");
|
|
5098
|
+
emit("description", "Invoke a prompty with tool calling");
|
|
4968
5099
|
emit("inputs", { prompt: serializeAgent(agent), tools: Object.keys(tools), inputs: inputs ?? {} });
|
|
4969
|
-
|
|
5100
|
+
let messages = await prepare(agent, inputs);
|
|
4970
5101
|
const parentInputs = inputs ?? {};
|
|
4971
5102
|
const provider = resolveProvider(agent);
|
|
4972
5103
|
const executor = getExecutor(provider);
|
|
4973
|
-
let response =
|
|
5104
|
+
let response = null;
|
|
4974
5105
|
let iteration = 0;
|
|
4975
5106
|
while (true) {
|
|
5107
|
+
try {
|
|
5108
|
+
checkCancellation(signal);
|
|
5109
|
+
} catch (err) {
|
|
5110
|
+
emitEvent(onEvent, "cancelled", {});
|
|
5111
|
+
throw err;
|
|
5112
|
+
}
|
|
5113
|
+
if (steering) {
|
|
5114
|
+
const pending = steering.drain();
|
|
5115
|
+
if (pending.length > 0) {
|
|
5116
|
+
messages.push(...pending);
|
|
5117
|
+
emitEvent(onEvent, "messages_updated", { messages });
|
|
5118
|
+
emitEvent(onEvent, "status", { message: `Injected ${pending.length} steering message(s)` });
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
if (contextBudget !== void 0) {
|
|
5122
|
+
const [droppedCount] = trimToContextWindow(messages, contextBudget);
|
|
5123
|
+
if (droppedCount > 0) {
|
|
5124
|
+
emitEvent(onEvent, "messages_updated", { messages });
|
|
5125
|
+
emitEvent(onEvent, "status", { message: `Trimmed ${droppedCount} messages for context budget` });
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
if (guardrails) {
|
|
5129
|
+
const result2 = guardrails.checkInput(messages);
|
|
5130
|
+
if (!result2.allowed) {
|
|
5131
|
+
emitEvent(onEvent, "error", { message: `Input guardrail denied: ${result2.reason}` });
|
|
5132
|
+
throw new GuardrailError(result2.reason ?? "Input guardrail denied");
|
|
5133
|
+
}
|
|
5134
|
+
if (result2.rewrite) messages = result2.rewrite;
|
|
5135
|
+
}
|
|
5136
|
+
try {
|
|
5137
|
+
checkCancellation(signal);
|
|
5138
|
+
} catch (err) {
|
|
5139
|
+
emitEvent(onEvent, "cancelled", {});
|
|
5140
|
+
throw err;
|
|
5141
|
+
}
|
|
5142
|
+
response = await executor.execute(agent, messages);
|
|
4976
5143
|
if (isAsyncIterable(response)) {
|
|
4977
|
-
const { toolCalls, content } = await consumeStream(agent, response);
|
|
5144
|
+
const { toolCalls, content } = await consumeStream(agent, response, onEvent);
|
|
5145
|
+
if (guardrails && content) {
|
|
5146
|
+
const assistantMsg = new Message("assistant", [text(content)]);
|
|
5147
|
+
const gr = guardrails.checkOutput(assistantMsg);
|
|
5148
|
+
if (!gr.allowed) {
|
|
5149
|
+
emitEvent(onEvent, "error", { message: `Output guardrail denied: ${gr.reason}` });
|
|
5150
|
+
throw new GuardrailError(gr.reason ?? "Output guardrail denied");
|
|
5151
|
+
}
|
|
5152
|
+
}
|
|
4978
5153
|
if (toolCalls.length === 0) {
|
|
4979
5154
|
emit("iterations", iteration);
|
|
4980
5155
|
emit("result", content);
|
|
5156
|
+
emitEvent(onEvent, "done", { response: content, messages });
|
|
4981
5157
|
return content;
|
|
4982
5158
|
}
|
|
4983
5159
|
iteration++;
|
|
@@ -4987,17 +5163,57 @@ async function executeAgent(prompt, inputs, options) {
|
|
|
4987
5163
|
);
|
|
4988
5164
|
}
|
|
4989
5165
|
const toolMessages2 = await traceSpan("toolCalls", async (toolEmit) => {
|
|
4990
|
-
toolEmit("signature", "prompty.
|
|
5166
|
+
toolEmit("signature", "prompty.invokeAgent.toolCalls");
|
|
4991
5167
|
toolEmit("description", `Tool call round ${iteration}`);
|
|
4992
|
-
const result2 = await
|
|
5168
|
+
const result2 = await buildToolMessagesFromCallsWithExtensions(
|
|
5169
|
+
toolCalls,
|
|
5170
|
+
content,
|
|
5171
|
+
tools,
|
|
5172
|
+
agent,
|
|
5173
|
+
parentInputs,
|
|
5174
|
+
toolEmit,
|
|
5175
|
+
{ onEvent, signal, guardrails, parallel: parallelToolCalls }
|
|
5176
|
+
);
|
|
4993
5177
|
toolEmit("result", result2.map((m) => ({ role: m.role, content: m.parts.map((p) => p.value ?? "").join(""), metadata: m.metadata })));
|
|
4994
5178
|
return result2;
|
|
4995
5179
|
});
|
|
4996
5180
|
messages.push(...toolMessages2);
|
|
4997
|
-
|
|
5181
|
+
emitEvent(onEvent, "messages_updated", { messages });
|
|
4998
5182
|
continue;
|
|
4999
5183
|
}
|
|
5000
|
-
if (!hasToolCalls(response))
|
|
5184
|
+
if (!hasToolCalls(response)) {
|
|
5185
|
+
const finalResult = options?.raw ? response : await process2(agent, response);
|
|
5186
|
+
if (guardrails) {
|
|
5187
|
+
const contentStr = typeof finalResult === "string" ? finalResult : JSON.stringify(finalResult);
|
|
5188
|
+
const assistantMsg = new Message("assistant", [text(contentStr)]);
|
|
5189
|
+
const gr = guardrails.checkOutput(assistantMsg);
|
|
5190
|
+
if (!gr.allowed) {
|
|
5191
|
+
emitEvent(onEvent, "error", { message: `Output guardrail denied: ${gr.reason}` });
|
|
5192
|
+
throw new GuardrailError(gr.reason ?? "Output guardrail denied");
|
|
5193
|
+
}
|
|
5194
|
+
if (gr.rewrite !== void 0) {
|
|
5195
|
+
emit("iterations", iteration);
|
|
5196
|
+
emit("result", gr.rewrite);
|
|
5197
|
+
emitEvent(onEvent, "done", { response: gr.rewrite, messages });
|
|
5198
|
+
return gr.rewrite;
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
emit("iterations", iteration);
|
|
5202
|
+
emit("result", finalResult);
|
|
5203
|
+
emitEvent(onEvent, "done", { response: finalResult, messages });
|
|
5204
|
+
return finalResult;
|
|
5205
|
+
}
|
|
5206
|
+
if (guardrails) {
|
|
5207
|
+
const { textContent } = extractToolInfo(response);
|
|
5208
|
+
if (textContent) {
|
|
5209
|
+
const assistantMsg = new Message("assistant", [text(textContent)]);
|
|
5210
|
+
const gr = guardrails.checkOutput(assistantMsg);
|
|
5211
|
+
if (!gr.allowed) {
|
|
5212
|
+
emitEvent(onEvent, "error", { message: `Output guardrail denied: ${gr.reason}` });
|
|
5213
|
+
throw new GuardrailError(gr.reason ?? "Output guardrail denied");
|
|
5214
|
+
}
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5001
5217
|
iteration++;
|
|
5002
5218
|
if (iteration > maxIterations) {
|
|
5003
5219
|
throw new Error(
|
|
@@ -5005,24 +5221,37 @@ async function executeAgent(prompt, inputs, options) {
|
|
|
5005
5221
|
);
|
|
5006
5222
|
}
|
|
5007
5223
|
const toolMessages = await traceSpan("toolCalls", async (toolEmit) => {
|
|
5008
|
-
toolEmit("signature", "prompty.
|
|
5224
|
+
toolEmit("signature", "prompty.invokeAgent.toolCalls");
|
|
5009
5225
|
toolEmit("description", `Tool call round ${iteration}`);
|
|
5010
|
-
const result2 = await
|
|
5226
|
+
const result2 = await buildToolResultMessagesWithExtensions(
|
|
5227
|
+
response,
|
|
5228
|
+
tools,
|
|
5229
|
+
agent,
|
|
5230
|
+
parentInputs,
|
|
5231
|
+
toolEmit,
|
|
5232
|
+
{ onEvent, signal, guardrails, parallel: parallelToolCalls }
|
|
5233
|
+
);
|
|
5011
5234
|
toolEmit("result", result2.map((m) => ({ role: m.role, content: m.parts.map((p) => p.value ?? "").join(""), metadata: m.metadata })));
|
|
5012
5235
|
return result2;
|
|
5013
5236
|
});
|
|
5014
5237
|
messages.push(...toolMessages);
|
|
5015
|
-
|
|
5238
|
+
emitEvent(onEvent, "messages_updated", { messages });
|
|
5016
5239
|
}
|
|
5017
5240
|
emit("iterations", iteration);
|
|
5018
5241
|
if (options?.raw) {
|
|
5019
5242
|
emit("result", response);
|
|
5243
|
+
emitEvent(onEvent, "done", { response, messages });
|
|
5020
5244
|
return response;
|
|
5021
5245
|
}
|
|
5022
5246
|
const result = await process2(agent, response);
|
|
5023
5247
|
emit("result", result);
|
|
5248
|
+
emitEvent(onEvent, "done", { response: result, messages });
|
|
5024
5249
|
return result;
|
|
5025
5250
|
});
|
|
5251
|
+
if (options?.validator) {
|
|
5252
|
+
return cast(rawResult, options.validator);
|
|
5253
|
+
}
|
|
5254
|
+
return rawResult;
|
|
5026
5255
|
}
|
|
5027
5256
|
function expandThreads(messages, nonces, inputs) {
|
|
5028
5257
|
if (nonces.size === 0) return messages;
|
|
@@ -5091,160 +5320,138 @@ function hasToolCalls(response) {
|
|
|
5091
5320
|
}
|
|
5092
5321
|
return false;
|
|
5093
5322
|
}
|
|
5094
|
-
|
|
5323
|
+
function extractToolInfo(response) {
|
|
5324
|
+
if (typeof response !== "object" || response === null) {
|
|
5325
|
+
return { toolCalls: [], textContent: "" };
|
|
5326
|
+
}
|
|
5095
5327
|
const r = response;
|
|
5096
5328
|
if (Array.isArray(r.content) && r.stop_reason === "tool_use") {
|
|
5097
|
-
|
|
5329
|
+
const content = r.content;
|
|
5330
|
+
const toolCalls = content.filter((b) => b.type === "tool_use").map((b) => ({
|
|
5331
|
+
id: b.id,
|
|
5332
|
+
name: b.name,
|
|
5333
|
+
arguments: JSON.stringify(b.input)
|
|
5334
|
+
}));
|
|
5335
|
+
const textContent = content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
5336
|
+
return { toolCalls, textContent };
|
|
5098
5337
|
}
|
|
5099
5338
|
if (r.object === "response" && Array.isArray(r.output)) {
|
|
5100
|
-
|
|
5339
|
+
const funcCalls = r.output.filter(
|
|
5340
|
+
(item) => item.type === "function_call"
|
|
5341
|
+
);
|
|
5342
|
+
const toolCalls = funcCalls.map((fc) => ({
|
|
5343
|
+
id: fc.call_id ?? fc.id ?? "",
|
|
5344
|
+
call_id: fc.call_id ?? fc.id ?? "",
|
|
5345
|
+
name: fc.name,
|
|
5346
|
+
arguments: fc.arguments ?? "{}"
|
|
5347
|
+
}));
|
|
5348
|
+
return { toolCalls, textContent: "" };
|
|
5101
5349
|
}
|
|
5102
|
-
return buildOpenAIToolResultMessages(r, tools, agent, parentInputs, parentEmit);
|
|
5103
|
-
}
|
|
5104
|
-
async function buildOpenAIToolResultMessages(r, tools, agent, parentInputs, parentEmit) {
|
|
5105
5350
|
const choices = r.choices;
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
for (const tc of toolCalls) {
|
|
5118
|
-
const fn = tc.function;
|
|
5119
|
-
const toolName = fn.name;
|
|
5120
|
-
const toolCallId = tc.id;
|
|
5121
|
-
let result;
|
|
5122
|
-
let parsedArgs;
|
|
5123
|
-
try {
|
|
5124
|
-
parsedArgs = JSON.parse(fn.arguments);
|
|
5125
|
-
if (agent && parentInputs && typeof parsedArgs === "object" && parsedArgs !== null && !Array.isArray(parsedArgs)) {
|
|
5126
|
-
parsedArgs = resolveBindings(agent, toolName, parsedArgs, parentInputs);
|
|
5127
|
-
}
|
|
5128
|
-
result = await traceSpan(toolName, async (toolEmit) => {
|
|
5129
|
-
toolEmit("signature", `prompty.tool.${toolName}`);
|
|
5130
|
-
toolEmit("description", `Execute tool: ${toolName}`);
|
|
5131
|
-
toolEmit("inputs", { arguments: parsedArgs, tool_call_id: toolCallId });
|
|
5132
|
-
const r2 = await dispatchTool(toolName, parsedArgs, tools, agent ?? {}, parentInputs ?? {});
|
|
5133
|
-
toolEmit("result", r2);
|
|
5134
|
-
return r2;
|
|
5351
|
+
if (Array.isArray(choices) && choices.length > 0) {
|
|
5352
|
+
const choice = choices[0];
|
|
5353
|
+
const message = choice.message;
|
|
5354
|
+
if (message && Array.isArray(message.tool_calls)) {
|
|
5355
|
+
const toolCalls = message.tool_calls.map((tc) => {
|
|
5356
|
+
const fn = tc.function;
|
|
5357
|
+
return {
|
|
5358
|
+
id: tc.id,
|
|
5359
|
+
name: fn.name,
|
|
5360
|
+
arguments: fn.arguments
|
|
5361
|
+
};
|
|
5135
5362
|
});
|
|
5136
|
-
|
|
5137
|
-
result = `Error: ${err instanceof Error ? err.message : String(err)}`;
|
|
5363
|
+
return { toolCalls, textContent: message.content ?? "" };
|
|
5138
5364
|
}
|
|
5139
|
-
toolInputs.push({ name: toolName, arguments: parsedArgs, tool_call_id: toolCallId, result });
|
|
5140
|
-
messages.push(
|
|
5141
|
-
new Message("tool", [text(result)], {
|
|
5142
|
-
tool_call_id: toolCallId,
|
|
5143
|
-
name: toolName
|
|
5144
|
-
})
|
|
5145
|
-
);
|
|
5146
|
-
}
|
|
5147
|
-
if (parentEmit) {
|
|
5148
|
-
parentEmit("inputs", { tool_calls: toolInputs });
|
|
5149
5365
|
}
|
|
5150
|
-
return
|
|
5366
|
+
return { toolCalls: [], textContent: "" };
|
|
5151
5367
|
}
|
|
5152
|
-
async function
|
|
5153
|
-
const
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
const toolName = block.name;
|
|
5164
|
-
const toolCallId = block.id;
|
|
5165
|
-
let toolArgs = block.input;
|
|
5166
|
-
if (agent && parentInputs && typeof toolArgs === "object" && toolArgs !== null && !Array.isArray(toolArgs)) {
|
|
5167
|
-
toolArgs = resolveBindings(agent, toolName, toolArgs, parentInputs);
|
|
5168
|
-
}
|
|
5169
|
-
let result;
|
|
5368
|
+
async function dispatchOneToolWithExtensions(tc, tools, agent, parentInputs, ext) {
|
|
5369
|
+
const { onEvent, signal, guardrails } = ext;
|
|
5370
|
+
try {
|
|
5371
|
+
checkCancellation(signal);
|
|
5372
|
+
} catch (err) {
|
|
5373
|
+
emitEvent(onEvent, "cancelled", {});
|
|
5374
|
+
throw err;
|
|
5375
|
+
}
|
|
5376
|
+
emitEvent(onEvent, "tool_call_start", { name: tc.name, arguments: tc.arguments });
|
|
5377
|
+
if (guardrails) {
|
|
5378
|
+
let parsedArgs2 = {};
|
|
5170
5379
|
try {
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5380
|
+
const parsed = JSON.parse(tc.arguments);
|
|
5381
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
5382
|
+
parsedArgs2 = parsed;
|
|
5383
|
+
}
|
|
5384
|
+
} catch {
|
|
5385
|
+
}
|
|
5386
|
+
const gr = guardrails.checkTool(tc.name, parsedArgs2);
|
|
5387
|
+
if (!gr.allowed) {
|
|
5388
|
+
const deniedMsg = `Tool denied by guardrail: ${gr.reason}`;
|
|
5389
|
+
emitEvent(onEvent, "tool_result", { name: tc.name, result: deniedMsg });
|
|
5390
|
+
return deniedMsg;
|
|
5391
|
+
}
|
|
5392
|
+
if (gr.rewrite !== void 0) {
|
|
5393
|
+
tc = { ...tc, arguments: typeof gr.rewrite === "string" ? gr.rewrite : JSON.stringify(gr.rewrite) };
|
|
5181
5394
|
}
|
|
5182
|
-
toolInputs.push({ name: toolName, arguments: toolArgs, tool_use_id: toolCallId, result });
|
|
5183
|
-
toolResultBlocks.push({
|
|
5184
|
-
type: "tool_result",
|
|
5185
|
-
tool_use_id: toolCallId,
|
|
5186
|
-
content: result
|
|
5187
|
-
});
|
|
5188
5395
|
}
|
|
5189
|
-
|
|
5190
|
-
|
|
5396
|
+
let result;
|
|
5397
|
+
let parsedArgs;
|
|
5398
|
+
try {
|
|
5399
|
+
parsedArgs = JSON.parse(tc.arguments);
|
|
5400
|
+
if (agent && parentInputs && typeof parsedArgs === "object" && parsedArgs !== null && !Array.isArray(parsedArgs)) {
|
|
5401
|
+
parsedArgs = resolveBindings(agent, tc.name, parsedArgs, parentInputs);
|
|
5402
|
+
}
|
|
5403
|
+
result = await traceSpan(tc.name, async (toolEmit) => {
|
|
5404
|
+
toolEmit("signature", `prompty.tool.${tc.name}`);
|
|
5405
|
+
toolEmit("description", `Execute tool: ${tc.name}`);
|
|
5406
|
+
toolEmit("inputs", { arguments: parsedArgs, id: tc.id });
|
|
5407
|
+
const r = await dispatchTool(tc.name, parsedArgs, tools, agent, parentInputs);
|
|
5408
|
+
toolEmit("result", r);
|
|
5409
|
+
return r;
|
|
5410
|
+
});
|
|
5411
|
+
} catch (err) {
|
|
5412
|
+
if (err instanceof CancelledError) throw err;
|
|
5413
|
+
result = `Error: ${err instanceof Error ? err.message : String(err)}`;
|
|
5191
5414
|
}
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
);
|
|
5195
|
-
return messages;
|
|
5415
|
+
emitEvent(onEvent, "tool_result", { name: tc.name, result });
|
|
5416
|
+
return result;
|
|
5196
5417
|
}
|
|
5197
|
-
async function
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
const toolInputs = [];
|
|
5202
|
-
for (const fc of funcCalls) {
|
|
5203
|
-
const toolName = fc.name;
|
|
5204
|
-
const callId = fc.call_id ?? fc.id ?? "";
|
|
5205
|
-
const argsStr = fc.arguments ?? "{}";
|
|
5206
|
-
messages.push(
|
|
5207
|
-
new Message("assistant", [], {
|
|
5208
|
-
responses_function_call: {
|
|
5209
|
-
type: "function_call",
|
|
5210
|
-
call_id: callId,
|
|
5211
|
-
name: toolName,
|
|
5212
|
-
arguments: argsStr
|
|
5213
|
-
}
|
|
5214
|
-
})
|
|
5215
|
-
);
|
|
5216
|
-
let result;
|
|
5217
|
-
let parsedArgs;
|
|
5218
|
-
try {
|
|
5219
|
-
parsedArgs = JSON.parse(argsStr);
|
|
5220
|
-
if (agent && parentInputs && typeof parsedArgs === "object" && parsedArgs !== null && !Array.isArray(parsedArgs)) {
|
|
5221
|
-
parsedArgs = resolveBindings(agent, toolName, parsedArgs, parentInputs);
|
|
5222
|
-
}
|
|
5223
|
-
result = await traceSpan(toolName, async (toolEmit) => {
|
|
5224
|
-
toolEmit("signature", `prompty.tool.${toolName}`);
|
|
5225
|
-
toolEmit("description", `Execute tool: ${toolName}`);
|
|
5226
|
-
toolEmit("inputs", { arguments: parsedArgs, call_id: callId });
|
|
5227
|
-
const r2 = await dispatchTool(toolName, parsedArgs, tools, agent ?? {}, parentInputs ?? {});
|
|
5228
|
-
toolEmit("result", r2);
|
|
5229
|
-
return r2;
|
|
5230
|
-
});
|
|
5231
|
-
} catch (err) {
|
|
5232
|
-
result = `Error: ${err instanceof Error ? err.message : String(err)}`;
|
|
5233
|
-
}
|
|
5234
|
-
toolInputs.push({ name: toolName, arguments: parsedArgs, call_id: callId, result });
|
|
5235
|
-
messages.push(
|
|
5236
|
-
new Message("tool", [text(result)], {
|
|
5237
|
-
tool_call_id: callId,
|
|
5238
|
-
name: toolName
|
|
5239
|
-
})
|
|
5418
|
+
async function dispatchToolsWithExtensions(toolCalls, tools, agent, parentInputs, ext) {
|
|
5419
|
+
if (ext.parallel && toolCalls.length > 1) {
|
|
5420
|
+
return Promise.all(
|
|
5421
|
+
toolCalls.map((tc) => dispatchOneToolWithExtensions(tc, tools, agent, parentInputs, ext))
|
|
5240
5422
|
);
|
|
5241
5423
|
}
|
|
5424
|
+
const results = [];
|
|
5425
|
+
for (const tc of toolCalls) {
|
|
5426
|
+
results.push(await dispatchOneToolWithExtensions(tc, tools, agent, parentInputs, ext));
|
|
5427
|
+
}
|
|
5428
|
+
return results;
|
|
5429
|
+
}
|
|
5430
|
+
async function buildToolResultMessagesWithExtensions(response, tools, agent, parentInputs, parentEmit, ext) {
|
|
5431
|
+
const { toolCalls, textContent } = extractToolInfo(response);
|
|
5432
|
+
const toolResults = await dispatchToolsWithExtensions(toolCalls, tools, agent, parentInputs, ext);
|
|
5433
|
+
if (parentEmit) {
|
|
5434
|
+
parentEmit("inputs", {
|
|
5435
|
+
tool_calls: toolCalls.map((tc, i) => ({ name: tc.name, arguments: tc.arguments, id: tc.id, result: toolResults[i] }))
|
|
5436
|
+
});
|
|
5437
|
+
}
|
|
5438
|
+
const provider = resolveProvider(agent);
|
|
5439
|
+
const executor = getExecutor(provider);
|
|
5440
|
+
return executor.formatToolMessages(response, toolCalls, toolResults, textContent);
|
|
5441
|
+
}
|
|
5442
|
+
async function buildToolMessagesFromCallsWithExtensions(toolCalls, textContent, tools, agent, parentInputs, parentEmit, ext) {
|
|
5443
|
+
const normalizedCalls = toolCalls.map((tc) => ({ id: tc.id, name: tc.name, arguments: tc.arguments }));
|
|
5444
|
+
const toolResults = await dispatchToolsWithExtensions(normalizedCalls, tools, agent, parentInputs, ext);
|
|
5242
5445
|
if (parentEmit) {
|
|
5243
|
-
parentEmit("inputs", {
|
|
5446
|
+
parentEmit("inputs", {
|
|
5447
|
+
tool_calls: normalizedCalls.map((tc, i) => ({ name: tc.name, arguments: tc.arguments, id: tc.id, result: toolResults[i] }))
|
|
5448
|
+
});
|
|
5244
5449
|
}
|
|
5245
|
-
|
|
5450
|
+
const provider = resolveProvider(agent);
|
|
5451
|
+
const executor = getExecutor(provider);
|
|
5452
|
+
return executor.formatToolMessages(null, normalizedCalls, toolResults, textContent);
|
|
5246
5453
|
}
|
|
5247
|
-
var DEFAULT_FORMAT, DEFAULT_PARSER, DEFAULT_PROVIDER, DEFAULT_MAX_ITERATIONS
|
|
5454
|
+
var DEFAULT_FORMAT, DEFAULT_PARSER, DEFAULT_PROVIDER, DEFAULT_MAX_ITERATIONS;
|
|
5248
5455
|
var init_pipeline = __esm({
|
|
5249
5456
|
"src/core/pipeline.ts"() {
|
|
5250
5457
|
"use strict";
|
|
@@ -5254,11 +5461,15 @@ var init_pipeline = __esm({
|
|
|
5254
5461
|
init_tracer();
|
|
5255
5462
|
init_loader();
|
|
5256
5463
|
init_tool_dispatch();
|
|
5464
|
+
init_agent_events();
|
|
5465
|
+
init_cancellation();
|
|
5466
|
+
init_context2();
|
|
5467
|
+
init_guardrails();
|
|
5468
|
+
init_structured();
|
|
5257
5469
|
DEFAULT_FORMAT = "nunjucks";
|
|
5258
5470
|
DEFAULT_PARSER = "prompty";
|
|
5259
5471
|
DEFAULT_PROVIDER = "openai";
|
|
5260
5472
|
DEFAULT_MAX_ITERATIONS = 10;
|
|
5261
|
-
runAgent = executeAgent;
|
|
5262
5473
|
}
|
|
5263
5474
|
});
|
|
5264
5475
|
|
|
@@ -5288,6 +5499,101 @@ function clearConnections() {
|
|
|
5288
5499
|
init_loader();
|
|
5289
5500
|
init_pipeline();
|
|
5290
5501
|
init_tool_dispatch();
|
|
5502
|
+
init_agent_events();
|
|
5503
|
+
init_cancellation();
|
|
5504
|
+
init_context2();
|
|
5505
|
+
init_guardrails();
|
|
5506
|
+
|
|
5507
|
+
// src/core/steering.ts
|
|
5508
|
+
init_types();
|
|
5509
|
+
var Steering = class {
|
|
5510
|
+
queue = [];
|
|
5511
|
+
/** Enqueue a message to be injected at the next iteration. */
|
|
5512
|
+
send(message) {
|
|
5513
|
+
this.queue.push(message);
|
|
5514
|
+
}
|
|
5515
|
+
/** Remove and return all queued messages as Message objects. */
|
|
5516
|
+
drain() {
|
|
5517
|
+
const items = this.queue.splice(0);
|
|
5518
|
+
return items.map((text2) => new Message("user", [{ kind: "text", value: text2 }]));
|
|
5519
|
+
}
|
|
5520
|
+
/** Whether there are pending messages without consuming them. */
|
|
5521
|
+
get hasPending() {
|
|
5522
|
+
return this.queue.length > 0;
|
|
5523
|
+
}
|
|
5524
|
+
};
|
|
5525
|
+
|
|
5526
|
+
// src/core/tool-decorator.ts
|
|
5527
|
+
init_tool();
|
|
5528
|
+
init_property();
|
|
5529
|
+
init_tool_dispatch();
|
|
5530
|
+
function tool(fn, options) {
|
|
5531
|
+
const toolName = options?.name ?? fn.name;
|
|
5532
|
+
const toolDesc = options?.description ?? "";
|
|
5533
|
+
const shouldRegister = options?.register !== false;
|
|
5534
|
+
const properties = (options?.parameters ?? []).map(
|
|
5535
|
+
(p) => new Property({
|
|
5536
|
+
name: p.name,
|
|
5537
|
+
kind: p.kind ?? "string",
|
|
5538
|
+
required: p.required ?? p.default === void 0,
|
|
5539
|
+
description: p.description,
|
|
5540
|
+
default: p.default
|
|
5541
|
+
})
|
|
5542
|
+
);
|
|
5543
|
+
const toolDef = new FunctionTool({
|
|
5544
|
+
name: toolName,
|
|
5545
|
+
kind: "function",
|
|
5546
|
+
description: toolDesc,
|
|
5547
|
+
parameters: properties
|
|
5548
|
+
});
|
|
5549
|
+
const wrapped = fn;
|
|
5550
|
+
wrapped.__tool__ = toolDef;
|
|
5551
|
+
if (shouldRegister) {
|
|
5552
|
+
registerTool(toolName, fn);
|
|
5553
|
+
}
|
|
5554
|
+
return wrapped;
|
|
5555
|
+
}
|
|
5556
|
+
function bindTools(agent, tools) {
|
|
5557
|
+
const handlers = {};
|
|
5558
|
+
for (const fn of tools) {
|
|
5559
|
+
const toolDef = fn.__tool__;
|
|
5560
|
+
if (!toolDef) {
|
|
5561
|
+
throw new Error(
|
|
5562
|
+
`Function '${fn.name || "(anonymous)"}' is not a tool()-wrapped function (missing __tool__ property)`
|
|
5563
|
+
);
|
|
5564
|
+
}
|
|
5565
|
+
const name = toolDef.name;
|
|
5566
|
+
if (name in handlers) {
|
|
5567
|
+
throw new Error(`Duplicate tool handler: '${name}'`);
|
|
5568
|
+
}
|
|
5569
|
+
handlers[name] = fn;
|
|
5570
|
+
}
|
|
5571
|
+
const declaredFunctionTools = /* @__PURE__ */ new Set();
|
|
5572
|
+
for (const toolDef of agent.tools ?? []) {
|
|
5573
|
+
if (toolDef.kind === "function") {
|
|
5574
|
+
declaredFunctionTools.add(toolDef.name);
|
|
5575
|
+
}
|
|
5576
|
+
}
|
|
5577
|
+
for (const name of Object.keys(handlers)) {
|
|
5578
|
+
if (!declaredFunctionTools.has(name)) {
|
|
5579
|
+
const declared = [...declaredFunctionTools].sort().join(", ") || "(none)";
|
|
5580
|
+
throw new Error(
|
|
5581
|
+
`Tool handler '${name}' has no matching 'kind: function' declaration in agent.tools. Declared function tools: ${declared}`
|
|
5582
|
+
);
|
|
5583
|
+
}
|
|
5584
|
+
}
|
|
5585
|
+
for (const name of declaredFunctionTools) {
|
|
5586
|
+
if (!(name in handlers)) {
|
|
5587
|
+
console.warn(
|
|
5588
|
+
`Tool '${name}' is declared in agent.tools but no handler was provided to bindTools()`
|
|
5589
|
+
);
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
return handlers;
|
|
5593
|
+
}
|
|
5594
|
+
|
|
5595
|
+
// src/core/index.ts
|
|
5596
|
+
init_structured();
|
|
5291
5597
|
|
|
5292
5598
|
// src/renderers/nunjucks.ts
|
|
5293
5599
|
init_common();
|
|
@@ -5680,11 +5986,14 @@ export {
|
|
|
5680
5986
|
ApiKeyConnection,
|
|
5681
5987
|
ArrayProperty,
|
|
5682
5988
|
Binding,
|
|
5989
|
+
CancelledError,
|
|
5683
5990
|
Connection,
|
|
5684
5991
|
CustomTool,
|
|
5685
5992
|
FormatConfig,
|
|
5686
5993
|
FoundryConnection,
|
|
5687
5994
|
FunctionTool,
|
|
5995
|
+
GuardrailError,
|
|
5996
|
+
Guardrails,
|
|
5688
5997
|
InvokerError,
|
|
5689
5998
|
LoadContext,
|
|
5690
5999
|
McpApprovalMode,
|
|
@@ -5710,22 +6019,31 @@ export {
|
|
|
5710
6019
|
ReferenceConnection,
|
|
5711
6020
|
RemoteConnection,
|
|
5712
6021
|
SaveContext,
|
|
6022
|
+
Steering,
|
|
6023
|
+
StructuredResultSymbol,
|
|
5713
6024
|
Template,
|
|
5714
6025
|
ThreadMarker,
|
|
5715
6026
|
Tool,
|
|
5716
6027
|
Tracer,
|
|
6028
|
+
bindTools,
|
|
6029
|
+
cast,
|
|
6030
|
+
checkCancellation,
|
|
5717
6031
|
clearCache,
|
|
5718
6032
|
clearConnections,
|
|
5719
6033
|
consoleTracer,
|
|
6034
|
+
createStructuredResult,
|
|
5720
6035
|
dictContentToPart,
|
|
5721
6036
|
dictToMessage,
|
|
5722
|
-
|
|
5723
|
-
|
|
6037
|
+
emitEvent,
|
|
6038
|
+
estimateChars,
|
|
5724
6039
|
getConnection,
|
|
5725
6040
|
getExecutor,
|
|
5726
6041
|
getParser,
|
|
5727
6042
|
getProcessor,
|
|
5728
6043
|
getRenderer,
|
|
6044
|
+
invoke,
|
|
6045
|
+
invokeAgent,
|
|
6046
|
+
isStructuredResult,
|
|
5729
6047
|
load,
|
|
5730
6048
|
otelTracer,
|
|
5731
6049
|
parse,
|
|
@@ -5739,14 +6057,16 @@ export {
|
|
|
5739
6057
|
render,
|
|
5740
6058
|
resolveBindings,
|
|
5741
6059
|
run,
|
|
5742
|
-
runAgent,
|
|
5743
6060
|
sanitizeValue,
|
|
6061
|
+
summarizeDropped,
|
|
5744
6062
|
text,
|
|
5745
6063
|
textMessage,
|
|
5746
6064
|
toSerializable,
|
|
6065
|
+
tool,
|
|
5747
6066
|
trace,
|
|
5748
6067
|
traceMethod,
|
|
5749
6068
|
traceSpan,
|
|
6069
|
+
trimToContextWindow,
|
|
5750
6070
|
validateInputs
|
|
5751
6071
|
};
|
|
5752
6072
|
//# sourceMappingURL=index.js.map
|