llmz 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +185 -98
  2. package/dist/chat.d.ts +34 -0
  3. package/dist/{chunk-TIZWOIDF.js → chunk-33AB6SVX.js} +134 -76
  4. package/dist/{chunk-EFEF2AL7.js → chunk-DH35WO5G.js} +93 -556
  5. package/dist/chunk-E5NHK3FS.js +1637 -0
  6. package/dist/{chunk-L74UZONX.js → chunk-HM5H556L.js} +3 -1
  7. package/dist/chunk-I56MPOVG.cjs +62 -0
  8. package/dist/{chunk-C7T6OJB4.cjs → chunk-IKLFMVSW.cjs} +144 -86
  9. package/dist/chunk-KWQTYXAT.js +62 -0
  10. package/dist/{chunk-JXD2KJVB.cjs → chunk-WWZ2W4WR.cjs} +103 -566
  11. package/dist/chunk-YGKQEVQQ.cjs +1637 -0
  12. package/dist/{chunk-ZPHRTTQX.cjs → chunk-YQT5G77W.cjs} +3 -1
  13. package/dist/compiler/compiler.d.ts +7 -2
  14. package/dist/compiler/index.d.ts +1 -1
  15. package/dist/compiler/plugins/async-wrapper.d.ts +11 -0
  16. package/dist/component-2NYFY6CW.cjs +14 -0
  17. package/dist/{component-2Z3KLWLX.js → component-ASNZHQUR.js} +3 -7
  18. package/dist/component.d.ts +3 -10
  19. package/dist/context.d.ts +88 -2
  20. package/dist/{dual-modes-HEXPFVUE.js → dual-modes-RMF7V7ZQ.js} +2 -4
  21. package/dist/dual-modes-ZZY6QPYT.cjs +10 -0
  22. package/dist/{execute-22PSGL7P.cjs → execute-BXPFSEVX.cjs} +331 -87
  23. package/dist/{execute-ZENBZBWL.js → execute-HIRXXR6X.js} +321 -77
  24. package/dist/index.cjs +502 -27
  25. package/dist/index.d.ts +8 -5
  26. package/dist/index.js +491 -16
  27. package/dist/message-stream/index.d.ts +9 -0
  28. package/dist/message-stream/instructions.d.ts +22 -0
  29. package/dist/message-stream/normalizer.d.ts +21 -0
  30. package/dist/message-stream/parser.d.ts +81 -0
  31. package/dist/message-stream/registry.d.ts +14 -0
  32. package/dist/message-stream/replayable.d.ts +27 -0
  33. package/dist/message-stream/sanitize.d.ts +10 -0
  34. package/dist/message-stream/stream.d.ts +54 -0
  35. package/dist/message-stream/types.d.ts +96 -0
  36. package/dist/message-stream/validator.d.ts +23 -0
  37. package/dist/message-stream/validator.test.d.ts +1 -0
  38. package/dist/prompts/chat-mode/system.md.d.ts +1 -1
  39. package/dist/prompts/chat-mode/user.md.d.ts +1 -1
  40. package/dist/prompts/common.d.ts +5 -5
  41. package/dist/prompts/prompt.d.ts +43 -6
  42. package/dist/prompts/protocol.d.ts +18 -0
  43. package/dist/prompts/worker-mode/system.md.d.ts +1 -1
  44. package/dist/prompts/worker-mode/user.md.d.ts +1 -1
  45. package/dist/result.d.ts +31 -0
  46. package/dist/runtime/execute.test.d.ts +1 -0
  47. package/dist/runtime/generate.d.ts +24 -1
  48. package/dist/runtime/interpret-result.d.ts +10 -0
  49. package/dist/runtime/types.d.ts +29 -4
  50. package/dist/truncator-7PGEGCHV.cjs +12 -0
  51. package/dist/{truncator-3U2QUUJJ.js → truncator-OZOBNYON.js} +3 -1
  52. package/dist/truncator.d.ts +2 -0
  53. package/dist/types.d.ts +8 -1
  54. package/dist/vm/drivers/quickjs.d.ts +2 -0
  55. package/dist/vm/index.d.ts +7 -0
  56. package/dist/vm/instrument.d.ts +1 -1
  57. package/dist/{vm-PYCKS77H.js → vm-44H4UKI2.js} +5 -4
  58. package/dist/{vm-VHB67FVH.cjs → vm-A3OTQVIR.cjs} +4 -3
  59. package/package.json +6 -6
  60. package/dist/chunk-2O3UTPVH.js +0 -813
  61. package/dist/chunk-3T5IU7OU.js +0 -186
  62. package/dist/chunk-BBX2LDZE.cjs +0 -813
  63. package/dist/chunk-CQ3UJW76.cjs +0 -186
  64. package/dist/compiler/plugins/async-iterator.d.ts +0 -6
  65. package/dist/compiler/plugins/braces-tsx.d.ts +0 -3
  66. package/dist/compiler/plugins/html-to-markdown.d.ts +0 -21
  67. package/dist/compiler/plugins/jsx-preserve-newlines.d.ts +0 -5
  68. package/dist/compiler/plugins/jsx-undefined-vars.d.ts +0 -14
  69. package/dist/component-NNHBHD72.cjs +0 -18
  70. package/dist/dual-modes-LLIWZCHC.cjs +0 -12
  71. package/dist/truncator-3ZN7W6NB.cjs +0 -10
  72. /package/dist/{compiler/plugins/html-to-markdown.test.d.ts → message-stream/instructions.test.d.ts} +0 -0
  73. /package/dist/{compiler/plugins/jsx-undefined-vars.test.d.ts → message-stream/normalizer.test.d.ts} +0 -0
  74. /package/dist/{component.test.d.ts → message-stream/parser.test.d.ts} +0 -0
  75. /package/dist/{vm/vm-jsx.test.d.ts → message-stream/stream.test.d.ts} +0 -0
