llmz 0.0.28 → 0.0.29
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/README.md +433 -39
- package/dist/{chunk-7G5QAIUX.js → chunk-ERK3MOZF.js} +43 -3
- package/dist/{chunk-M3LCKL55.cjs → chunk-FMOTPO76.cjs} +43 -3
- package/dist/index.cjs +3 -3
- package/dist/index.js +3 -3
- package/dist/{llmz-WPO4HYQY.js → llmz-QUBEO7EF.js} +1 -1
- package/dist/{llmz-M7XYQZT7.cjs → llmz-RZUY2RT4.cjs} +2 -2
- package/dist/{vm-YJX6M4NJ.cjs → vm-5SJN3OJI.cjs} +2 -2
- package/dist/{vm-I4G4IH7T.js → vm-SQHETBVH.js} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,24 +1,85 @@
|
|
|
1
|
-
#
|
|
1
|
+
# LLMz
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Stop chaining tools. Start generating code.**
|
|
4
|
+
|
|
5
|
+
LLMz is a TypeScript AI agent framework that replaces traditional JSON tool calling with executable code generation. Instead of orchestrating tools through multiple LLM roundtrips, agents write and execute TypeScript directly—enabling complex logic, loops, and multi-tool coordination in a single pass.
|
|
6
|
+
|
|
7
|
+
Powers millions of production agents at [Botpress](https://botpress.com).
|
|
8
|
+
|
|
9
|
+
| | |
|
|
10
|
+
| --- | ----------------------------------------------------------------------------------------- |
|
|
11
|
+
| 📚 | [**Examples →**](https://github.com/botpress/botpress/tree/master/packages/llmz/examples) |
|
|
4
12
|
|
|
5
13
|
---
|
|
6
14
|
|
|
7
|
-
|
|
15
|
+
## The Problem with Tool Calling
|
|
8
16
|
|
|
9
|
-
|
|
17
|
+
Traditional agentic frameworks (LangChain, CrewAI, MCP servers) rely on JSON tool calling:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"tool": "getTicketPrice",
|
|
22
|
+
"parameters": { "from": "quebec", "to": "new york" }
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This breaks down quickly:
|
|
27
|
+
|
|
28
|
+
- **Verbose schemas**: LLMs struggle with complex JSON structures
|
|
29
|
+
- **No logic**: Can't express conditionals, loops, or error handling
|
|
30
|
+
- **Multiple roundtrips**: Each tool call requires another LLM inference ($$$)
|
|
31
|
+
- **Fragile composition**: Chaining tools is error-prone and expensive
|
|
32
|
+
|
|
33
|
+
You end up with brittle agents that cost 10-100x more than they should.
|
|
10
34
|
|
|
11
35
|
---
|
|
12
36
|
|
|
13
|
-
##
|
|
37
|
+
## The LLMz Solution
|
|
38
|
+
|
|
39
|
+
LLMz generates and executes **real TypeScript code** in a secure sandbox:
|
|
14
40
|
|
|
15
|
-
|
|
41
|
+
```typescript
|
|
42
|
+
const price = await getTicketPrice({ from: 'quebec', to: 'new york' })
|
|
43
|
+
|
|
44
|
+
if (price > 500) {
|
|
45
|
+
throw new Error('Price too high')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const ticketId = await buyTicket({ from: 'quebec', to: 'new york' })
|
|
49
|
+
return { action: 'done', result: ticketId }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Why this works:**
|
|
53
|
+
|
|
54
|
+
- LLMs have seen billions of lines of TypeScript—they're exceptionally good at it
|
|
55
|
+
- Complex logic (loops, conditionals, error handling) happens in one inference
|
|
56
|
+
- Multiple tool calls execute synchronously without LLM roundtrips
|
|
57
|
+
- Full type safety via Zui schemas and TypeScript inference
|
|
58
|
+
|
|
59
|
+
**Real-world impact**: Anthropic reduced agent costs by 98.7% using code execution patterns ([source](https://www.anthropic.com/engineering/code-execution-with-mcp)).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
**Requirements:** Node.js 20+
|
|
16
66
|
|
|
17
67
|
```bash
|
|
18
68
|
npm install @botpress/client llmz
|
|
19
69
|
```
|
|
20
70
|
|
|
21
|
-
###
|
|
71
|
+
### Platform Support
|
|
72
|
+
|
|
73
|
+
| Platform | Support | Notes |
|
|
74
|
+
| ----------- | --------- | --------------------------------------- |
|
|
75
|
+
| Node.js 20+ | Full | Includes isolated VM sandbox |
|
|
76
|
+
| Browser | Partial\* | No sandbox (uses standard JS execution) |
|
|
77
|
+
| Bun | Partial\* | No sandbox (uses standard JS execution) |
|
|
78
|
+
| Deno | Partial\* | No sandbox (uses standard JS execution) |
|
|
79
|
+
|
|
80
|
+
\* A WASM-based sandbox (QuickJS) is in progress and coming soon, which will provide full sandboxed execution for Browser, Bun, and Deno environments.
|
|
81
|
+
|
|
82
|
+
### Worker Mode: Autonomous Execution
|
|
22
83
|
|
|
23
84
|
```typescript
|
|
24
85
|
import { Client } from '@botpress/client'
|
|
@@ -27,67 +88,400 @@ import { execute } from 'llmz'
|
|
|
27
88
|
const client = new Client({ botId: '...', token: '...' })
|
|
28
89
|
|
|
29
90
|
const result = await execute({
|
|
30
|
-
instructions: '
|
|
91
|
+
instructions: 'Calculate sum of integers 14-1078 divisible by 3, 9, or 5',
|
|
31
92
|
client,
|
|
32
93
|
})
|
|
33
94
|
|
|
34
95
|
console.log(result.output) // 271575
|
|
35
96
|
```
|
|
36
97
|
|
|
37
|
-
**
|
|
98
|
+
**Generated code:**
|
|
38
99
|
|
|
39
100
|
```typescript
|
|
40
|
-
|
|
101
|
+
let sum = 0
|
|
102
|
+
for (let i = 14; i <= 1078; i++) {
|
|
103
|
+
if (i % 3 === 0 || i % 9 === 0 || i % 5 === 0) {
|
|
104
|
+
sum += i
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { action: 'done', value: { success: true, result: sum } }
|
|
41
108
|
```
|
|
42
109
|
|
|
43
|
-
|
|
110
|
+
### Chat Mode: Interactive Agents
|
|
44
111
|
|
|
45
112
|
```typescript
|
|
46
|
-
|
|
47
|
-
|
|
113
|
+
import { execute } from 'llmz'
|
|
114
|
+
import { Text, Button } from './components'
|
|
48
115
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
116
|
+
const tools = [searchFlights, bookTicket, cancelBooking]
|
|
117
|
+
|
|
118
|
+
let state = { transcript: [] }
|
|
119
|
+
|
|
120
|
+
while (true) {
|
|
121
|
+
const result = await execute({
|
|
122
|
+
client,
|
|
123
|
+
tools,
|
|
124
|
+
chat: {
|
|
125
|
+
transcript: state.transcript,
|
|
126
|
+
components: { Text, Button },
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
if (result.is('listen')) {
|
|
131
|
+
// Agent yielded UI and is waiting for user input
|
|
132
|
+
console.log('Agent:', result.value.components)
|
|
133
|
+
const userInput = await getUserInput()
|
|
134
|
+
state.transcript.push({ role: 'user', content: userInput })
|
|
135
|
+
} else {
|
|
136
|
+
// Agent completed the task
|
|
137
|
+
break
|
|
53
138
|
}
|
|
54
139
|
}
|
|
140
|
+
```
|
|
55
141
|
|
|
56
|
-
|
|
57
|
-
|
|
142
|
+
**Generated code:**
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const flights = await searchFlights({ from: 'SFO', to: 'NYC' })
|
|
146
|
+
|
|
147
|
+
yield (
|
|
148
|
+
<Text>
|
|
149
|
+
Found {flights.length} flights. Cheapest is ${flights[0].price}. Book it?
|
|
150
|
+
</Text>
|
|
151
|
+
)
|
|
152
|
+
yield <Button>Book Flight</Button>
|
|
153
|
+
yield <Button>Cancel</Button>
|
|
154
|
+
|
|
155
|
+
return { action: 'listen' }
|
|
58
156
|
```
|
|
59
157
|
|
|
60
|
-
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Core Concepts
|
|
61
161
|
|
|
62
|
-
|
|
63
|
-
|
|
162
|
+
### Execution Modes
|
|
163
|
+
|
|
164
|
+
**Worker Mode**: Autonomous agents that execute to completion
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const result = await execute({
|
|
168
|
+
instructions: 'Analyze Q4 sales data and generate report',
|
|
169
|
+
client,
|
|
170
|
+
tools: [fetchSales, calculateMetrics, generatePDF],
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Chat Mode**: Interactive conversations with user input
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const result = await execute({
|
|
178
|
+
client,
|
|
179
|
+
tools,
|
|
180
|
+
chat: {
|
|
181
|
+
transcript: conversationHistory,
|
|
182
|
+
components: { Text, Button, Form },
|
|
183
|
+
},
|
|
184
|
+
})
|
|
64
185
|
```
|
|
65
186
|
|
|
187
|
+
### Tools: Type-Safe Functions
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { Tool } from 'llmz'
|
|
191
|
+
import { z } from '@bpinternal/zui'
|
|
192
|
+
|
|
193
|
+
const searchFlights = new Tool({
|
|
194
|
+
name: 'searchFlights',
|
|
195
|
+
description: 'Search for available flights',
|
|
196
|
+
input: z.object({
|
|
197
|
+
from: z.string(),
|
|
198
|
+
to: z.string(),
|
|
199
|
+
date: z.string(),
|
|
200
|
+
}),
|
|
201
|
+
output: z.array(
|
|
202
|
+
z.object({
|
|
203
|
+
id: z.string(),
|
|
204
|
+
price: z.number(),
|
|
205
|
+
departure: z.string(),
|
|
206
|
+
})
|
|
207
|
+
),
|
|
208
|
+
handler: async ({ from, to, date }) => {
|
|
209
|
+
// Your implementation
|
|
210
|
+
return flights
|
|
211
|
+
},
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Tools are exposed to agents with full TypeScript signatures. Agents call them like regular async functions.
|
|
216
|
+
|
|
217
|
+
### Objects: Namespaced State
|
|
218
|
+
|
|
219
|
+
Group related tools and variables:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { ObjectInstance } from 'llmz'
|
|
223
|
+
import { z } from '@bpinternal/zui'
|
|
224
|
+
|
|
225
|
+
const database = new ObjectInstance({
|
|
226
|
+
name: 'db',
|
|
227
|
+
description: 'Database operations',
|
|
228
|
+
tools: [queryUsers, updateRecord, deleteRecord],
|
|
229
|
+
properties: [
|
|
230
|
+
{
|
|
231
|
+
name: 'connectionString',
|
|
232
|
+
value: process.env.DB_URL,
|
|
233
|
+
writable: false,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: 'lastQueryTime',
|
|
237
|
+
value: null,
|
|
238
|
+
type: z.string().nullable(),
|
|
239
|
+
writable: true,
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
})
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Agents access via namespaces:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
const users = await db.queryUsers({ active: true })
|
|
249
|
+
db.lastQueryTime = new Date().toISOString()
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Exits: Structured Termination
|
|
253
|
+
|
|
254
|
+
Define how agents can complete:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { Exit } from 'llmz'
|
|
258
|
+
import { z } from '@bpinternal/zui'
|
|
259
|
+
|
|
260
|
+
const TicketBooked = new Exit({
|
|
261
|
+
name: 'ticket_booked',
|
|
262
|
+
description: 'Successfully booked a ticket',
|
|
263
|
+
schema: z.object({
|
|
264
|
+
ticketId: z.string(),
|
|
265
|
+
price: z.number(),
|
|
266
|
+
confirmation: z.string(),
|
|
267
|
+
}),
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const result = await execute({
|
|
271
|
+
client,
|
|
272
|
+
tools,
|
|
273
|
+
exits: [TicketBooked],
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
if (result.is(TicketBooked)) {
|
|
277
|
+
console.log('Booked:', result.value.ticketId) // Fully typed
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Agents use exits via return statements:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
return {
|
|
285
|
+
action: 'ticket_booked',
|
|
286
|
+
ticketId: 'TKT-12345',
|
|
287
|
+
price: 299,
|
|
288
|
+
confirmation: 'ABC123',
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Advanced Features
|
|
295
|
+
|
|
296
|
+
### Thinking: Forced Reflection
|
|
297
|
+
|
|
298
|
+
Prevent agents from rushing to conclusions:
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
import { ThinkSignal } from 'llmz'
|
|
302
|
+
|
|
303
|
+
const complexAnalysis = new Tool({
|
|
304
|
+
name: 'analyze',
|
|
305
|
+
handler: async (data) => {
|
|
306
|
+
const result = performComplexCalculation(data)
|
|
307
|
+
// Force agent to reflect on results before proceeding
|
|
308
|
+
throw new ThinkSignal('Analysis complete. Review data before next step.')
|
|
309
|
+
},
|
|
310
|
+
})
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Agents can also self-initiate thinking:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// Agent-generated code
|
|
317
|
+
const data = await fetchLargeDataset()
|
|
318
|
+
return { action: 'think' } // Pause to process information
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Snapshots: Pause and Resume
|
|
322
|
+
|
|
323
|
+
Save execution state for long-running workflows:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import { SnapshotSignal } from 'llmz'
|
|
327
|
+
|
|
328
|
+
const approvalRequired = new Tool({
|
|
329
|
+
name: 'submitForApproval',
|
|
330
|
+
handler: async (request) => {
|
|
331
|
+
await saveToDatabase(request)
|
|
332
|
+
// Halt execution until manual approval
|
|
333
|
+
throw new SnapshotSignal('Awaiting manager approval')
|
|
334
|
+
},
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
// Later, resume from snapshot
|
|
338
|
+
const result = await execute({
|
|
339
|
+
client,
|
|
340
|
+
snapshot: savedSnapshot,
|
|
341
|
+
})
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Hooks: Custom Logic Injection
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
const result = await execute({
|
|
348
|
+
client,
|
|
349
|
+
tools,
|
|
350
|
+
hooks: {
|
|
351
|
+
onTrace: (trace) => {
|
|
352
|
+
// Non-blocking: log tool calls, errors, outputs
|
|
353
|
+
logger.info(trace)
|
|
354
|
+
},
|
|
355
|
+
onExit: (exit) => {
|
|
356
|
+
// Validate before allowing exit
|
|
357
|
+
if (exit.action === 'transfer_money' && exit.amount > 10000) {
|
|
358
|
+
throw new Error('Amount exceeds limit')
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
onBeforeExecution: (code) => {
|
|
362
|
+
// Inspect/modify generated code before execution
|
|
363
|
+
if (code.includes('dangerousOperation')) {
|
|
364
|
+
throw new Error('Blocked unsafe operation')
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
})
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Coming from MCP?
|
|
374
|
+
|
|
375
|
+
LLMz is **not** a replacement for MCP—it's complementary.
|
|
376
|
+
|
|
377
|
+
**MCP** (Model Context Protocol): Standardizes how AI applications connect to data sources and tools across processes/machines.
|
|
378
|
+
|
|
379
|
+
**LLMz**: Replaces the execution pattern _after_ tools are exposed. Instead of making multiple LLM calls to orchestrate MCP tools via JSON, LLMz generates TypeScript code that calls those same tools in a single inference—reducing costs by up to 98%.
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Production Ready
|
|
384
|
+
|
|
385
|
+
LLMz has been running in production for over a year:
|
|
386
|
+
|
|
387
|
+
- **Millions** of active users across enterprise and consumer applications
|
|
388
|
+
- **Hundreds of thousands** of deployed agents handling real-world workloads
|
|
389
|
+
- **Secure sandbox**: Uses `isolated-vm` for untrusted code execution
|
|
390
|
+
- **Type-safe**: Full TypeScript inference and Zui validation
|
|
391
|
+
- **Observable**: Comprehensive tracing and error handling
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Architecture
|
|
396
|
+
|
|
397
|
+
**Execution Pipeline:**
|
|
398
|
+
|
|
399
|
+
1. **Prompt Generation**: Injects tools, schemas, and context into dual-mode prompts
|
|
400
|
+
2. **Code Generation**: LLM generates TypeScript with tool calls and logic
|
|
401
|
+
3. **Compilation**: Babel AST transformation with custom plugins (tracking, JSX, source maps)
|
|
402
|
+
4. **Execution**: Runs in isolated VM (production) or Node.js VM (development)
|
|
403
|
+
5. **Result Processing**: Type-safe exit handling and error recovery
|
|
404
|
+
|
|
405
|
+
**Security:**
|
|
406
|
+
|
|
407
|
+
- Sandboxed execution environment (no filesystem/network access)
|
|
408
|
+
- Stack trace sanitization (removes internal framework details)
|
|
409
|
+
- Configurable tool permissions and rate limiting
|
|
410
|
+
- Automatic token limit handling
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Comparison
|
|
415
|
+
|
|
416
|
+
| Feature | LangChain / CrewAI | MCP Servers | LLMz |
|
|
417
|
+
| ------------------------ | ---------------------- | ---------------------- | ------------------------- |
|
|
418
|
+
| Tool calling | JSON | JSON | TypeScript code |
|
|
419
|
+
| Multi-tool orchestration | Multiple LLM calls | Multiple LLM calls | Single LLM call |
|
|
420
|
+
| Complex logic | Limited | Limited | Full language support |
|
|
421
|
+
| Type safety | Partial | Schema-based | Full TypeScript + Zui |
|
|
422
|
+
| Execution environment | Python/JS runtime | Cross-process | Isolated VM |
|
|
423
|
+
| Cost (complex workflows) | High (many roundtrips) | High (many roundtrips) | Low (one-shot generation) |
|
|
424
|
+
| Production scale | Varies | Emerging | Battle-tested (1M+ users) |
|
|
425
|
+
|
|
66
426
|
---
|
|
67
427
|
|
|
68
|
-
##
|
|
428
|
+
## Examples
|
|
69
429
|
|
|
70
|
-
|
|
430
|
+
Check out the [examples folder](https://github.com/botpress/botpress/tree/master/packages/llmz/examples) for complete working examples:
|
|
71
431
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
432
|
+
| Title | Mode | Description |
|
|
433
|
+
| --------------------------------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------- |
|
|
434
|
+
| [Basic Chat](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/01_chat_basic) | Chat | Simple interactive chat with button-based navigation |
|
|
435
|
+
| [Chat with Exits](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/02_chat_exits) | Chat | Custom exit conditions with type-safe validation |
|
|
436
|
+
| [Conditional Tools](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/03_chat_conditional_tool) | Chat | Dynamic tool availability based on context |
|
|
437
|
+
| [Small Models](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/04_chat_small_models) | Chat | Optimized prompts for smaller language models |
|
|
438
|
+
| [Web Search](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/05_chat_web_search) | Chat | Integrate web search and content browsing |
|
|
439
|
+
| [Tool Confirmation](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/06_chat_confirm_tool) | Chat | User confirmation before executing tools |
|
|
440
|
+
| [Guardrails](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/07_chat_guardrails) | Chat | Safety constraints and content filtering |
|
|
441
|
+
| [Multi-Agent](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/08_chat_multi_agent) | Chat | Coordinating multiple agents in one system |
|
|
442
|
+
| [Variables](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/09_chat_variables) | Chat | Stateful properties that persist across iterations |
|
|
443
|
+
| [Components](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/10_chat_components) | Chat | Rich UI components for interactive experiences |
|
|
444
|
+
| [Minimal Worker](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/11_worker_minimal) | Worker | One-shot computational task execution |
|
|
445
|
+
| [File System](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/12_worker_fs) | Worker | Automated file operations with conditional logic |
|
|
446
|
+
| [Sandbox](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/13_worker_sandbox) | Worker | Secure isolated code execution environment |
|
|
447
|
+
| [Snapshots](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/14_worker_snapshot) | Worker | Pause and resume long-running workflows |
|
|
448
|
+
| [Stack Traces](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/15_worker_stacktraces) | Worker | Error handling and debugging patterns |
|
|
449
|
+
| [Tool Chaining](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/16_worker_tool_chaining) | Worker | Sequential multi-tool orchestration |
|
|
450
|
+
| [Error Recovery](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/17_worker_error_recovery) | Worker | Graceful failure handling and retries |
|
|
451
|
+
| [Security](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/18_worker_security) | Worker | Code inspection and security validation |
|
|
452
|
+
| [Wrap Tools](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/19_worker_wrap_tool) | Worker | Creating higher-order tool abstractions |
|
|
453
|
+
| [RAG](https://github.com/botpress/botpress/tree/master/packages/llmz/examples/20_chat_rag) | Chat | Retrieval-augmented generation with knowledge bases |
|
|
76
454
|
|
|
77
|
-
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Contributing
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
git clone https://github.com/botpress/botpress
|
|
461
|
+
cd packages/llmz
|
|
462
|
+
|
|
463
|
+
pnpm install
|
|
464
|
+
pnpm test
|
|
465
|
+
pnpm build
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**Commands:**
|
|
78
469
|
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
- Scales effortlessly in production
|
|
470
|
+
- `pnpm test`: Run test suite (Vitest with LLM retries)
|
|
471
|
+
- `pnpm test:watch`: Watch mode for development
|
|
472
|
+
- `pnpm build`: Compile TypeScript and bundle (ESM + CJS)
|
|
473
|
+
- `pnpm generate`: Regenerate prompt templates from markdown
|
|
84
474
|
|
|
85
475
|
---
|
|
86
476
|
|
|
87
|
-
##
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
MIT
|
|
480
|
+
|
|
481
|
+
---
|
|
88
482
|
|
|
89
|
-
|
|
483
|
+
## Learn More
|
|
90
484
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
485
|
+
- [Anthropic: Code Execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp)
|
|
486
|
+
- [How Code Execution Reduces Agent Costs by 98%](https://medium.com/@meshuggah22/weve-been-using-mcp-wrong-how-anthropic-reduced-ai-agent-costs-by-98-7-7c102fc22589)
|
|
487
|
+
- [Botpress Documentation](https://botpress.com/docs)
|
|
@@ -2031,19 +2031,59 @@ function escapeBracesInCodeFences(tsx) {
|
|
|
2031
2031
|
let i = 0;
|
|
2032
2032
|
let output = "";
|
|
2033
2033
|
let insideFencedBlock = false;
|
|
2034
|
+
let jsxDepth = 0;
|
|
2035
|
+
let braceDepth = 0;
|
|
2034
2036
|
while (i < tsx.length) {
|
|
2037
|
+
const char = tsx[i];
|
|
2038
|
+
if (char === "<" && !insideFencedBlock) {
|
|
2039
|
+
if (tsx[i + 1] !== "/") {
|
|
2040
|
+
jsxDepth++;
|
|
2041
|
+
} else {
|
|
2042
|
+
jsxDepth--;
|
|
2043
|
+
}
|
|
2044
|
+
output += char;
|
|
2045
|
+
i++;
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
if (jsxDepth > 0 && !insideFencedBlock) {
|
|
2049
|
+
if (char === "{") {
|
|
2050
|
+
braceDepth++;
|
|
2051
|
+
output += char;
|
|
2052
|
+
i++;
|
|
2053
|
+
continue;
|
|
2054
|
+
} else if (char === "}") {
|
|
2055
|
+
braceDepth--;
|
|
2056
|
+
output += char;
|
|
2057
|
+
i++;
|
|
2058
|
+
continue;
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2035
2061
|
if (tsx.startsWith("```", i)) {
|
|
2036
2062
|
insideFencedBlock = !insideFencedBlock;
|
|
2037
2063
|
output += "```";
|
|
2038
2064
|
i += 3;
|
|
2039
2065
|
continue;
|
|
2040
2066
|
}
|
|
2041
|
-
if (insideFencedBlock &&
|
|
2042
|
-
|
|
2067
|
+
if (jsxDepth > 0 && braceDepth === 0 && !insideFencedBlock && char === "`") {
|
|
2068
|
+
const closingIndex = tsx.indexOf("`", i + 1);
|
|
2069
|
+
if (closingIndex !== -1) {
|
|
2070
|
+
const inlineCode = tsx.slice(i + 1, closingIndex);
|
|
2071
|
+
let escaped = "`";
|
|
2072
|
+
for (const c of inlineCode) {
|
|
2073
|
+
escaped += HTML_ENTITIES[c] || c;
|
|
2074
|
+
}
|
|
2075
|
+
escaped += "`";
|
|
2076
|
+
output += escaped;
|
|
2077
|
+
i = closingIndex + 1;
|
|
2078
|
+
continue;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
if (insideFencedBlock && char in HTML_ENTITIES) {
|
|
2082
|
+
output += HTML_ENTITIES[char];
|
|
2043
2083
|
i++;
|
|
2044
2084
|
continue;
|
|
2045
2085
|
}
|
|
2046
|
-
output +=
|
|
2086
|
+
output += char;
|
|
2047
2087
|
i++;
|
|
2048
2088
|
}
|
|
2049
2089
|
return output;
|
|
@@ -2031,19 +2031,59 @@ function escapeBracesInCodeFences(tsx) {
|
|
|
2031
2031
|
let i = 0;
|
|
2032
2032
|
let output = "";
|
|
2033
2033
|
let insideFencedBlock = false;
|
|
2034
|
+
let jsxDepth = 0;
|
|
2035
|
+
let braceDepth = 0;
|
|
2034
2036
|
while (i < tsx.length) {
|
|
2037
|
+
const char = tsx[i];
|
|
2038
|
+
if (char === "<" && !insideFencedBlock) {
|
|
2039
|
+
if (tsx[i + 1] !== "/") {
|
|
2040
|
+
jsxDepth++;
|
|
2041
|
+
} else {
|
|
2042
|
+
jsxDepth--;
|
|
2043
|
+
}
|
|
2044
|
+
output += char;
|
|
2045
|
+
i++;
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
if (jsxDepth > 0 && !insideFencedBlock) {
|
|
2049
|
+
if (char === "{") {
|
|
2050
|
+
braceDepth++;
|
|
2051
|
+
output += char;
|
|
2052
|
+
i++;
|
|
2053
|
+
continue;
|
|
2054
|
+
} else if (char === "}") {
|
|
2055
|
+
braceDepth--;
|
|
2056
|
+
output += char;
|
|
2057
|
+
i++;
|
|
2058
|
+
continue;
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2035
2061
|
if (tsx.startsWith("```", i)) {
|
|
2036
2062
|
insideFencedBlock = !insideFencedBlock;
|
|
2037
2063
|
output += "```";
|
|
2038
2064
|
i += 3;
|
|
2039
2065
|
continue;
|
|
2040
2066
|
}
|
|
2041
|
-
if (insideFencedBlock &&
|
|
2042
|
-
|
|
2067
|
+
if (jsxDepth > 0 && braceDepth === 0 && !insideFencedBlock && char === "`") {
|
|
2068
|
+
const closingIndex = tsx.indexOf("`", i + 1);
|
|
2069
|
+
if (closingIndex !== -1) {
|
|
2070
|
+
const inlineCode = tsx.slice(i + 1, closingIndex);
|
|
2071
|
+
let escaped = "`";
|
|
2072
|
+
for (const c of inlineCode) {
|
|
2073
|
+
escaped += HTML_ENTITIES[c] || c;
|
|
2074
|
+
}
|
|
2075
|
+
escaped += "`";
|
|
2076
|
+
output += escaped;
|
|
2077
|
+
i = closingIndex + 1;
|
|
2078
|
+
continue;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
if (insideFencedBlock && char in HTML_ENTITIES) {
|
|
2082
|
+
output += HTML_ENTITIES[char];
|
|
2043
2083
|
i++;
|
|
2044
2084
|
continue;
|
|
2045
2085
|
}
|
|
2046
|
-
output +=
|
|
2086
|
+
output += char;
|
|
2047
2087
|
i++;
|
|
2048
2088
|
}
|
|
2049
2089
|
return output;
|
package/dist/index.cjs
CHANGED
|
@@ -1103,16 +1103,16 @@ var utils = {
|
|
|
1103
1103
|
truncateWrappedContent: _chunkGZPN7RGHcjs.truncateWrappedContent
|
|
1104
1104
|
};
|
|
1105
1105
|
var execute = async (props) => {
|
|
1106
|
-
const { executeContext } = await Promise.resolve().then(() => _interopRequireWildcard(require("./llmz-
|
|
1106
|
+
const { executeContext } = await Promise.resolve().then(() => _interopRequireWildcard(require("./llmz-RZUY2RT4.cjs")));
|
|
1107
1107
|
return executeContext(props);
|
|
1108
1108
|
};
|
|
1109
1109
|
var init = async () => {
|
|
1110
|
-
await Promise.resolve().then(() => _interopRequireWildcard(require("./llmz-
|
|
1110
|
+
await Promise.resolve().then(() => _interopRequireWildcard(require("./llmz-RZUY2RT4.cjs")));
|
|
1111
1111
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./component-R4WTW6DZ.cjs")));
|
|
1112
1112
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./tool-GMYMVXUK.cjs")));
|
|
1113
1113
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./exit-XAYKJ6TR.cjs")));
|
|
1114
1114
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./jsx-AJAXBWFE.cjs")));
|
|
1115
|
-
await Promise.resolve().then(() => _interopRequireWildcard(require("./vm-
|
|
1115
|
+
await Promise.resolve().then(() => _interopRequireWildcard(require("./vm-5SJN3OJI.cjs")));
|
|
1116
1116
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./utils-L5QAQXV2.cjs")));
|
|
1117
1117
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./truncator-W3NXBLYJ.cjs")));
|
|
1118
1118
|
await Promise.resolve().then(() => _interopRequireWildcard(require("./typings-2RAAZ2YP.cjs")));
|
package/dist/index.js
CHANGED
|
@@ -1103,16 +1103,16 @@ var utils = {
|
|
|
1103
1103
|
truncateWrappedContent
|
|
1104
1104
|
};
|
|
1105
1105
|
var execute = async (props) => {
|
|
1106
|
-
const { executeContext } = await import("./llmz-
|
|
1106
|
+
const { executeContext } = await import("./llmz-QUBEO7EF.js");
|
|
1107
1107
|
return executeContext(props);
|
|
1108
1108
|
};
|
|
1109
1109
|
var init = async () => {
|
|
1110
|
-
await import("./llmz-
|
|
1110
|
+
await import("./llmz-QUBEO7EF.js");
|
|
1111
1111
|
await import("./component-WFVDVSDK.js");
|
|
1112
1112
|
await import("./tool-GEBXW6AQ.js");
|
|
1113
1113
|
await import("./exit-YLO7BY7Z.js");
|
|
1114
1114
|
await import("./jsx-AEHVFB3L.js");
|
|
1115
|
-
await import("./vm-
|
|
1115
|
+
await import("./vm-SQHETBVH.js");
|
|
1116
1116
|
await import("./utils-RQHQ2KOG.js");
|
|
1117
1117
|
await import("./truncator-BSP6PQPC.js");
|
|
1118
1118
|
await import("./typings-3VYUEACY.js");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkFMOTPO76cjs = require('./chunk-FMOTPO76.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -362,7 +362,7 @@ var executeIteration = async ({
|
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
364
|
startedAt = Date.now();
|
|
365
|
-
const result = await
|
|
365
|
+
const result = await _chunkFMOTPO76cjs.runAsyncFunction.call(void 0,
|
|
366
366
|
vmContext,
|
|
367
367
|
iteration.code,
|
|
368
368
|
traces,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkFMOTPO76cjs = require('./chunk-FMOTPO76.cjs');
|
|
5
5
|
require('./chunk-T63Y6GTW.cjs');
|
|
6
6
|
require('./chunk-KIN7Y247.cjs');
|
|
7
7
|
require('./chunk-KMZDFWYZ.cjs');
|
|
@@ -9,4 +9,4 @@ require('./chunk-UQOBUJIQ.cjs');
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
exports.CAN_USE_ISOLATED_VM =
|
|
12
|
+
exports.CAN_USE_ISOLATED_VM = _chunkFMOTPO76cjs.CAN_USE_ISOLATED_VM; exports.runAsyncFunction = _chunkFMOTPO76cjs.runAsyncFunction;
|
package/package.json
CHANGED