llmz 0.0.13 → 0.0.15

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 (52) hide show
  1. package/CLAUDE.md +363 -0
  2. package/README.md +61 -34
  3. package/dist/abort-signal.d.ts +40 -0
  4. package/dist/chat.d.ts +325 -0
  5. package/dist/{chunk-KH6JQYQA.js → chunk-2D2DE7CD.js} +2 -2
  6. package/dist/chunk-3G3BS5IA.cjs +256 -0
  7. package/dist/{chunk-SNDVQU5A.js → chunk-3JYCCI4S.js} +1 -1
  8. package/dist/chunk-A7QHWVD7.js +493 -0
  9. package/dist/{chunk-IH2WQFO5.js → chunk-EE6NVDID.js} +1 -1
  10. package/dist/{chunk-4L6D2A6O.cjs → chunk-FZJHYLM2.cjs} +14 -14
  11. package/dist/{chunk-JGVAZO4X.cjs → chunk-GZPN7RGH.cjs} +2 -2
  12. package/dist/{chunk-SHJDRZF5.cjs → chunk-PIDLNYIP.cjs} +25 -25
  13. package/dist/{chunk-PRVFVXT4.js → chunk-RBRTK37G.js} +383 -4
  14. package/dist/{chunk-HJKOSEH2.cjs → chunk-TCRRSS44.cjs} +397 -18
  15. package/dist/chunk-VPTFUOIK.js +256 -0
  16. package/dist/{chunk-276Q6EWP.cjs → chunk-WHNOR4ZU.cjs} +3 -0
  17. package/dist/chunk-XGJOEQMW.cjs +493 -0
  18. package/dist/{chunk-4MNIJGK6.js → chunk-ZORRILUV.js} +3 -0
  19. package/dist/context.d.ts +412 -4
  20. package/dist/{dual-modes-T53P72CH.js → dual-modes-7FI4T35O.js} +3 -3
  21. package/dist/{dual-modes-VLIGPIHX.cjs → dual-modes-OFHV2C3X.cjs} +4 -4
  22. package/dist/exit-XAYKJ6TR.cjs +8 -0
  23. package/dist/{exit-YORW76T3.js → exit-YLO7BY7Z.js} +2 -2
  24. package/dist/exit.d.ts +369 -2
  25. package/dist/index.cjs +253 -28
  26. package/dist/index.d.ts +71 -1
  27. package/dist/index.js +242 -17
  28. package/dist/{llmz-ROOX7RYI.js → llmz-67EZPJ4E.js} +113 -39
  29. package/dist/{llmz-QLZBDG2Z.cjs → llmz-WVNKAMCP.cjs} +123 -49
  30. package/dist/llmz.d.ts +142 -5
  31. package/dist/objects.d.ts +350 -1
  32. package/dist/result.d.ts +809 -6
  33. package/dist/snapshots.d.ts +181 -1
  34. package/dist/{tool-QP4MVRWI.cjs → tool-O4SFRIE4.cjs} +4 -4
  35. package/dist/{tool-N6ODRRGH.js → tool-PCOYOCRH.js} +3 -3
  36. package/dist/tool.d.ts +470 -2
  37. package/dist/{truncator-IY2MXOMC.js → truncator-BSP6PQPC.js} +2 -2
  38. package/dist/truncator-W3NXBLYJ.cjs +10 -0
  39. package/dist/types.d.ts +3 -0
  40. package/dist/{typings-GDMY6VY2.js → typings-WYHEFCYB.js} +2 -2
  41. package/dist/{typings-2CPHOFDN.cjs → typings-Y45GMPZT.cjs} +3 -3
  42. package/dist/utils-L5QAQXV2.cjs +39 -0
  43. package/dist/{utils-N24IHDFA.js → utils-RQHQ2KOG.js} +1 -1
  44. package/docs/TODO.md +919 -0
  45. package/package.json +3 -3
  46. package/dist/chunk-C6WNNTEV.cjs +0 -212
  47. package/dist/chunk-GWFYZDUR.cjs +0 -105
  48. package/dist/chunk-JAGB2AOU.js +0 -212
  49. package/dist/chunk-JMSZKB4T.js +0 -105
  50. package/dist/exit-TRXEU4OU.cjs +0 -8
  51. package/dist/truncator-DUMWEGQO.cjs +0 -10
  52. package/dist/utils-A7WNEFTA.cjs +0 -39