package/dist/index.d.ts CHANGED
@@ -4,11 +4,11 @@ export { Exit, ExitResult } from './exit.js';
4
4
  export { ObjectInstance } from './objects.js';
5
5
  export { SnapshotSignal, ThinkSignal, LoopExceededError } from './errors.js';
6
6
  export { parseExit, type ParsedExit } from './exit-parser.js';
7
- export { Component, RenderedComponent, LeafComponentDefinition, ContainerComponentDefinition, DefaultComponentDefinition, ComponentDefinition, assertValidComponent, isComponent, isAnyComponent, renderToTsx, } from './component.js';
7
+ export { Component, RenderedComponent, LeafComponentDefinition, ContainerComponentDefinition, DefaultComponentDefinition, ComponentDefinition, assertValidComponent, isComponent, isAnyComponent, } from './component.js';
8
8
  export { Citation, CitationsManager } from './citations.js';
9
9
  export { DefaultComponents } from './component.default.js';
10
10
  export { Snapshot } from './snapshots.js';
11
- export { Chat, type MessageHandler } from './chat.js';
11
+ export { Chat, type MessageHandler, type MessageDelta, type MessageDeltaHandler } from './chat.js';
12
12
  import { ExecutionResult } from './result.js';
13
13
  import { type ExecutionProps } from './runtime/types.js';
14
14
  import { truncateWrappedContent, wrapContent } from './truncator.js';
@@ -16,15 +16,18 @@ export { Transcript } from './transcript.js';
16
16
  export { ErrorExecutionResult, ExecutionResult, PartialExecutionResult, SuccessExecutionResult } from './result.js';
17
17
  export { type Trace, type Traces } from './types.js';
18
18
  export { type Iteration, ListenExit, ThinkExit, DefaultExit, IterationStatuses, IterationStatus } from './context.js';
19
- export { type Context } from './context.js';
20
- export type { LLMzPrompts } from './prompts/prompt.js';
19
+ export { type Context, type TokenUsage, type ContextTokens } from './context.js';
20
+ export type { LLMzPrompts, ParsedSend, ParsedNext, ParsedAssistantResponse } from './prompts/prompt.js';
21
+ export type { ExecutionProps, ExecutionHooks } from './runtime/types.js';
21
22
  export { type ValueOrGetter, getValue } from './getter.js';
23
+ export * from './message-stream/index.js';
22
24
  export * from './custom-client.js';
23
25
  export declare const utils: {
24
26
  toValidObjectName: (str: string) => string;
25
27
  toValidFunctionName: (str: string) => string;
26
28
  wrapContent: typeof wrapContent;
27
29
  truncateWrappedContent: typeof truncateWrappedContent;
30
+ stripTruncationTags: (content: string) => string;
28
31
  };
