llmz 0.8.0 → 0.9.1

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.
Files changed (68) hide show
  1. package/README.md +45 -11
  2. package/dist/chat.d.ts +6 -6
  3. package/dist/{common-DdArNQhl.cjs → common-DJkSpeqw.cjs} +239 -22
  4. package/dist/{common-pgJjFu2Y.js → common-DuEhn6u3.js} +234 -23
  5. package/dist/compiler/plugins/variable-extraction.d.ts +1 -7
  6. package/dist/{compiler-C-OI9sim.cjs → compiler-BJJUmNS9.cjs} +34 -68
  7. package/dist/{compiler-CW1VjQsn.js → compiler-BPl-5CXh.js} +34 -68
  8. package/dist/{component-BXS8vAwO.cjs → component-CPKXe6Ca.cjs} +2 -2
  9. package/dist/{component-Dq7ZLdvy.js → component-DGG7d_Mz.js} +1 -1
  10. package/dist/component.default.d.ts +10 -0
  11. package/dist/context.d.ts +4 -8
  12. package/dist/{custom-client-HkM1Sdzv.cjs → custom-client-B_o56CB4.cjs} +22 -19
  13. package/dist/{custom-client-2V9lmzUf.js → custom-client-C-nDKG37.js} +17 -14
  14. package/dist/{dual-modes-Cb7ThvoV.cjs → dual-modes-BNHlj2qM.cjs} +1252 -1181
  15. package/dist/{dual-modes-Cy0_W4O2.js → dual-modes-BNIiNLrR.js} +1257 -1180
  16. package/dist/example-format.d.ts +8 -0
  17. package/dist/{execute-COIHOIKR.cjs → execute-0bvqakr7.cjs} +91 -99
  18. package/dist/{execute-Aw4cbIx-.js → execute-CWFIL5ny.js} +91 -99
  19. package/dist/{exit-DUM96DN1.cjs → exit-CGLXI0BH.cjs} +2 -2
  20. package/dist/index.cjs +265 -22
  21. package/dist/index.js +258 -15
  22. package/dist/index.workerd.js +8565 -8005
  23. package/dist/inspect.d.ts +2 -0
  24. package/dist/isPlainObject-CSxXVKCk.cjs +56 -0
  25. package/dist/isPlainObject-D39AzPO2.js +51 -0
  26. package/dist/{jsx-D5Y2cPo-.cjs → jsx-BJ6GWXI2.cjs} +3 -57
  27. package/dist/{jsx-B0iYyvfr.js → jsx-CIgdGGVs.js} +2 -50
  28. package/dist/message-stream/instructions.d.ts +8 -0
  29. package/dist/message-stream/parser.d.ts +6 -0
  30. package/dist/message-stream/response-parser.d.ts +24 -0
  31. package/dist/message-stream/response-parser.test.d.ts +1 -0
  32. package/dist/message-stream/types.d.ts +3 -2
  33. package/dist/prompts/adherence.test.d.ts +1 -0
  34. package/dist/prompts/catalogue-examples.test.d.ts +1 -0
  35. package/dist/prompts/chat-mode/protocol.d.ts +2 -0
  36. package/dist/prompts/chat-mode/system.d.ts +1 -1
  37. package/dist/prompts/chat-mode/user.d.ts +1 -1
  38. package/dist/prompts/code-examples.d.ts +2 -0
  39. package/dist/prompts/code-examples.test.d.ts +1 -0
  40. package/dist/prompts/common.d.ts +2 -1
  41. package/dist/prompts/concrete-patterns.test.d.ts +1 -0
  42. package/dist/prompts/long-search.test.d.ts +1 -0
  43. package/dist/prompts/prompt.d.ts +5 -2
  44. package/dist/prompts/protocol-basics.d.ts +5 -0
  45. package/dist/prompts/protocol-simple.test.d.ts +1 -0
  46. package/dist/prompts/protocol.d.ts +13 -0
  47. package/dist/prompts/sections.test.d.ts +1 -0
  48. package/dist/prompts/worker-mode/protocol.d.ts +2 -0
  49. package/dist/prompts/worker-mode/system.d.ts +1 -1
  50. package/dist/prompts/worker-mode/user.d.ts +1 -1
  51. package/dist/runtime/citations.test.d.ts +1 -0
  52. package/dist/runtime/fixtures/long-search.d.ts +19 -0
  53. package/dist/runtime/fixtures/protocol-languages.d.ts +74 -0
  54. package/dist/runtime/fixtures/qwen-protocol-failures.d.ts +29 -0
  55. package/dist/runtime/generate.d.ts +2 -9
  56. package/dist/runtime/generate.test.d.ts +1 -0
  57. package/dist/runtime/protocol-adherence.test.d.ts +1 -0
  58. package/dist/runtime/types.d.ts +4 -7
  59. package/dist/{tool-Bv8N4IPj.js → tool-B6Pmuk6K.js} +35 -49
  60. package/dist/{tool-Dy6AJpJH.cjs → tool-BLTrA-sL.cjs} +38 -52
  61. package/dist/tool.d.ts +5 -3
  62. package/dist/{truncator-DZqEqnpD.js → truncator-CD7QtE84.js} +11 -6
  63. package/dist/{truncator-CLkouTCO.cjs → truncator-DmCu9M4m.cjs} +13 -8
  64. package/dist/{typings-3lsqCbkn.cjs → typings-DXJMu59O.cjs} +2 -2
  65. package/dist/{utils-3ESwP3yg.cjs → utils-DGQ4sRke.cjs} +1 -1
  66. package/dist/{vm-BLsHw1da.js → vm-Cn3jvZ00.js} +109 -53
  67. package/dist/{vm-D6s1zF6M.cjs → vm-X0uTj5Aa.cjs} +109 -53
  68. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ /** Synthetic multilingual inputs shared by parser/execution and live model tests. */