package/dist/chat.d.ts CHANGED
@@ -3,15 +3,340 @@ import { Context } from './context.js';
3
3
  import { ValueOrGetter } from './getter.js';
4
4
  import { ExecutionResult } from './result.js';
5
5
  import { TranscriptArray, Transcript } from './transcript.js';
6
+ /**
7
+ * Function type for handling messages sent from the agent to the user.
8
+ *
9
+ * The handler receives rendered components from the agent and is responsible for
10
+ * presenting them to the user through the appropriate interface (CLI, web UI, mobile app, etc.).
11
+ * This is how the agent communicates with the user.
12
+ *
13
+ * @param input - The rendered component to display to the user
14
+ * @returns Promise that resolves when the message has been handled
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const handler: MessageHandler = async (input) => {
19
+ * if (isComponent(input, DefaultComponents.Text)) {
20
+ * console.log('Agent:', input.children.join(''))
21
+ * } else if (isComponent(input, DefaultComponents.Button)) {
22
+ * console.log('Button:', input.props.label)
23
+ * }
24
+ * }
25
+ * ```
26
+ */
6
27
  export type MessageHandler = (input: RenderedComponent) => Promise<void> | void;
28
+ /**
29
+ * Base class for implementing chat interfaces in LLMz agents.
30
+ *
31
+ * The Chat class provides the foundation for interactive conversational agents by defining
32
+ * how agents communicate with users. It manages the conversation transcript, available UI
33
+ * components, and message handling. This is the bridge between the agent's generated code
34
+ * and your user interface.
35
+ *
36
+ * ## Key Concepts
37
+ *
38
+ * **Handler Function**: The core method that receives agent messages (rendered components)
39
+ * and displays them to the user. This is called every time the agent wants to communicate.
40
+ *
41
+ * **Transcript**: An up-to-date conversation history that is evaluated at each iteration.
42
+ * The transcript must reflect the complete conversation state as the agent uses it to
43
+ * understand context and generate appropriate responses.
44
+ *
45
+ * **Components**: The UI elements available to the agent for creating rich interactive
46
+ * experiences (text, buttons, images, cards, etc.).
47
+ *
48
+ * ## Implementation Requirements
49
+ *
50
+ * To create a functional chat interface, you must:
51
+ * 1. Implement the MessageHandler to display agent messages to users
52
+ * 2. Maintain an accurate transcript of the conversation
53
+ * 3. Provide the available UI components (typically includes DefaultComponents)
54
+ * 4. Optional: Override onExecutionDone() to handle execution completion
55
+ *
56
+ * ## Basic Implementation
57
+ *
58
+ * ```typescript
59
+ * import { Chat, DefaultComponents, isComponent } from 'llmz'
60
+ *
61
+ * class MyChat extends Chat {
62
+ * private messages: Array<{role: 'user' | 'assistant', content: string}> = []
63
+ *
64
+ * constructor() {
65
+ * super({
66
+ * // Handle agent messages - this is called for every agent output
67
+ * handler: async (input) => {
68
+ * if (isComponent(input, DefaultComponents.Text)) {
69
+ * const text = input.children.join('')
70
+ * console.log('Agent:', text)
71
+ * this.messages.push({ role: 'assistant', content: text })
72
+ * } else if (isComponent(input, DefaultComponents.Button)) {
73
+ * console.log('Button:', input.props.label)
74
+ * }
75
+ * },
76
+ *
77
+ * // Provide available components - agent can use these in generated code
78
+ * components: [DefaultComponents.Text, DefaultComponents.Button],
79
+ *
80
+ * // Return current transcript - evaluated at each iteration
81
+ * transcript: () => this.messages,
82
+ * })
83
+ * }
84
+ *
85
+ * // Add user message to transcript
86
+ * addUserMessage(content: string) {
87
+ * this.messages.push({ role: 'user', content })
88
+ * }
89
+ * }
90
+ *
91
+ * // Usage
92
+ * const chat = new MyChat()
93
+ * chat.addUserMessage('Hello!')
94
+ *
95
+ * const result = await execute({
96
+ * instructions: 'You are a helpful assistant',
97
+ * chat, // Enable chat mode
98
+ * client,
99
+ * })
100
+ * ```
101
+ *
102
+ * ## Advanced Implementation (CLIChat Example)
103
+ *
104
+ * ```typescript
105
+ * import { Chat, DefaultComponents, ListenExit } from 'llmz'
106
+ *
107
+ * class CLIChat extends Chat {
108
+ * public transcript: Array<{role: 'user' | 'assistant', content: string}> = []
109
+ * private buttons: string[] = []
110
+ * public result?: ExecutionResult
111
+ *
112
+ * constructor() {
113
+ * super({
114
+ * // Dynamic component list with custom renderers
115
+ * components: () => [
116
+ * DefaultComponents.Text,
117
+ * DefaultComponents.Button,
118
+ * ...this.customComponents
119
+ * ],
120
+ *
121
+ * // Dynamic transcript access
122
+ * transcript: () => this.transcript,
123
+ *
124
+ * // Sophisticated message handling
125
+ * handler: async (input) => {
126
+ * if (isComponent(input, DefaultComponents.Text)) {
127
+ * const text = input.children.join('')
128
+ * console.log('🤖 Agent:', text)
129
+ * this.transcript.push({ role: 'assistant', content: text })
130
+ * } else if (isComponent(input, DefaultComponents.Button)) {
131
+ * this.buttons.push(input.props.label)
132
+ * }
133
+ * },
134
+ * })
135
+ * }
136
+ *
137
+ * // Handle execution completion
138
+ * onExecutionDone(result: ExecutionResult) {
139
+ * this.result = result
140
+ * }
141
+ *
142
+ * // Check if agent is waiting for user input
143
+ * isWaitingForInput(): boolean {
144
+ * return this.result?.is(ListenExit) ?? false
145
+ * }
146
+ *
147
+ * // Conversation loop
148
+ * async iterate(): Promise<boolean> {
149
+ * if (this.isWaitingForInput()) {
150
+ * const userInput = await this.promptUser()
151
+ * this.transcript.push({ role: 'user', content: userInput })
152
+ * return true // Continue conversation
153
+ * }
154
+ * return false // End conversation
155
+ * }
156
+ * }
157
+ * ```
158
+ *
159
+ * ## Component System
160
+ *
161
+ * The agent generates JSX code using available components:
162
+ *
163
+ * ```typescript
164
+ * // Agent generates this TSX code:
165
+ * yield <Text>Welcome! Choose an option:</Text>
166
+ * yield <Button action="postback" label="Get Help" value="help" />
167
+ * yield <Button action="postback" label="Contact Sales" value="sales" />
168
+ *
169
+ * // Your handler receives these as RenderedComponent objects
170
+ * ```
171
+ *
172
+ * ## Transcript Management
173
+ *
174
+ * The transcript is critical for agent context and must be kept up-to-date:
175
+ *
176
+ * ```typescript
177
+ * // ❌ Bad - static transcript
178
+ * transcript: [{ role: 'user', content: 'Hello' }]
179
+ *
180
+ * // ✅ Good - dynamic transcript that reflects current state
181
+ * transcript: () => this.messages
182
+ *
183
+ * // The transcript is evaluated at each iteration, so the agent
184
+ * // always sees the current conversation state
185
+ * ```
186
+ *
187
+ * ## Custom Components
188
+ *
189
+ * Extend the UI with custom components for your specific use case:
190
+ *
191
+ * ```typescript
192
+ * import { Component } from 'llmz'
193
+ *
194
+ * const ProductCard = new Component({
195
+ * type: 'leaf',
196
+ * name: 'ProductCard',
197
+ * leaf: {
198
+ * props: z.object({
199
+ * name: z.string(),
200
+ * price: z.number(),
201
+ * imageUrl: z.string(),
202
+ * })
203
+ * }
204
+ * })
205
+ *
206
+ * class ShoppingChat extends Chat {
207
+ * constructor() {
208
+ * super({
209
+ * components: [
210
+ * ...DefaultComponents,
211
+ * ProductCard, // Add custom component
212
+ * ],
213
+ * handler: async (input) => {
214
+ * if (isComponent(input, ProductCard)) {
215
+ * // Handle custom component rendering
216
+ * this.renderProduct(input.props)
217
+ * }
218
+ * // ... handle other components
219
+ * },
220
+ * })
221
+ * }
222
+ * }
223
+ * ```
224
+ *
225
+ * @see {@link DefaultComponents} For standard UI components
226
+ * @see {@link https://github.com/botpress/botpress/blob/master/packages/llmz/examples/utils/cli-chat.ts} Complete CLIChat implementation
227
+ */
7
228
  export declare class Chat {
8
229
  readonly handler: MessageHandler;
9
230
  readonly transcript: ValueOrGetter<TranscriptArray, Context>;
10
231
  readonly components: ValueOrGetter<Component[], Context>;
232
+ /**
233
+ * Creates a new Chat instance.
234
+ *
235
+ * @param props - Chat configuration
236
+ * @param props.handler - Function to handle agent messages (called for every agent output)
237
+ * @param props.components - Available UI components (static array or dynamic function)
238
+ * @param props.transcript - Conversation history (static array or dynamic function, defaults to empty)
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * // Basic chat with static configuration
243
+ * const chat = new Chat({
244
+ * handler: async (input) => {
245
+ * if (isComponent(input, DefaultComponents.Text)) {
246
+ * console.log('Agent:', input.children.join(''))
247
+ * }
248
+ * },
249
+ * components: [DefaultComponents.Text, DefaultComponents.Button],
250
+ * transcript: [
251
+ * { role: 'user', content: 'Hello', timestamp: Date.now() }
252
+ * ],
253
+ * })
254
+ * ```
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * // Dynamic chat with functions for real-time updates
259
+ * class MyChat extends Chat {
260
+ * private messages: Transcript.Message[] = []
261
+ *
262
+ * constructor() {
263
+ * super({
264
+ * handler: (input) => this.handleMessage(input),
265
+ *
266
+ * // Dynamic components - can change during execution
267
+ * components: () => [
268
+ * DefaultComponents.Text,
269
+ * DefaultComponents.Button,
270
+ * ...this.getCustomComponents()
271
+ * ],
272
+ *
273
+ * // Dynamic transcript - always reflects current state
274
+ * transcript: () => this.messages,
275
+ * })
276
+ * }
277
+ * }
278
+ * ```
279
+ */
11
280
  constructor(props: {
12
281
  handler: MessageHandler;
13
282
  components: ValueOrGetter<Component[], Context>;
14
283
  transcript?: ValueOrGetter<Transcript.Message[], Context>;
15
284
  });
285
+ /**
286
+ * Called when an execution cycle completes, regardless of the outcome.
287
+ *
288
+ * Override this method to handle execution results, manage conversation flow,
289
+ * or perform cleanup tasks. This is called after each `execute()` call completes,
290
+ * whether it succeeds, fails, or is interrupted.
291
+ *
292
+ * @param result - The execution result containing status, iterations, and exit information
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * class MyChat extends Chat {
297
+ * public result?: ExecutionResult
298
+ *
299
+ * onExecutionDone(result: ExecutionResult) {
300
+ * // Store result for conversation flow control
301
+ * this.result = result
302
+ *
303
+ * // Handle different result types
304
+ * if (result.isSuccess()) {
305
+ * console.log('✅ Execution completed successfully')
306
+ * console.log('Exit:', result.output.exit_name)
307
+ * } else if (result.isError()) {
308
+ * console.error('❌ Execution failed:', result.output.error)
309
+ * } else if (result.isInterrupted()) {
310
+ * console.log('⏸️ Execution interrupted (partial result)')
311
+ * }
312
+ * }
313
+ *
314
+ * // Use stored result for conversation flow
315
+ * isWaitingForInput(): boolean {
316
+ * return this.result?.is(ListenExit) ?? false
317
+ * }
318
+ * }
319
+ * ```
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * // CLIChat implementation example
324
+ * class CLIChat extends Chat {
325
+ * public status?: IterationStatus
326
+ * public result?: ExecutionResult
327
+ *
328
+ * onExecutionDone(result: ExecutionResult) {
329
+ * this.result = result
330
+ * this.status = result.iterations.at(-1)?.status
331
+ * }
332
+ *
333
+ * // Check if agent exited with specific exit type
334
+ * hasExitedWith<R>(exit: Exit<R>): boolean {
335
+ * return this.status?.type === 'exit_success' &&
336
+ * this.status.exit_success.exit_name === exit.name
337
+ * }
338
+ * }
339
+ * ```
340
+ */
16
341
  onExecutionDone(_result: ExecutionResult): void;
17
342
  }