29
32
  /**
30
33
  * Executes an LLMz agent in either Chat Mode or Worker Mode.
@@ -45,7 +48,7 @@ export declare const utils: {
45
48
  * @param props.model - Optional model name (or array or models to use as fallback) (static or dynamic function)
46
49
  * @param props.temperature - Optional temperature value (static or dynamic function)
47
50
  * @param props.metadata - Optional metadata attached to cognitive usage records for each LLM call
48
- * @param props.options - Optional execution options (loop limit, timeout)
51
+ * @param props.options - Optional execution options (loop limit, timeout, maxTokens context cap)
49
52
  * @param props.onTrace - Optional non-blocking hook for monitoring traces during execution
50
53
  * @param props.onIterationEnd - Optional blocking hook called after each iteration
51
54
  * @param props.onExit - Optional blocking hook called when an exit is reached (can prevent exit)
package/dist/index.js CHANGED
@@ -10,8 +10,14 @@ import {
10
10
  _CustomModelClient,
11
11
  getValue,
12
12
  parseExit
13
- } from "./chunk-TIZWOIDF.js";
14
- import "./chunk-2O3UTPVH.js";
13
+ } from "./chunk-33AB6SVX.js";
14
+ import {
15
+ MARKER,
16
+ NAME_REGEX,
17
+ StreamingMessageParser,
18
+ generateInstructions,
19
+ tryParseJson
20
+ } from "./chunk-E5NHK3FS.js";
15
21
  import {
16
22
  Tool
17
23
  } from "./chunk-IRCB4FRM.js";
@@ -33,18 +39,20 @@ import {
33
39
  Component,
34
40
  assertValidComponent,
35
41
  isAnyComponent,
36
- isComponent,
37
- renderToTsx
38
- } from "./chunk-3T5IU7OU.js";
42
+ isComponent
43
+ } from "./chunk-KWQTYXAT.js";
39
44
  import "./chunk-XTEHT2TK.js";
40
45
  import {
46
+ stripTruncationTags,
41
47
  truncateWrappedContent,
42
48
  wrapContent
43
- } from "./chunk-L74UZONX.js";
49
+ } from "./chunk-HM5H556L.js";
44
50
  import {
45
51
  escapeString,
46
52
  getMultilineComment,
53
+ isJsonSchema,
47
54
  isValidIdentifier,
55
+ isZuiSchema,
48
56
  toValidFunctionName,
49
57
  toValidObjectName
50
58
  } from "./chunk-YX27XM67.js";
@@ -54,7 +62,7 @@ import {
54
62
  } from "./chunk-34GJUS6U.js";
55
63
 
56
64
  // package.json
57
- var version = "0.1.4";
65
+ var version = "0.2.0";
58
66
 
59
67
  // src/objects.ts
60
68
  import { z } from "@bpinternal/zui";
@@ -964,7 +972,7 @@ var Text = new Component({
964
972
  type: "default",
965
973
  name: "Message",
966
974
  aliases: ["Text", "Markdown"],
967
- description: "Markdown-formatted text that appears directly inside components like <Message>.",
975
+ description: "A Markdown-formatted text message.",
968
976
  examples: [
969
977
  {
970
978
  name: "Basic Markdown",
@@ -993,6 +1001,7 @@ var DefaultComponents = {
993
1001
  // src/chat.ts
994
1002
  var Chat = class {
995
1003
  handler;
1004
+ onMessageDelta;
996
1005
  transcript;
997
1006
  components;
998
1007
  /**
@@ -1045,6 +1054,7 @@ var Chat = class {
1045
1054
  */
1046
1055
  constructor(props) {
1047
1056
  this.handler = props.handler;
1057
+ this.onMessageDelta = props.onMessageDelta;
1048
1058
  this.components = props.components;
1049
1059
  this.transcript = props.transcript || [];
1050
1060
  }
@@ -1108,33 +1118,481 @@ var Chat = class {
1108
1118
  }
1109
1119
  };
1110
1120
 