2
+ export declare const protocolLanguages: readonly [{
3
+ readonly language: 'English';
4
+ readonly hello: 'Hello!';
5
+ readonly question: 'Help me choose a plan.';
6
+ readonly reply: 'How many conversations do you expect per month?';
7
+ readonly checking: 'Checking.';
8
+ }, {
9
+ readonly language: 'French';
10
+ readonly hello: 'Bonjour !';
11
+ readonly question: 'Aidez-moi à choisir un forfait.';
12
+ readonly reply: 'Combien de conversations prévoyez-vous par mois ?';
13
+ readonly checking: 'Je vérifie.';
14
+ }, {
15
+ readonly language: 'Spanish';
16
+ readonly hello: '¡Hola!';
17
+ readonly question: 'Ayúdame a elegir un plan.';
18
+ readonly reply: '¿Cuántas conversaciones esperas al mes?';
19
+ readonly checking: 'Estoy comprobando.';
20
+ }, {
21
+ readonly language: 'German';
22
+ readonly hello: 'Hallo!';
23
+ readonly question: 'Hilf mir, einen Tarif auszuwählen.';
24
+ readonly reply: 'Wie viele Gespräche erwartest du pro Monat?';
25
+ readonly checking: 'Ich prüfe das.';
26
+ }, {
27
+ readonly language: 'Portuguese';
28
+ readonly hello: 'Olá!';
29
+ readonly question: 'Ajude-me a escolher um plano.';
30
+ readonly reply: 'Quantas conversas você espera por mês?';
31
+ readonly checking: 'Estou verificando.';
32
+ }, {
33
+ readonly language: 'Italian';
34
+ readonly hello: 'Ciao!';
35
+ readonly question: 'Aiutami a scegliere un piano.';
36
+ readonly reply: 'Quante conversazioni prevedi al mese?';
37
+ readonly checking: 'Sto controllando.';
38
+ }, {
39
+ readonly language: 'Arabic';
40
+ readonly hello: 'مرحباً!';
41
+ readonly question: 'ساعدني في اختيار خطة.';
42
+ readonly reply: 'كم محادثة تتوقع في الشهر؟';
43
+ readonly checking: 'أتحقق الآن.';
44
+ }, {
45
+ readonly language: 'Chinese';
46
+ readonly hello: '你好!';
47
+ readonly question: '帮我选择一个套餐。';
48
+ readonly reply: '你预计每月有多少次对话?';
49
+ readonly checking: '正在查询。';
50
+ }, {
51
+ readonly language: 'Japanese';
52
+ readonly hello: 'こんにちは!';
53
+ readonly question: 'プラン選びを手伝ってください。';
54
+ readonly reply: '月に何件の会話を想定していますか?';
55
+ readonly checking: '確認しています。';
56
+ }, {
57
+ readonly language: 'Korean';
58
+ readonly hello: '안녕하세요!';
59
+ readonly question: '요금제 선택을 도와주세요.';
60
+ readonly reply: '월별 대화 수는 얼마나 예상하시나요?';
61
+ readonly checking: '확인 중입니다.';
62
+ }, {
63
+ readonly language: 'Hindi';
64
+ readonly hello: 'नमस्ते!';
65
+ readonly question: 'एक योजना चुनने में मेरी मदद करें।';
66
+ readonly reply: 'आपको हर महीने कितनी बातचीत की उम्मीद है?';
67
+ readonly checking: 'मैं जाँच कर रहा हूँ।';
68
+ }, {
69
+ readonly language: 'Russian';
70
+ readonly hello: 'Здравствуйте!';
71
+ readonly question: 'Помогите мне выбрать тариф.';
72
+ readonly reply: 'Сколько разговоров вы ожидаете в месяц?';
73
+ readonly checking: 'Проверяю.';
74
+ }];
@@ -0,0 +1,29 @@
1
+ export declare const qwenProtocolFailures: readonly [{
2
+ readonly name: 'unmarked-estimation-answer';
3
+ readonly output: 'To estimate monthly conversations, look at your recent conversation totals rather than counting individual messages or visits. Check how many complete conversations your team handled in the last month (or average across a few months) and use that number as your expected monthly volume.\n■next=listen\n';
4
+ readonly reply: 'Please tell me your expected monthly conversation volume.';
5
+ }, {
6
+ readonly name: 'thinking-close-before-message';
7
+ readonly output: 'The user wants help choosing a plan. According to the instructions, when asked to choose a plan, I should first ask for expected monthly conversations. I need to ask one question at a time and never recommend a plan before knowing that volume.\n</think>\n\n■send=message\nSure! To point you to the right plan, how many conversations do you expect to handle each month?\n■next=listen';
8
+ readonly reply: 'Sure! To point you to the right plan, how many conversations do you expect to handle each month?';
9
+ }, {
10
+ readonly name: 'wrong-bullet-instead-of-send';
11
+ readonly output: '● Hello! It looks like you just sent a greeting. How can I help you today? I can assist with choosing a plan or answering questions about Cedar Desk.\n■next=listen';
12
+ readonly reply: 'Please tell me your expected monthly conversation volume.';
13
+ }, {
14
+ readonly name: 'xml-tool-call-instead-of-protocol';
15
+ readonly output: '<tool_call>\n<function=■send=message>\nI can help with that. To start, how many conversations do you expect to have each month?\n</function>\n</tool_call>';
16
+ readonly reply: 'Please tell me your expected monthly conversation volume.';
17
+ }, {
18
+ readonly name: 'repeated-messages-after-listen';
19
+ readonly output: "A conversation is a back-and-forth between a visitor and your team, not a single message or page visit. To estimate monthly conversations, look at your recent conversation totals (for example, last month's total) and use that as your baseline, adjusting if your traffic is trending up or down.\n■next=listen\n■send=message\nA conversation is a back-and-forth between a visitor and your team, not a single message or page visit. To estimate monthly conversations, look at your recent conversation totals (for example, last month's total) and use that as your baseline, adjusting if your traffic is trending up or down.\n■next=listen\n■next=listen\n■send=message\nA conversation is a back-and-forth between a visitor and your team, not a single message or page visit. To estimate monthly conversations, look at your recent conversation totals (for example, last month's total) and use that as your baseline, adjusting if your traffic is trending up or down.\n■next=listen\n■next=listen\n■send=message\nA conversation is a back-and-forth between a visitor and your team, not a single message or page visit. To estimate monthly conversations, look at your recent conversation totals (for example, last month's total) and use that as your baseline, adjusting if your traffic is trending up or down.\n■next=listen\n■next=listen";
20
+ readonly reply: 'Please tell me your expected monthly conversation volume.';
21
+ }, {
22
+ readonly name: 'premature-listen-before-thinking-close';
23
+ readonly output: 'I need to understand your expected monthly conversations before I can recommend a plan.\n\nHow many conversations do you expect to handle each month?\n■next=listen\n</think>\n\n■send=message\nI can help with that. To get started, how many conversations do you expect to handle each month?\n■next=listen';
24
+ readonly reply: 'Please tell me your expected monthly conversation volume.';
25
+ }, {
26
+ readonly name: 'draft-answer-before-explicit-send';
27
+ readonly output: 'The user wants help choosing a plan. According to the instructions, I should first ask for expected monthly conversations. Messages, visits, and conversations are different units.\nI should ask one question at a time.\n\n"Great! To point you to the right plan, could you tell me how many conversations you expect to have each month? (Just a rough estimate is fine.)"\n\nThen wait for the user.\n\n■send=message\nGreat! To point you to the right plan, could you tell me roughly how many conversations you expect to have each month?\n■next=listen';
28
+ readonly reply: 'Great! To point you to the right plan, could you tell me roughly how many conversations you expect to have each month?';
29
+ }];
@@ -9,8 +9,7 @@ type GenerateCodeProps = {
9
9
  controller: AbortController;
10
10
  metadata?: Record<string, string>;
11
11
  /**
12
- * Called for each completed `■send` block. On streaming clients this fires
13
- * while the model is still generating — messages are delivered progressively.
12
+ * Called for each send after a complete, valid response and successful transport.
14
13
  */
15
14
  onSend?: (send: ParsedSend, metadata: MessageMetadata) => Promise<void>;
16
15
  /**
@@ -24,12 +23,6 @@ type GenerateCodeProps = {
24
23
  * being generated (streaming clients only). Used to pre-warm the VM.
25
24
  */
26
25
  onRunStart?: () => void;
27
- /**
28
- * Called with the code of the first `■run` block the moment it is fully
29
- * parsed — the rest of the response (e.g. `■next`) may still be streaming
30
- * (streaming clients only). Used to start executing the code early.
31
- */
32
- onRunComplete?: (code: string) => void;
33
26
  };