@@ -6,11 +6,11 @@ import {
6
6
  } from "./chunk-GGWM6X2K.js";
7
7
  import {
8
8
  wrapContent
9
- } from "./chunk-SNDVQU5A.js";
9
+ } from "./chunk-3JYCCI4S.js";
10
10
  import {
11
11
  escapeString,
12
12
  getTokenizer
13
- } from "./chunk-4MNIJGK6.js";
13
+ } from "./chunk-ZORRILUV.js";
14
14
  import {
15
15
  chain_default,
16
16
  countBy_default,
@@ -0,0 +1,256 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class;
2
+
3
+
4
+
5
+ var _chunkWHNOR4ZUcjs = require('./chunk-WHNOR4ZU.cjs');
6
+
7
+
8
+ var _chunkUQOBUJIQcjs = require('./chunk-UQOBUJIQ.cjs');
9
+
10
+ // src/exit.ts
11
+ var _zui = require('@bpinternal/zui');
12
+ var Exit = (_class = class _Exit {
13
+ /** The primary name of the exit (used in return statements) */
14
+
15
+ /** Alternative names that can be used to reference this exit */
16
+ __init() {this.aliases = []}
17
+ /** Human-readable description of when this exit should be used */
18
+
19
+ /** Additional metadata for orchestration and custom logic */
20
+
21
+ /** JSON Schema for validating exit result data */
22
+
23
+ /**
24
+ * Returns the Zod schema equivalent of the JSON schema (if available).
25
+ * Used internally for validation and type inference.
26
+ */
27
+ get zSchema() {
28
+ return this.schema ? _zui.transforms.fromJSONSchemaLegacy(this.schema) : void 0;
29
+ }
30
+ /**
31
+ * Renames the exit and updates aliases accordingly.
32
+ *
33
+ * @param name - The new name for the exit (must be a valid identifier)
34
+ * @returns This exit instance for chaining
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const exit = new Exit({ name: 'old_name', description: 'Test exit' })
39
+ * exit.rename('new_name')
40
+ * console.log(exit.name) // 'new_name'
41
+ * ```
42
+ */
43
+ rename(name) {
44
+ const before = this.name;
45
+ if (!_chunkWHNOR4ZUcjs.isValidIdentifier.call(void 0, name)) {
46
+ throw new Error(
47
+ `Invalid name for exit ${name}. An exit name must start with a letter and contain only letters, numbers, and underscores. It must be 1-50 characters long.`
48
+ );
49
+ }
50
+ this.name = name;
51
+ this.aliases = _chunkUQOBUJIQcjs.uniq_default.call(void 0, [name, ...this.aliases.map((alias) => alias === before ? name : alias)]);
52
+ return this;
53
+ }
54
+ /**
55
+ * Creates a deep copy of this exit.
56
+ *
57
+ * The clone is completely independent and can be modified without affecting
58
+ * the original exit. This is useful for creating variations of existing exits.
59
+ *
60
+ * @returns A new Exit instance with the same configuration
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const originalExit = new Exit({
65
+ * name: 'base',
66
+ * description: 'Base exit',
67
+ * schema: z.object({ status: z.string() }),
68
+ * })
69
+ *
70
+ * const customExit = originalExit.clone().rename('custom')
71
+ * // customExit is independent of originalExit
72
+ * ```
73
+ */
74
+ clone() {
75
+ return new _Exit({
76
+ name: this.name,
77
+ aliases: [...this.aliases],
78
+ description: this.description,
79
+ metadata: JSON.parse(JSON.stringify(this.metadata)),
80
+ schema: this.zSchema
81
+ });
82
+ }
83
+ /**
84
+ * Type guard to check if this exit matches another exit by name.
85
+ *
86
+ * Used internally for type narrowing and exit comparison.
87
+ *
88
+ * @param exit - The exit to compare against
89
+ * @returns True if the exits have the same name
90
+ */
91
+ is(exit) {
92
+ return this.name === exit.name;
93
+ }
94
+ /**
95
+ * Type guard to check if an ExitResult matches this exit.
96
+ *
97
+ * @param result - The exit result to check
98
+ * @returns True if the result was created by this exit
99
+ */
100
+ match(result) {
101
+ return result.exit instanceof _Exit && this.name === result.exit.name;
102
+ }
103
+ /**
104
+ * Serializes this exit to a JSON-compatible object.
105
+ *
106
+ * @returns JSON representation of the exit
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const exit = new Exit({
111
+ * name: 'complete',
112
+ * description: 'Task completed successfully',
113
+ * })
114
+ *
115
+ * console.log(exit.toJSON())
116
+ * // { name: 'complete', aliases: [], description: 'Task completed successfully', metadata: {}, schema: undefined }
117
+ * ```
118
+ */
119
+ toJSON() {
120
+ return {
121
+ name: this.name,
122
+ aliases: [...this.aliases],
123
+ description: this.description,
124
+ metadata: { ...this.metadata },
125
+ schema: this.schema
126
+ };
127
+ }
128
+ /**
129
+ * Creates a new Exit instance.
130
+ *
131
+ * @param props - Exit configuration
132
+ * @param props.name - Primary name for the exit (must be valid identifier)
133
+ * @param props.description - Human-readable description of the exit's purpose
134
+ * @param props.aliases - Alternative names that can be used to reference this exit
135
+ * @param props.metadata - Additional data for orchestration and custom logic
136
+ * @param props.schema - Zod schema for validating exit result data
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * // Simple exit without data validation
141
+ * const exit = new Exit({
142
+ * name: 'complete',
143
+ * description: 'Task completed successfully',
144
+ * })
145
+ * ```
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // Exit with typed result data
150
+ * const approval = new Exit({
151
+ * name: 'approved',
152
+ * description: 'Request approved by system',
153
+ * schema: z.object({
154
+ * amount: z.number().positive(),
155
+ * reference: z.string().min(1),
156
+ * timestamp: z.date().default(() => new Date()),
157
+ * }),
158
+ * })
159
+ * ```
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * // Exit with aliases and metadata
164
+ * const handoff = new Exit({
165
+ * name: 'handoff_support',
166
+ * aliases: ['escalate', 'transfer'],
167
+ * description: 'Transfer to human support agent',
168
+ * metadata: {
169
+ * department: 'customer_service',
170
+ * priority: 'high',
171
+ * },
172
+ * schema: z.object({
173
+ * reason: z.string(),
174
+ * customerData: z.record(z.any()),
175
+ * }),
176
+ * })
177
+ * ```
178
+ */
179
+ constructor(props) {;_class.prototype.__init.call(this);
180
+ if (!_chunkWHNOR4ZUcjs.isValidIdentifier.call(void 0, props.name)) {
181
+ throw new Error(
182
+ `Invalid name for exit ${props.name}. A exit name must start with a letter and contain only letters, numbers, and underscores. It must be 1-50 characters long.`
183
+ );
184
+ }
185
+ if (typeof props.description !== "string" || props.description.trim().length === 0) {
186
+ throw new Error(
187
+ `Invalid description for exit ${props.name}. Expected a non-empty string, but got type "${typeof props.description}"`
188
+ );
189
+ }
190
+ if (props.metadata !== void 0 && typeof props.metadata !== "object") {
191
+ throw new Error(
192
+ `Invalid metadata for exit ${props.name}. Expected an object, but got type "${typeof props.metadata}"`
193
+ );
194
+ }
195
+ if (props.aliases !== void 0 && !Array.isArray(props.aliases)) {
196
+ throw new Error(
197
+ `Invalid aliases for exit ${props.name}. Expected an array, but got type "${typeof props.aliases}"`
198
+ );
199
+ }
200
+ if (props.aliases && props.aliases.some((alias) => !_chunkWHNOR4ZUcjs.isValidIdentifier.call(void 0, alias))) {
201
+ throw new Error(`Invalid aliases for exit ${props.name}. Expected an array of valid identifiers.`);
202
+ }
203
+ if (typeof props.schema !== "undefined") {
204
+ if (_chunkWHNOR4ZUcjs.isZuiSchema.call(void 0, props.schema)) {
205
+ this.schema = _zui.transforms.toJSONSchemaLegacy(props.schema);
206
+ } else if (_chunkWHNOR4ZUcjs.isJsonSchema.call(void 0, props.schema)) {
207
+ this.schema = props.schema;
208
+ } else {
209
+ throw new Error(
210
+ `Invalid input schema for exit ${props.name}. Expected a ZodType or JSONSchema, but got type "${typeof props.schema}"`
211
+ );
212
+ }
213
+ }
214
+ this.name = props.name;
215
+ this.aliases = _chunkUQOBUJIQcjs.uniq_default.call(void 0, [props.name, ..._nullishCoalesce(props.aliases, () => ( []))]);
216
+ this.description = props.description;
217
+ this.metadata = _nullishCoalesce(props.metadata, () => ( {}));
218
+ }
219
+ /**
220
+ * Ensures all exits in an array have unique names by renaming duplicates.
221
+ *
222
+ * When multiple exits have the same name, this method appends numbers to
223
+ * create unique names (e.g., 'exit1', 'exit2'). This prevents naming conflicts
224
+ * in execution contexts with multiple exits.
225
+ *
226
+ * @param exits - Array of exits that may have duplicate names
227
+ * @returns Array of exits with guaranteed unique names
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const exit1 = new Exit({ name: 'done', description: 'First done' })
232
+ * const exit2 = new Exit({ name: 'done', description: 'Second done' })
233
+ *
234
+ * const uniqueExits = Exit.withUniqueNames([exit1, exit2])
235
+ * // Result: [{ name: 'done' }, { name: 'done1' }]
236
+ * ```
237
+ */
238
+ static __initStatic() {this.withUniqueNames = (exits) => {
239
+ const names = /* @__PURE__ */ new Set();
240
+ return exits.map((exit) => {
241
+ if (exits.filter((t) => t.name === exit.name).length === 1) {
242
+ return exit;
243
+ }
244
+ let counter = 1;
245
+ let exitName = exit.name + counter;
246
+ while (names.has(exitName)) {
247
+ exitName = `${exit.name}${++counter}`;
248
+ }
249
+ return exit.rename(exitName);
250
+ });
251
+ }}
252
+ }, _class.__initStatic(), _class);
253
+
254
+
255
+
256
+ exports.Exit = Exit;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getTokenizer
3
- } from "./chunk-4MNIJGK6.js";
3
+ } from "./chunk-ZORRILUV.js";
4
4
 
5
5
  // src/truncator.ts
6
6
  var DEFAULT_REMOVE_CHUNK = 250;