1121
+ // src/message-stream/replayable.ts
1122
+ var ReplayableAsyncIterable = class {
1123
+ _source;
1124
+ _chunks = [];
1125
+ _done = false;
1126
+ _failed = false;
1127
+ _error;
1128
+ _lock = Promise.resolve();
1129
+ constructor(source) {
1130
+ this._source = source[Symbol.asyncIterator]();
1131
+ }
1132
+ /** True once the underlying source has been fully consumed (or has failed). */
1133
+ get done() {
1134
+ return this._done;
1135
+ }
1136
+ /** The chunks pulled from the source so far. */
1137
+ get chunks() {
1138
+ return [...this._chunks];
1139
+ }
1140
+ async *[Symbol.asyncIterator]() {
1141
+ let index = 0;
1142
+ while (true) {
1143
+ if (index < this._chunks.length) {
1144
+ yield this._chunks[index++];
1145
+ } else if (this._failed) {
1146
+ throw this._error;
1147
+ } else if (this._done) {
1148
+ return;
1149
+ } else {
1150
+ await this._pull();
1151
+ }
1152
+ }
1153
+ }
1154
+ /** Consumes the entire source and returns all chunks. */
1155
+ async collect() {
1156
+ for await (const _ of this) {
1157
+ }
1158
+ return this.chunks;
1159
+ }
1160
+ _pull() {
1161
+ const next = this._lock.then(async () => {
1162
+ if (this._done) {
1163
+ return;
1164
+ }
1165
+ let result;
1166
+ try {
1167
+ result = await this._source.next();
1168
+ } catch (thrown) {
1169
+ this._done = true;
1170
+ this._failed = true;
1171
+ this._error = thrown;
1172
+ throw thrown;
1173
+ }
1174
+ if (result.done) {
1175
+ this._done = true;
1176
+ } else {
1177
+ this._chunks.push(result.value);
1178
+ }
1179
+ });
1180
+ this._lock = next.catch(() => {
1181
+ });
1182
+ return next;
1183
+ }
1184
+ };
1185
+ var collectText = async (iterable) => {
1186
+ let text = "";
1187
+ for await (const chunk of iterable) {
1188
+ text += chunk;
1189
+ }
1190
+ return text;
1191
+ };
1192
+
1193
+ // src/message-stream/stream.ts
1194
+ var BaseResponse = class {
1195
+ constructor(action, item) {
1196
+ this.action = action;
1197
+ this.item = item;
1198
+ }
1199
+ get diagnostics() {
1200
+ return this.item.diagnostics;
1201
+ }
1202
+ };
1203
+ var SendResponse = class extends BaseResponse {
1204
+ constructor(item, content) {
1205
+ super("send", item);
1206
+ this.content = content;
1207
+ }
1208
+ get component() {
1209
+ return this.item.name;
1210
+ }
1211
+ get props() {
1212
+ return this.item.props;
1213
+ }
1214
+ static formatToText(component, props, body) {
1215
+ const header = `${MARKER}send=${component}${props && Object.keys(props).length ? ` ${JSON.stringify(props)}` : ""}`;
1216
+ return body ? `${header}
1217
+ ${body}` : header;
1218
+ }
1219
+ };
1220
+ var RunResponse = class extends BaseResponse {
1221
+ constructor(item, code) {
1222
+ super("run", item);
1223
+ this.code = code;
1224
+ }
1225
+ static formatToText(code) {
1226
+ return `${MARKER}run
1227
+ ${code}`;
1228
+ }
1229
+ };
1230
+ var NextResponse = class extends BaseResponse {
1231
+ constructor(item) {
1232
+ super("next", item);
1233
+ }
1234
+ get name() {
1235
+ return this.item.name;
1236
+ }
1237
+ get props() {
1238
+ return this.item.props;
1239
+ }
1240
+ static formatToText(name, props) {
1241
+ return `${MARKER}next=${name}${props && Object.keys(props).length ? ` ${JSON.stringify(props)}` : ""}`;
1242
+ }
1243
+ };
1244
+ var EventPump = class {
1245
+ _iterator;
1246
+ _parser;
1247
+ _queue = [];
1248
+ _sourceDone = false;
1249
+ _lock = Promise.resolve();
1250
+ constructor(stream, parser) {
1251
+ this._iterator = stream[Symbol.asyncIterator]();
1252
+ this._parser = parser;
1253
+ }
1254
+ next() {
1255
+ const next = this._lock.then(() => this._next());
1256
+ this._lock = next.catch(() => {
1257
+ });
1258
+ return next;
1259
+ }
1260
+ unshift(event) {
1261
+ this._queue.unshift(event);
1262
+ }
1263
+ async _next() {
1264
+ while (this._queue.length === 0) {
1265
+ if (this._sourceDone) {
1266
+ return void 0;
1267
+ }
1268
+ let result;
1269
+ try {
1270
+ result = await this._iterator.next();
1271
+ } catch {
1272
+ this._sourceDone = true;
1273
+ this._queue.push(...this._parser.finish("interrupted"));
1274
+ continue;
1275
+ }
1276
+ if (result.done) {
1277
+ this._sourceDone = true;
1278
+ this._queue.push(...this._parser.finish());
1279
+ } else {
1280
+ this._queue.push(...this._parser.push(result.value));
1281
+ }
1282
+ }
1283
+ return this._queue.shift();
1284
+ }
1285
+ };
1286
+ function parseStream(stream, options) {
1287
+ return parseResponses(stream, options);
1288
+ }
1289
+ function parseText(text, options) {
1290
+ return parseResponses(
1291
+ async function* () {
1292
+ yield text;
1293
+ }(),
1294
+ options
1295
+ );
1296
+ }
1297
+ async function* parseResponses(stream, options) {
1298
+ const parser = new StreamingMessageParser(options);
1299
+ const pump = new EventPump(stream, parser);
1300
+ let activeBody;
1301
+ while (true) {
1302
+ if (activeBody) {
1303
+ await activeBody.collect();
1304
+ activeBody = void 0;
1305
+ }
1306
+ const event = await pump.next();
1307
+ if (!event) {
1308
+ return;
1309
+ }
1310
+ if (event.type === "item-ready" && (event.item.kind === "send" || event.item.kind === "run")) {
1311
+ const body = new ReplayableAsyncIterable(bodyStream(pump, event.item.id));
1312
+ activeBody = body;
1313
+ yield event.item.kind === "send" ? new SendResponse(event.item, body) : new RunResponse(event.item, body);
1314
+ continue;
1315
+ }
1316
+ if (event.type === "item-complete" && event.item.kind === "next") {
1317
+ yield new NextResponse(event.item);
1318
+ continue;
1319
+ }
1320
+ }
1321
+ }
1322
+ async function* bodyStream(pump, itemId) {
1323
+ while (true) {
1324
+ const event = await pump.next();
1325
+ if (!event) {
1326
+ return;
1327
+ }
1328
+ if (event.type === "body-delta" && event.itemId === itemId) {
1329
+ yield event.delta;
1330
+ continue;
1331
+ }
1332
+ if (event.type === "body-start" && event.itemId === itemId) {
1333
+ continue;
1334
+ }
1335
+ if (event.type === "diagnostic") {
1336
+ continue;
1337
+ }
1338
+ if (event.type === "item-complete" && event.item.id === itemId) {
1339
+ return;
1340
+ }
1341
+ pump.unshift(event);
1342
+ return;
1343
+ }
1344
+ }
1345
+
1346
+ // src/message-stream/registry.ts
1347
+ var ComponentRegistry = class {
1348
+ _definitions = /* @__PURE__ */ new Map();
1349
+ constructor(definitions = []) {
1350
+ for (const definition of definitions) {
1351
+ this.register(definition);
1352
+ }
1353
+ }
1354
+ register(definition) {
1355
+ if (!NAME_REGEX.test(definition.name)) {
1356
+ throw new Error(
1357
+ `Invalid component name "${definition.name}". Component names must be lowercase ([a-z][a-z0-9_-]*).`
1358
+ );
1359
+ }
1360
+ this._definitions.set(definition.name, definition);
1361
+ }
1362
+ unregister(name) {
1363
+ this._definitions.delete(name);
1364
+ }
1365
+ has(name) {
1366
+ return this._definitions.has(name);
1367
+ }
1368
+ get(name) {
1369
+ return this._definitions.get(name);
1370
+ }
1371
+ list() {
1372
+ return [...this._definitions.values()];
1373
+ }
1374
+ };
1375
+
1376
+ // src/message-stream/normalizer.ts
1377
+ import { transforms } from "@bpinternal/zui";
1378
+ var EMPTY_PROPS_SCHEMA = { type: "object", properties: {}, additionalProperties: false };
1379
+ var normalizeComponentName = (name) => name.trim().toLowerCase();
1380
+ function normalizeComponentDefinition(definition) {
1381
+ const name = normalizeComponentName(definition.name ?? "");
1382
+ if (!NAME_REGEX.test(name)) {
1383
+ throw new Error(
1384
+ `Invalid component name "${definition.name}". Component names must be lowercase ([a-z][a-z0-9_-]*).`
1385
+ );
1386
+ }
1387
+ return {
1388
+ name,
1389
+ description: definition.description,
1390
+ propsJsonSchema: normalizePropsSchema(definition.props, name),
1391
+ body: definition.body ? {
1392
+ format: definition.body.type,
1393
+ description: definition.body.description,
1394
+ required: definition.body.required ?? false
1395
+ } : void 0,
1396
+ generation: definition.generation
1397
+ };
1398
+ }
1399
+ function normalizePropsSchema(props, name) {
1400
+ if (props === void 0) {
1401
+ return EMPTY_PROPS_SCHEMA;
1402
+ }
1403
+ if (isZuiSchema(props)) {
1404
+ try {
1405
+ return transforms.toJSONSchema(props);
1406
+ } catch {
1407
+ return transforms.toJSONSchemaLegacy(props);
1408
+ }
1409
+ }
1410
+ if (isJsonSchema(props)) {
1411
+ return props;
1412
+ }
1413
+ throw new Error(
1414
+ `Invalid props schema for "${name}". Expected a ZUI/Zod object schema or a JSON schema, but got type "${typeof props}".`
1415
+ );
1416
+ }
1417
+
1418
+ // src/message-stream/validator.ts
1419
+ function validateComponent(item, registry) {
1420
+ const definition = registry.get(item.name);
1421
+ if (!definition) {
1422
+ const registered = registry.list().map((d) => d.name).join(", ") || "(none)";
1423
+ return {
1424
+ valid: false,
1425
+ props: item.props,
1426
+ errors: [
1427
+ {
1428
+ code: "unknown-component",
1429
+ message: `Unknown component "${item.name}". Registered components: ${registered}`
1430
+ }
1431
+ ]
1432
+ };
1433
+ }
1434
+ const errors = [
1435
+ ..._validateProps(item.props, definition),
1436
+ ..._validateBody(item, definition)
1437
+ ];
1438
+ return { valid: errors.length === 0, props: item.props, errors };
1439
+ }
1440
+ function validateProps(props, schema) {
1441
+ const errors = [];
1442
+ _checkValue(props, schema, "", errors);
1443
+ return errors;
1444
+ }
1445
+ var _validateProps = (props, definition) => validateProps(props, definition.propsJsonSchema);
1446
+ var _validateBody = (item, definition) => {
1447
+ var _a;
1448
+ const hasBody = typeof item.body === "string" && item.body.length > 0;
1449
+ if (hasBody && !definition.body) {
1450
+ return [
1451
+ {
1452
+ code: "body-not-allowed",
1453
+ message: `Component "${definition.name}" does not support a body`
1454
+ }
1455
+ ];
1456
+ }
1457
+ if (!hasBody && ((_a = definition.body) == null ? void 0 : _a.required)) {
1458
+ return [
1459
+ {
1460
+ code: "missing-required-body",
1461
+ message: `Component "${definition.name}" requires a body`
1462
+ }
1463
+ ];
1464
+ }
1465
+ return [];
1466
+ };
1467
+ var _typeOf = (value) => {
1468
+ if (value === null)
1469
+ return "null";
1470
+ if (Array.isArray(value))
1471
+ return "array";
1472
+ return typeof value;
1473
+ };
1474
+ var _matchesType = (value, type) => {
1475
+ switch (type) {
1476
+ case "string":
1477
+ return typeof value === "string";
1478
+ case "number":
1479
+ return typeof value === "number";
1480
+ case "integer":
1481
+ return typeof value === "number" && Number.isInteger(value);
1482
+ case "boolean":
1483
+ return typeof value === "boolean";
1484
+ case "null":
1485
+ return value === null;
1486
+ case "array":
1487
+ return Array.isArray(value);
1488
+ case "object":
1489
+ return !!value && typeof value === "object" && !Array.isArray(value);
1490
+ default:
1491
+ return true;
1492
+ }
1493
+ };
1494
+ var _isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
1495
+ var _checkValue = (value, schema, path, errors) => {
1496
+ if (schema === void 0 || typeof schema === "boolean" || typeof schema !== "object") {
1497
+ return;
1498
+ }
1499
+ const label = path || "props";
1500
+ const propError = (message) => {
1501
+ errors.push({ code: "invalid-prop-value", message, path: path || void 0 });
1502
+ };
1503
+ if (schema.const !== void 0 && !_isEqual(value, schema.const)) {
1504
+ propError(`Expected "${label}" to equal ${JSON.stringify(schema.const)}`);
1505
+ return;
1506
+ }
1507
+ if (schema.enum && !schema.enum.some((allowed) => _isEqual(value, allowed))) {
1508
+ propError(`Expected "${label}" to be one of: ${schema.enum.map((v) => JSON.stringify(v)).join(", ")}`);
1509
+ return;
1510
+ }
1511
+ const variants = schema.anyOf ?? schema.oneOf;
1512
+ if (variants == null ? void 0 : variants.length) {
1513
+ const matchesAny = variants.some((variant) => {
1514
+ const variantErrors = [];
1515
+ _checkValue(value, variant, path, variantErrors);
1516
+ return variantErrors.length === 0;
1517
+ });
1518
+ if (!matchesAny) {
1519
+ propError(`Value of "${label}" does not match any of the allowed types`);
1520
+ return;
1521
+ }
1522
+ }
1523
+ if (schema.type) {
1524
+ const types = Array.isArray(schema.type) ? schema.type : [schema.type];
1525
+ if (!types.some((type) => _matchesType(value, type))) {
1526
+ propError(`Expected "${label}" to be of type ${types.join(" | ")}, but got ${_typeOf(value)}`);
1527
+ return;
1528
+ }
1529
+ }
1530
+ if (Array.isArray(value) && schema.items && !Array.isArray(schema.items)) {
1531
+ value.forEach((item, index) => _checkValue(item, schema.items, `${label}[${index}]`, errors));
1532
+ }
1533
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1534
+ const record = value;
1535
+ const properties = schema.properties ?? {};
1536
+ for (const requiredKey of schema.required ?? []) {
1537
+ if (record[requiredKey] === void 0) {
1538
+ errors.push({
1539
+ code: "missing-required-prop",
1540
+ message: `Missing required prop "${path ? `${path}.` : ""}${requiredKey}"`,
1541
+ path: path ? `${path}.${requiredKey}` : requiredKey
1542
+ });
1543
+ }
1544
+ }
1545
+ for (const [key, propValue] of Object.entries(record)) {
1546
+ const propSchema = properties[key];
1547
+ const propPath = path ? `${path}.${key}` : key;
1548
+ if (propSchema === void 0) {
1549
+ if (schema.additionalProperties === false) {
1550
+ errors.push({
1551
+ code: "unexpected-prop",
1552
+ message: `Unexpected prop "${propPath}"`,
1553
+ path: propPath
1554
+ });
1555
+ }
1556
+ continue;
1557
+ }
1558
+ _checkValue(propValue, propSchema, propPath, errors);
1559
+ }
1560
+ }
1561
+ };
1562
+
1563
+ // src/message-stream/sanitize.ts
1564
+ var sanitizeMessageText = (value, options = {}) => value.replaceAll(MARKER, options.markerReplacement ?? "\u25AA");
1565
+
1111
1566
  // src/index.ts