34
- export declare const generateCode: ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart, onRunComplete, }: GenerateCodeProps) => Promise<void>;
27
+ export declare const generateCode: ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart, }: GenerateCodeProps) => Promise<void>;
35
28
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -124,13 +124,10 @@ type Options = Partial<Pick<Context, 'loop' | 'timeout'>> & {
124
124
  */
125
125
  maxTimeToFirstToken?: number;
126
126
  /**
127
- * Allow Cognitive to restart failed streams on another model. No buffered
128
- * delivery and no final delivery queue: delta text and completed Chat.handler
129
- * sends stream immediately during generation. A reset-only delta (restart:
130
- * true) on Chat.onMessageDelta invalidates ALL current-iteration messages,
131
- * including completed sends — consumers must retract/replace them (not safe for
132
- * irreversible transports). Only TOOL/CODE execution waits for a successful
133
- * stream. Streaming-only; defaults to false, preserving progressive sending.
127
+ * Allow Cognitive to restart a failed stream on another model. Previews remain
128
+ * live and are retracted with a restart delta before replacement output.
129
+ * Completed sends and code always wait for a valid response and successful
130
+ * transport. Streaming-only; defaults to false.
134
131
  */
135
132
  midStreamFallback?: boolean;
136
133
  /**
@@ -164,13 +164,15 @@ var tool_exports = /* @__PURE__ */ __exportAll({ Tool: () => Tool });
164
164
  *
165
165
  * Tools automatically handle:
166
166
  * - **Input validation**: Invalid inputs throw descriptive errors
167
- * - **Output validation**: Outputs are validated but invalid outputs are still returned
167
+ * - **Output descriptions**: Output schemas describe likely results; handler output is returned unchanged
168
168
  * - **Handler errors**: Exceptions in handlers are caught and can trigger retries
169
169
  * - **Type coercion**: Basic type coercion where possible
170
170
  *
171
171
  */
172
172
  var Tool = class Tool {
173
173
  _staticInputValues;
174
+ _inputSchema;
175
+ _outputSchema;
174
176
  name;
175
177
  aliases = [];
176
178
  description;
@@ -241,23 +243,14 @@ var Tool = class Tool {
241
243
  * @internal
242
244
  */
243
245
  get zInput() {
244
- let input;
245
- if (this.input) try {
246
- input = transforms.fromJSONSchema(this.input);
247
- } catch {
248
- input = transforms.fromJSONSchemaLegacy(this.input);
249
- }
250
- else input = z.any();
251
- if (!isEmpty(this._staticInputValues)) {
252
- if (z.is.zuiObject(input)) {
253
- const inputExtensions = convertObjectToZuiLiterals(this._staticInputValues);
254
- input = input.extend(inputExtensions);
255
- } else if (z.is.zuiArray(input)) {
256
- const inputExtensions = convertObjectToZuiLiterals(this._staticInputValues);
257
- input = z.array(input.element.extend(inputExtensions));
258
- } else input = convertObjectToZuiLiterals(this._staticInputValues);
259
- }
260
- return input;
246
+ const input = this._inputSchema ?? (this.input ? fromJSONSchemaCompat(this.input) : z.any());
247
+ if (isEmpty(this._staticInputValues)) return input;
248
+ const shape = this.input ? fromJSONSchemaCompat(this.input) : z.any();
249
+ let overrides;
250
+ if (z.is.zuiObject(shape)) overrides = z.object(convertObjectToZuiLiterals(this._staticInputValues)).passthrough();
251
+ else if (z.is.zuiArray(shape)) overrides = z.array(z.object(convertObjectToZuiLiterals(this._staticInputValues)).passthrough());
252
+ else overrides = convertObjectToZuiLiterals(this._staticInputValues);
253
+ return overrides.pipe(input);
261
254
  }
262
255
  /**
263
256
  * Gets the output schema for validation.
@@ -354,18 +347,8 @@ var Tool = class Tool {
354
347
  clone(props = {}) {
355
348
  try {
356
349
  var _props$input, _props$output;
357
- let zInput;
358
- if (this.input) try {
359
- zInput = transforms.fromJSONSchema(this.input);
360
- } catch {
361
- zInput = transforms.fromJSONSchemaLegacy(this.input);
362
- }
363
- let zOutput;
364
- if (this.output) try {
365
- zOutput = transforms.fromJSONSchema(this.output);
366
- } catch {
367
- zOutput = transforms.fromJSONSchemaLegacy(this.output);
368
- }
350
+ const zInput = this._inputSchema ?? (this.input ? fromJSONSchemaCompat(this.input) : void 0);
351
+ const zOutput = this._outputSchema ?? (this.output ? fromJSONSchemaCompat(this.output) : void 0);
369
352
  return new Tool({
370
353
  name: props.name ?? this.name,
371
354
  aliases: props.aliases ?? [...this.aliases],
@@ -388,7 +371,7 @@ var Tool = class Tool {
388
371
  * @param props.name - Unique tool name (must be valid TypeScript identifier)
389
372
  * @param props.description - Human-readable description for the LLM
390
373
  * @param props.input - Zui/Zod schema for input validation (optional)
391
- * @param props.output - Zui/Zod schema for output validation (optional)
374
+ * @param props.output - Zui/Zod schema describing output (optional)
392
375
  * @param props.handler - Async function that implements the tool logic
393
376
  * @param props.aliases - Alternative names for the tool (optional)
394
377
  * @param props.metadata - Additional metadata for the tool (optional)
@@ -465,21 +448,25 @@ var Tool = class Tool {
465
448
  if (props.aliases !== void 0 && !Array.isArray(props.aliases)) throw new Error(`Invalid aliases for tool ${props.name}. Expected an array, but got type "${typeof props.aliases}"`);
466
449
  if (props.aliases && props.aliases.some((alias) => !isValidIdentifier(alias))) throw new Error(`Invalid aliases for tool ${props.name}. Expected an array of valid identifiers.`);
467
450
  if (typeof props.input !== "undefined") {
468
- if (isZuiSchema(props.input)) try {
469
- this.input = transforms.toJSONSchema(props.input);
470
- } catch {
471
- this.input = transforms.toJSONSchemaLegacy(props.input);
472
- }
473
- else if (isJsonSchema(props.input)) this.input = props.input;
451
+ if (isZuiSchema(props.input)) {
452
+ this._inputSchema = props.input;
453
+ try {
454
+ this.input = transforms.toJSONSchema(props.input);
455
+ } catch {
456
+ this.input = transforms.toJSONSchemaLegacy(props.input);
457
+ }
458
+ } else if (isJsonSchema(props.input)) this.input = props.input;
474
459
  else throw new Error(`Invalid input schema for tool ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.input}"`);
475
460
  }
476
461
  if (typeof props.output !== "undefined") {
477
- if (isZuiSchema(props.output)) try {
478
- this.output = transforms.toJSONSchema(props.output);
479
- } catch {
480
- this.output = transforms.toJSONSchemaLegacy(props.output);
481
- }
482
- else if (isJsonSchema(props.output)) this.output = props.output;
462
+ if (isZuiSchema(props.output)) {
463
+ this._outputSchema = props.output;
464
+ try {
465
+ this.output = transforms.toJSONSchema(props.output);
466
+ } catch {
467
+ this.output = transforms.toJSONSchemaLegacy(props.output);
468
+ }
469
+ } else if (isJsonSchema(props.output)) this.output = props.output;
483
470
  else throw new Error(`Invalid output schema for tool ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.output}"`);
484
471
  }
485
472
  this.name = props.name;
@@ -511,7 +498,7 @@ var Tool = class Tool {
511
498
  /**
512
499
  * Executes the tool with the given input and context.
513
500
  *
514
- * This method handles input validation, retry logic, output validation, and error handling.
501
+ * This method handles input validation, retry logic, and error handling.
515
502
  * It's called internally by the LLMz execution engine when generated code calls the tool.
516
503
  *
517
504
  * @param input - Input data to pass to the tool handler
@@ -533,17 +520,16 @@ var Tool = class Tool {
533
520
  * @internal This method is primarily used internally by the LLMz execution engine
534
521
  */
535
522
  async execute(rawInput, ctx, chat) {
536
- const input = this.zInput._def.typeName === "ZodObject" ? rawInput ?? {} : rawInput;
537
- const pInput = this.zInput.safeParse(input);
523
+ const shape = this.input ? fromJSONSchemaCompat(this.input) : z.any();
524
+ const input = z.is.zuiObject(shape) ? rawInput ?? {} : rawInput;
525
+ const pInput = await this.zInput.safeParseAsync(input);
538
526
  if (!pInput.success) throw new Error(`Tool "${this.name}" received invalid input: ${pInput.error.message}`);
539
527
  let attempt = 0;
540
528
  let yieldedCount = 0;
541
529
  while (attempt < this.MAX_RETRIES) try {
542
- const result = await this._executeHandler(pInput.data, ctx, chat, yieldedCount, (n) => {
530
+ return await this._executeHandler(pInput.data, ctx, chat, yieldedCount, (n) => {
543
531
  yieldedCount = n;
544
532
  });
545
- const pOutput = this.zOutput.safeParse(result);
546
- return pOutput.success ? pOutput.data : result;
547
533
  } catch (err) {
548
534
  var _this$retry;
549
535
  if (!await ((_this$retry = this.retry) === null || _this$retry === void 0 ? void 0 : _this$retry.call(this, {
@@ -1,8 +1,8 @@
1
- const require_compiler = require("./compiler-C-OI9sim.cjs");
1
+ const require_compiler = require("./compiler-BJJUmNS9.cjs");
2
2
  const require_uniq = require("./uniq-G872RWmE.cjs");
3
- const require_utils = require("./utils-3ESwP3yg.cjs");
3
+ const require_utils = require("./utils-DGQ4sRke.cjs");
4
4
  const require_isEmpty = require("./isEmpty-LY533Wmh.cjs");
5
- const require_typings = require("./typings-3lsqCbkn.cjs");
5
+ const require_typings = require("./typings-DXJMu59O.cjs");
6
6
  let _bpinternal_zui = require("@bpinternal/zui");
7
7
  //#region src/convert.ts
8
8
  function convertObjectToZuiLiterals(obj, nested = false) {
@@ -164,13 +164,15 @@ var tool_exports = /* @__PURE__ */ require_compiler.__exportAll({ Tool: () => To
164
164
  *
165
165
  * Tools automatically handle:
166
166
  * - **Input validation**: Invalid inputs throw descriptive errors
167
- * - **Output validation**: Outputs are validated but invalid outputs are still returned
167
+ * - **Output descriptions**: Output schemas describe likely results; handler output is returned unchanged
168
168
  * - **Handler errors**: Exceptions in handlers are caught and can trigger retries
169
169
  * - **Type coercion**: Basic type coercion where possible
170
170
  *
171
171
  */
172
172
  var Tool = class Tool {
173
173
  _staticInputValues;
174
+ _inputSchema;
175
+ _outputSchema;
174
176
  name;
175
177
  aliases = [];
176
178
  description;
@@ -241,23 +243,14 @@ var Tool = class Tool {
241
243
  * @internal
242
244
  */
243
245
  get zInput() {
244
- let input;
245
- if (this.input) try {
246
- input = _bpinternal_zui.transforms.fromJSONSchema(this.input);
247
- } catch {
248
- input = _bpinternal_zui.transforms.fromJSONSchemaLegacy(this.input);
249
- }
250
- else input = _bpinternal_zui.z.any();
251
- if (!require_isEmpty.isEmpty(this._staticInputValues)) {
252
- if (_bpinternal_zui.z.is.zuiObject(input)) {
253
- const inputExtensions = convertObjectToZuiLiterals(this._staticInputValues);
254
- input = input.extend(inputExtensions);
255
- } else if (_bpinternal_zui.z.is.zuiArray(input)) {
256
- const inputExtensions = convertObjectToZuiLiterals(this._staticInputValues);
257
- input = _bpinternal_zui.z.array(input.element.extend(inputExtensions));
258
- } else input = convertObjectToZuiLiterals(this._staticInputValues);
259
- }
260
- return input;
246
+ const input = this._inputSchema ?? (this.input ? require_utils.fromJSONSchemaCompat(this.input) : _bpinternal_zui.z.any());
247
+ if (require_isEmpty.isEmpty(this._staticInputValues)) return input;
248
+ const shape = this.input ? require_utils.fromJSONSchemaCompat(this.input) : _bpinternal_zui.z.any();
249
+ let overrides;
250
+ if (_bpinternal_zui.z.is.zuiObject(shape)) overrides = _bpinternal_zui.z.object(convertObjectToZuiLiterals(this._staticInputValues)).passthrough();
251
+ else if (_bpinternal_zui.z.is.zuiArray(shape)) overrides = _bpinternal_zui.z.array(_bpinternal_zui.z.object(convertObjectToZuiLiterals(this._staticInputValues)).passthrough());
252
+ else overrides = convertObjectToZuiLiterals(this._staticInputValues);
253
+ return overrides.pipe(input);
261
254
  }
262
255
  /**
263
256
  * Gets the output schema for validation.
@@ -354,18 +347,8 @@ var Tool = class Tool {
354
347
  clone(props = {}) {
355
348
  try {
356
349
  var _props$input, _props$output;
357
- let zInput;
358
- if (this.input) try {
359
- zInput = _bpinternal_zui.transforms.fromJSONSchema(this.input);
360
- } catch {
361
- zInput = _bpinternal_zui.transforms.fromJSONSchemaLegacy(this.input);
362
- }
363
- let zOutput;
364
- if (this.output) try {
365
- zOutput = _bpinternal_zui.transforms.fromJSONSchema(this.output);
366
- } catch {
367
- zOutput = _bpinternal_zui.transforms.fromJSONSchemaLegacy(this.output);
368
- }
350
+ const zInput = this._inputSchema ?? (this.input ? require_utils.fromJSONSchemaCompat(this.input) : void 0);
351
+ const zOutput = this._outputSchema ?? (this.output ? require_utils.fromJSONSchemaCompat(this.output) : void 0);
369
352
  return new Tool({
370
353
  name: props.name ?? this.name,
371
354
  aliases: props.aliases ?? [...this.aliases],
@@ -388,7 +371,7 @@ var Tool = class Tool {
388
371
  * @param props.name - Unique tool name (must be valid TypeScript identifier)
389
372
  * @param props.description - Human-readable description for the LLM
390
373
  * @param props.input - Zui/Zod schema for input validation (optional)
391
- * @param props.output - Zui/Zod schema for output validation (optional)
374
+ * @param props.output - Zui/Zod schema describing output (optional)
392
375
  * @param props.handler - Async function that implements the tool logic
393
376
  * @param props.aliases - Alternative names for the tool (optional)
394
377
  * @param props.metadata - Additional metadata for the tool (optional)
@@ -465,21 +448,25 @@ var Tool = class Tool {
465
448
  if (props.aliases !== void 0 && !Array.isArray(props.aliases)) throw new Error(`Invalid aliases for tool ${props.name}. Expected an array, but got type "${typeof props.aliases}"`);
466
449
  if (props.aliases && props.aliases.some((alias) => !require_utils.isValidIdentifier(alias))) throw new Error(`Invalid aliases for tool ${props.name}. Expected an array of valid identifiers.`);
467
450
  if (typeof props.input !== "undefined") {
468
- if (require_utils.isZuiSchema(props.input)) try {
469
- this.input = _bpinternal_zui.transforms.toJSONSchema(props.input);
470
- } catch {
471
- this.input = _bpinternal_zui.transforms.toJSONSchemaLegacy(props.input);
472
- }
473
- else if (require_utils.isJsonSchema(props.input)) this.input = props.input;
451
+ if (require_utils.isZuiSchema(props.input)) {
452
+ this._inputSchema = props.input;
453
+ try {
454
+ this.input = _bpinternal_zui.transforms.toJSONSchema(props.input);
455
+ } catch {
456
+ this.input = _bpinternal_zui.transforms.toJSONSchemaLegacy(props.input);
457
+ }
458
+ } else if (require_utils.isJsonSchema(props.input)) this.input = props.input;
474
459
  else throw new Error(`Invalid input schema for tool ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.input}"`);
475
460
  }
476
461
  if (typeof props.output !== "undefined") {
477
- if (require_utils.isZuiSchema(props.output)) try {
478
- this.output = _bpinternal_zui.transforms.toJSONSchema(props.output);
479
- } catch {
480
- this.output = _bpinternal_zui.transforms.toJSONSchemaLegacy(props.output);
481
- }
482
- else if (require_utils.isJsonSchema(props.output)) this.output = props.output;
462
+ if (require_utils.isZuiSchema(props.output)) {
463
+ this._outputSchema = props.output;
464
+ try {
465
+ this.output = _bpinternal_zui.transforms.toJSONSchema(props.output);
466
+ } catch {
467
+ this.output = _bpinternal_zui.transforms.toJSONSchemaLegacy(props.output);
468
+ }
469
+ } else if (require_utils.isJsonSchema(props.output)) this.output = props.output;
483
470
  else throw new Error(`Invalid output schema for tool ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.output}"`);
484
471
  }
485
472
  this.name = props.name;
@@ -511,7 +498,7 @@ var Tool = class Tool {
511
498
  /**
512
499
  * Executes the tool with the given input and context.
513
500
  *
514
- * This method handles input validation, retry logic, output validation, and error handling.
501
+ * This method handles input validation, retry logic, and error handling.
515
502
  * It's called internally by the LLMz execution engine when generated code calls the tool.
516
503
  *
517
504
  * @param input - Input data to pass to the tool handler
@@ -533,17 +520,16 @@ var Tool = class Tool {
533
520
  * @internal This method is primarily used internally by the LLMz execution engine
534
521
  */
535
522
  async execute(rawInput, ctx, chat) {
536
- const input = this.zInput._def.typeName === "ZodObject" ? rawInput ?? {} : rawInput;
537
- const pInput = this.zInput.safeParse(input);
523
+ const shape = this.input ? require_utils.fromJSONSchemaCompat(this.input) : _bpinternal_zui.z.any();
524
+ const input = _bpinternal_zui.z.is.zuiObject(shape) ? rawInput ?? {} : rawInput;
525
+ const pInput = await this.zInput.safeParseAsync(input);
538
526
  if (!pInput.success) throw new Error(`Tool "${this.name}" received invalid input: ${pInput.error.message}`);
539
527
  let attempt = 0;
540
528
  let yieldedCount = 0;
541
529
  while (attempt < this.MAX_RETRIES) try {
542
- const result = await this._executeHandler(pInput.data, ctx, chat, yieldedCount, (n) => {
530
+ return await this._executeHandler(pInput.data, ctx, chat, yieldedCount, (n) => {
543
531
  yieldedCount = n;
544
532
  });
545
- const pOutput = this.zOutput.safeParse(result);
546
- return pOutput.success ? pOutput.data : result;
547
533
  } catch (err) {
548
534
  var _this$retry;
549
535
  if (!await ((_this$retry = this.retry) === null || _this$retry === void 0 ? void 0 : _this$retry.call(this, {
package/dist/tool.d.ts CHANGED
@@ -200,13 +200,15 @@ export declare namespace Tool {
200
200
  *
201
201
  * Tools automatically handle:
202
202
  * - **Input validation**: Invalid inputs throw descriptive errors
203
- * - **Output validation**: Outputs are validated but invalid outputs are still returned
203
+ * - **Output descriptions**: Output schemas describe likely results; handler output is returned unchanged
204
204
  * - **Handler errors**: Exceptions in handlers are caught and can trigger retries
205
205
  * - **Type coercion**: Basic type coercion where possible
206
206
  *
207
207
  */
208
208
  export declare class Tool<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType> implements Serializable<Tool.JSON> {
209
209
  private _staticInputValues?;
210
+ private _inputSchema?;
211
+ private _outputSchema?;
210
212
  name: string;
211
213
  aliases: string[];
212
214
  description?: string;
@@ -364,7 +366,7 @@ export declare class Tool<I extends z.ZodType = z.ZodType, O extends z.ZodType =
364
366
  * @param props.name - Unique tool name (must be valid TypeScript identifier)
365
367
  * @param props.description - Human-readable description for the LLM
366
368
  * @param props.input - Zui/Zod schema for input validation (optional)
367
- * @param props.output - Zui/Zod schema for output validation (optional)
369
+ * @param props.output - Zui/Zod schema describing output (optional)
368
370
  * @param props.handler - Async function that implements the tool logic
369
371
  * @param props.aliases - Alternative names for the tool (optional)
370
372
  * @param props.metadata - Additional metadata for the tool (optional)
@@ -448,7 +450,7 @@ export declare class Tool<I extends z.ZodType = z.ZodType, O extends z.ZodType =
448
450
  /**
449
451
  * Executes the tool with the given input and context.
450
452
  *
451
- * This method handles input validation, retry logic, output validation, and error handling.
453
+ * This method handles input validation, retry logic, and error handling.
452
454
  * It's called internally by the LLMz execution engine when generated code calls the tool.
453
455
  *
454
456
  * @param input - Input data to pass to the tool handler
@@ -126,9 +126,9 @@ function truncateWrappedContent({ messages, tokenLimit, throwOnFailure = true })
126
126
  * After { content: 'content', tokens: 10, truncatable: false }
127
127
  */
128
128
  const parts = [];
129
- for (const msg of messages) {
129
+ const contents = messages.flatMap((message) => typeof message.content === "string" ? [message.content] : (message.content ?? []).flatMap((part) => part.type === "text" ? [part.text ?? ""] : []));
130
+ for (const content of contents) {
130
131
  const current = [];
131
- const content = typeof msg.content === "string" ? msg.content : "";
132
132
  let match;
133
133
  const parser = new _MessageContentParser();
134
134
  while ((match = parser.parse(content)) !== null) {
@@ -190,11 +190,16 @@ function truncateWrappedContent({ messages, tokenLimit, throwOnFailure = true })
190
190
  biggest.tokens -= toRemove;
191
191
  currentCount -= toRemove;
192
192
  }
193
- return messages.map((msg, i) => {
194
- const p = parts[i];
193
+ let textIndex = 0;
194
+ const renderText = () => _renderRemainingWrappers(parts[textIndex++].map((part) => part.content).join(""));
195
+ return messages.map((message) => {
196
+ var _message$content;
195
197
  return {
196
- ...msg,
197
- content: typeof msg.content === "string" ? _renderRemainingWrappers(p.map((part) => part.content).join("")) : msg.content
198
+ ...message,
199
+ content: typeof message.content === "string" ? renderText() : ((_message$content = message.content) === null || _message$content === void 0 ? void 0 : _message$content.map((part) => part.type === "text" ? {
200
+ ...part,
201
+ text: renderText()
202
+ } : part)) ?? message.content
198
203
  };
199
204
  });
200
205
  }
@@ -1,5 +1,5 @@
1
- const require_compiler = require("./compiler-C-OI9sim.cjs");
2
- const require_utils = require("./utils-3ESwP3yg.cjs");
1
+ const require_compiler = require("./compiler-BJJUmNS9.cjs");
2
+ const require_utils = require("./utils-DGQ4sRke.cjs");
3
3
  //#region src/truncator.ts
4
4
  var truncator_exports = /* @__PURE__ */ require_compiler.__exportAll({
5
5
  stripTruncationTags: () => stripTruncationTags,
@@ -126,9 +126,9 @@ function truncateWrappedContent({ messages, tokenLimit, throwOnFailure = true })
126
126
  * After { content: 'content', tokens: 10, truncatable: false }
127
127
  */
128
128
  const parts = [];
129
- for (const msg of messages) {
129
+ const contents = messages.flatMap((message) => typeof message.content === "string" ? [message.content] : (message.content ?? []).flatMap((part) => part.type === "text" ? [part.text ?? ""] : []));
130
+ for (const content of contents) {
130
131
  const current = [];
131
- const content = typeof msg.content === "string" ? msg.content : "";
132
132
  let match;
133
133
  const parser = new _MessageContentParser();
134
134
  while ((match = parser.parse(content)) !== null) {
@@ -190,11 +190,16 @@ function truncateWrappedContent({ messages, tokenLimit, throwOnFailure = true })
190
190
  biggest.tokens -= toRemove;
191
191
  currentCount -= toRemove;
192
192
  }
193
- return messages.map((msg, i) => {
194
- const p = parts[i];
193
+ let textIndex = 0;
194
+ const renderText = () => _renderRemainingWrappers(parts[textIndex++].map((part) => part.content).join(""));
195
+ return messages.map((message) => {
196
+ var _message$content;
195
197
  return {
196
- ...msg,
197
- content: typeof msg.content === "string" ? _renderRemainingWrappers(p.map((part) => part.content).join("")) : msg.content
198
+ ...message,
199
+ content: typeof message.content === "string" ? renderText() : ((_message$content = message.content) === null || _message$content === void 0 ? void 0 : _message$content.map((part) => part.type === "text" ? {
200
+ ...part,
201
+ text: renderText()
202
+ } : part)) ?? message.content
198
203
  };
199
204
  });
200
205
  }
@@ -1,5 +1,5 @@
1
- const require_compiler = require("./compiler-C-OI9sim.cjs");
2
- const require_utils = require("./utils-3ESwP3yg.cjs");
1
+ const require_compiler = require("./compiler-BJJUmNS9.cjs");
2
+ const require_utils = require("./utils-DGQ4sRke.cjs");
3
3
  const require_errors = require("./errors-C962uJdS.cjs");
4
4
  let _bpinternal_zui = require("@bpinternal/zui");
5
5
  //#region src/typings-formatter.ts
@@ -1,4 +1,4 @@
1
- const require_compiler = require("./compiler-C-OI9sim.cjs");
1
+ const require_compiler = require("./compiler-BJJUmNS9.cjs");
2
2
  const require__baseIteratee = require("./_baseIteratee-CF4qP2a8.cjs");
3
3
  const require__getPrototype = require("./_getPrototype-DQDlNVVM.cjs");
4
4
  let _bpinternal_zui = require("@bpinternal/zui");