1112
1567
  var utils = {
1113
1568
  toValidObjectName,
1114
1569
  toValidFunctionName,
1115
1570
  wrapContent,
1116
- truncateWrappedContent
1571
+ truncateWrappedContent,
1572
+ stripTruncationTags
1117
1573
  };
1118
1574
  var execute = async (props) => {
1119
- const { executeContext } = await import("./execute-ZENBZBWL.js");
1575
+ const { executeContext } = await import("./execute-HIRXXR6X.js");
1120
1576
  return executeContext(props);
1121
1577
  };
1122
1578
  var init = async () => {
1123
- await import("./execute-ZENBZBWL.js");
1124
- await import("./component-2Z3KLWLX.js");
1579
+ await import("./execute-HIRXXR6X.js");
1580
+ await import("./component-ASNZHQUR.js");
1125
1581
  await import("./tool-DNHVW3KC.js");
1126
1582
  await import("./exit-VJATJTQI.js");
1127
1583
  await import("./jsx-DDZ63UUF.js");
1128
- await import("./vm-PYCKS77H.js");
1584
+ await import("./vm-44H4UKI2.js");
1129
1585
  await import("./utils-ZEZ66X6Q.js");
1130
- await import("./truncator-3U2QUUJJ.js");
1586
+ await import("./truncator-OZOBNYON.js");
1131
1587
  await import("./typings-3YV3RDMP.js");
1132
- await import("./dual-modes-HEXPFVUE.js");
1588
+ await import("./dual-modes-RMF7V7ZQ.js");
1133
1589
  };
1134
1590
  export {
1591
+ BaseResponse,
1135
1592
  Chat,
1136
1593
  CitationsManager,
1137
1594
  Component,
1595
+ ComponentRegistry,
1138
1596
  DefaultComponents,
1139
1597
  DefaultExit,
1140
1598
  ErrorExecutionResult,
@@ -1142,23 +1600,40 @@ export {
1142
1600
  Exit,
1143
1601
  ListenExit,
1144
1602
  LoopExceededError,
1603
+ MARKER,
1604
+ NAME_REGEX,
1605
+ NextResponse,
1145
1606
  ObjectInstance,
1146
1607
  PartialExecutionResult,
1608
+ ReplayableAsyncIterable,
1609
+ RunResponse,
1610
+ SendResponse,
1147
1611
  Snapshot,
1148
1612
  SnapshotSignal,
1613
+ StreamingMessageParser,
1149
1614
  SuccessExecutionResult,
1150
1615
  ThinkExit,
1151
1616
  ThinkSignal,
1152
1617
  Tool,
1153
1618
  _CustomModelClient,
1154
1619
  assertValidComponent,
1620
+ collectText,
1155
1621
  execute,
1622
+ generateInstructions,
1156
1623
  getValue,
1157
1624
  init,
1158
1625
  isAnyComponent,
1159
1626
  isComponent,
1627
+ normalizeComponentDefinition,
1628
+ normalizeComponentName,
1629
+ normalizePropsSchema,
1160
1630
  parseExit,
1161
- renderToTsx,
1631
+ parseStream,
1632
+ parseText,
1633
+ sanitizeMessageText,
1634
+ tryParseJson,
1162
1635
  utils,
1636
+ validateComponent,
1637
+ validateProps,
1163
1638
  version
1164
1639
  };
@@ -0,0 +1,9 @@
1
+ export * from './types.js';
2
+ export { StreamingMessageParser, tryParseJson, type StreamingParserOptions } from './parser.js';
3
+ export { BaseResponse, NextResponse, RunResponse, SendResponse, parseStream, parseText, type MessageStreamResponse, } from './stream.js';
4
+ export { ReplayableAsyncIterable, collectText } from './replayable.js';
5
+ export { ComponentRegistry } from './registry.js';
6
+ export { normalizeComponentDefinition, normalizeComponentName, normalizePropsSchema, type GenerativeComponentDefinition, } from './normalizer.js';
7
+ export { validateComponent, validateProps, type ComponentValidationError, type ComponentValidationResult, } from './validator.js';
8
+ export { generateInstructions, type InstructionGeneratorOptions, type InstructionVerbosity } from './instructions.js';
9
+ export { sanitizeMessageText, type SanitizeOptions } from './sanitize.js';
@@ -0,0 +1,22 @@
1
+ import { type NormalizedComponentDefinition, type NormalizedExitDefinition } from './types.js';
2
+ export type InstructionVerbosity = 'compact' | 'standard' | 'verbose';
3
+ export type InstructionGeneratorOptions = {
4
+ /** Exits available to `■next`. */
5
+ exits?: NormalizedExitDefinition[];
6
+ /** Whether the `■run` directive is available. Default: true. */
7
+ includeRun?: boolean;
8
+ /** Whether the `■send` directive is available. Default: true when at least one component is registered. */
9
+ includeSend?: boolean;
10
+ verbosity?: InstructionVerbosity;
11
+ /** Defaults to true, except in compact mode. */
12
+ includeExamples?: boolean;
13
+ maxExamples?: number;
14
+ /** Sort components by priority then name. Default: true. */
15
+ sortComponents?: boolean;
16
+ };
17
+ /**
18
+ * Converts registered component and exit definitions into a deterministic,
19
+ * model-facing protocol specification. Given the same definitions and options,
20
+ * the output is byte-identical — safe for prompt caching and snapshots.
21
+ */
22
+ export declare function generateInstructions(components: NormalizedComponentDefinition[], options?: InstructionGeneratorOptions): string;
@@ -0,0 +1,21 @@
1
+ import { type ZodObject } from '@bpinternal/zui';
2
+ import { type BodyFormat, type GenerativeComponentMetadata, type JsonSchema, type NormalizedComponentDefinition } from './types.js';
3
+ /**
4
+ * User-facing component definition. Props may be declared with a ZUI/Zod object
5
+ * schema or a plain JSON schema. Everything downstream of the normalizer
6
+ * (parser, validator, instruction generator) is independent of ZUI/Zod.
7
+ */
8
+ export type GenerativeComponentDefinition = {
9
+ name: string;
10
+ description?: string;
11
+ props?: ZodObject<any> | JsonSchema;
12
+ body?: {
13
+ type: BodyFormat;
14
+ description?: string;
15
+ required?: boolean;
16
+ };
17
+ generation?: GenerativeComponentMetadata;
18
+ };
19
+ export declare const normalizeComponentName: (name: string) => string;
20
+ export declare function normalizeComponentDefinition(definition: GenerativeComponentDefinition): NormalizedComponentDefinition;
21
+ export declare function normalizePropsSchema(props: ZodObject<any> | JsonSchema | undefined, name: string): JsonSchema;