@deepagents/context 0.26.0 → 0.28.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.
package/dist/browser.js CHANGED
@@ -1,167 +1,7 @@
1
- // packages/context/src/lib/estimate.ts
2
- import { encode } from "gpt-tokenizer";
3
- var defaultTokenizer = {
4
- encode(text) {
5
- return encode(text);
6
- },
7
- count(text) {
8
- return encode(text).length;
9
- }
10
- };
11
- var ModelsRegistry = class {
12
- #cache = /* @__PURE__ */ new Map();
13
- #loaded = false;
14
- #tokenizers = /* @__PURE__ */ new Map();
15
- #defaultTokenizer = defaultTokenizer;
16
- /**
17
- * Load models data from models.dev API
18
- */
19
- async load() {
20
- if (this.#loaded) return;
21
- const response = await fetch("https://models.dev/api.json");
22
- if (!response.ok) {
23
- throw new Error(`Failed to fetch models: ${response.statusText}`);
24
- }
25
- const data = await response.json();
26
- for (const [providerId, provider] of Object.entries(data)) {
27
- for (const [modelId, model] of Object.entries(provider.models)) {
28
- const info = {
29
- id: model.id,
30
- name: model.name,
31
- family: model.family,
32
- cost: model.cost,
33
- limit: model.limit,
34
- provider: providerId
35
- };
36
- this.#cache.set(`${providerId}:${modelId}`, info);
37
- }
38
- }
39
- this.#loaded = true;
40
- }
41
- /**
42
- * Get model info by ID
43
- * @param modelId - Model ID (e.g., "openai:gpt-4o")
44
- */
45
- get(modelId) {
46
- return this.#cache.get(modelId);
47
- }
48
- /**
49
- * Check if a model exists in the registry
50
- */
51
- has(modelId) {
52
- return this.#cache.has(modelId);
53
- }
54
- /**
55
- * List all available model IDs
56
- */
57
- list() {
58
- return [...this.#cache.keys()];
59
- }
60
- /**
61
- * Register a custom tokenizer for specific model families
62
- * @param family - Model family name (e.g., "llama", "claude")
63
- * @param tokenizer - Tokenizer implementation
64
- */
65
- registerTokenizer(family, tokenizer) {
66
- this.#tokenizers.set(family, tokenizer);
67
- }
68
- /**
69
- * Set the default tokenizer used when no family-specific tokenizer is registered
70
- */
71
- setDefaultTokenizer(tokenizer) {
72
- this.#defaultTokenizer = tokenizer;
73
- }
74
- /**
75
- * Get the appropriate tokenizer for a model
76
- */
77
- getTokenizer(modelId) {
78
- const model = this.get(modelId);
79
- if (model) {
80
- const familyTokenizer = this.#tokenizers.get(model.family);
81
- if (familyTokenizer) {
82
- return familyTokenizer;
83
- }
84
- }
85
- return this.#defaultTokenizer;
86
- }
87
- /**
88
- * Estimate token count and cost for given text and model
89
- * @param modelId - Model ID to use for pricing (e.g., "openai:gpt-4o")
90
- * @param input - Input text (prompt)
91
- */
92
- estimate(modelId, input) {
93
- const model = this.get(modelId);
94
- if (!model) {
95
- throw new Error(
96
- `Model "${modelId}" not found. Call load() first or check model ID.`
97
- );
98
- }
99
- const tokenizer = this.getTokenizer(modelId);
100
- const tokens = tokenizer.count(input);
101
- const cost = tokens / 1e6 * model.cost.input;
102
- return {
103
- model: model.id,
104
- provider: model.provider,
105
- tokens,
106
- cost,
107
- limits: {
108
- context: model.limit.context,
109
- output: model.limit.output,
110
- exceedsContext: tokens > model.limit.context
111
- },
112
- fragments: []
113
- };
114
- }
115
- };
116
- var _registry = null;
117
- function getModelsRegistry() {
118
- if (!_registry) {
119
- _registry = new ModelsRegistry();
120
- }
121
- return _registry;
122
- }
123
- async function estimate(modelId, renderer, ...fragments) {
124
- const registry = getModelsRegistry();
125
- await registry.load();
126
- const input = renderer.render(fragments);
127
- const model = registry.get(modelId);
128
- if (!model) {
129
- throw new Error(
130
- `Model "${modelId}" not found. Call load() first or check model ID.`
131
- );
132
- }
133
- const tokenizer = registry.getTokenizer(modelId);
134
- const totalTokens = tokenizer.count(input);
135
- const totalCost = totalTokens / 1e6 * model.cost.input;
136
- const fragmentEstimates = fragments.map((fragment2) => {
137
- const rendered = renderer.render([fragment2]);
138
- const tokens = tokenizer.count(rendered);
139
- const cost = tokens / 1e6 * model.cost.input;
140
- return {
141
- id: fragment2.id,
142
- name: fragment2.name,
143
- tokens,
144
- cost
145
- };
146
- });
147
- return {
148
- model: model.id,
149
- provider: model.provider,
150
- tokens: totalTokens,
151
- cost: totalCost,
152
- limits: {
153
- context: model.limit.context,
154
- output: model.limit.output,
155
- exceedsContext: totalTokens > model.limit.context
156
- },
157
- fragments: fragmentEstimates
158
- };
159
- }
160
-
161
1
  // packages/context/src/lib/fragments.ts
162
2
  import { generateId } from "ai";
163
3
  function isFragment(data) {
164
- return typeof data === "object" && data !== null && "name" in data && "data" in data && typeof data.name === "string";
4
+ return typeof data === "object" && data !== null && "name" in data && ("data" in data || "codec" in data) && typeof data.name === "string";
165
5
  }
166
6
  function isFragmentObject(data) {
167
7
  return typeof data === "object" && data !== null && !Array.isArray(data) && !isFragment(data);
@@ -169,6 +9,15 @@ function isFragmentObject(data) {
169
9
  function isMessageFragment(fragment2) {
170
10
  return fragment2.type === "message";
171
11
  }
12
+ function getFragmentData(fragment2) {
13
+ if (fragment2.codec) {
14
+ return fragment2.codec.decode();
15
+ }
16
+ if ("data" in fragment2) {
17
+ return fragment2.data;
18
+ }
19
+ throw new Error(`Fragment "${fragment2.name}" is missing data and codec`);
20
+ }
172
21
  function fragment(name, ...children) {
173
22
  return {
174
23
  name,
@@ -179,7 +28,6 @@ function assistant(message2) {
179
28
  return {
180
29
  id: message2.id,
181
30
  name: "assistant",
182
- data: "content",
183
31
  type: "message",
184
32
  persist: true,
185
33
  codec: {
@@ -201,7 +49,6 @@ function message(content) {
201
49
  return {
202
50
  id: message2.id,
203
51
  name: message2.role,
204
- data: "content",
205
52
  type: "message",
206
53
  persist: true,
207
54
  codec: {
@@ -239,17 +86,60 @@ function lastAssistantMessage(content) {
239
86
  };
240
87
  }
241
88
 
89
+ // packages/context/src/lib/codec/serialized-codec.ts
90
+ function encodeSerializedValue(value) {
91
+ if (isFragment(value)) {
92
+ if (isMessageFragment(value)) {
93
+ throw new Error(
94
+ "Message fragments are not supported by serialized fragment conversion"
95
+ );
96
+ }
97
+ if (!value.codec) {
98
+ throw new Error(`Fragment "${value.name}" is missing codec`);
99
+ }
100
+ return value.codec.encode();
101
+ }
102
+ if (Array.isArray(value)) {
103
+ return value.map((item) => encodeSerializedValue(item));
104
+ }
105
+ if (isFragmentObject(value)) {
106
+ return Object.fromEntries(
107
+ Object.entries(value).map(([key, entry]) => [
108
+ key,
109
+ encodeSerializedValue(entry)
110
+ ])
111
+ );
112
+ }
113
+ return value;
114
+ }
115
+
242
116
  // packages/context/src/lib/fragments/domain.ts
243
117
  function term(name, definition) {
244
118
  return {
245
119
  name: "term",
246
- data: { name, definition }
120
+ data: { name, definition },
121
+ codec: {
122
+ encode() {
123
+ return { type: "term", name, definition };
124
+ },
125
+ decode() {
126
+ return { name, definition };
127
+ }
128
+ }
247
129
  };
248
130
  }
249
131
  function hint(text) {
250
132
  return {
251
133
  name: "hint",
252
- data: text
134
+ data: text,
135
+ codec: {
136
+ encode() {
137
+ return { type: "hint", text };
138
+ },
139
+ decode() {
140
+ return text;
141
+ }
142
+ }
253
143
  };
254
144
  }
255
145
  function guardrail(input) {
@@ -259,6 +149,23 @@ function guardrail(input) {
259
149
  rule: input.rule,
260
150
  ...input.reason && { reason: input.reason },
261
151
  ...input.action && { action: input.action }
152
+ },
153
+ codec: {
154
+ encode() {
155
+ return {
156
+ type: "guardrail",
157
+ rule: input.rule,
158
+ ...input.reason && { reason: input.reason },
159
+ ...input.action && { action: input.action }
160
+ };
161
+ },
162
+ decode() {
163
+ return {
164
+ rule: input.rule,
165
+ ...input.reason && { reason: input.reason },
166
+ ...input.action && { action: input.action }
167
+ };
168
+ }
262
169
  }
263
170
  };
264
171
  }
@@ -269,6 +176,23 @@ function explain(input) {
269
176
  concept: input.concept,
270
177
  explanation: input.explanation,
271
178
  ...input.therefore && { therefore: input.therefore }
179
+ },
180
+ codec: {
181
+ encode() {
182
+ return {
183
+ type: "explain",
184
+ concept: input.concept,
185
+ explanation: input.explanation,
186
+ ...input.therefore && { therefore: input.therefore }
187
+ };
188
+ },
189
+ decode() {
190
+ return {
191
+ concept: input.concept,
192
+ explanation: input.explanation,
193
+ ...input.therefore && { therefore: input.therefore }
194
+ };
195
+ }
272
196
  }
273
197
  };
274
198
  }
@@ -279,6 +203,23 @@ function example(input) {
279
203
  question: input.question,
280
204
  answer: input.answer,
281
205
  ...input.note && { note: input.note }
206
+ },
207
+ codec: {
208
+ encode() {
209
+ return {
210
+ type: "example",
211
+ question: input.question,
212
+ answer: input.answer,
213
+ ...input.note && { note: input.note }
214
+ };
215
+ },
216
+ decode() {
217
+ return {
218
+ question: input.question,
219
+ answer: input.answer,
220
+ ...input.note && { note: input.note }
221
+ };
222
+ }
282
223
  }
283
224
  };
284
225
  }
@@ -289,6 +230,23 @@ function clarification(input) {
289
230
  when: input.when,
290
231
  ask: input.ask,
291
232
  reason: input.reason
233
+ },
234
+ codec: {
235
+ encode() {
236
+ return {
237
+ type: "clarification",
238
+ when: input.when,
239
+ ask: input.ask,
240
+ reason: input.reason
241
+ };
242
+ },
243
+ decode() {
244
+ return {
245
+ when: input.when,
246
+ ask: input.ask,
247
+ reason: input.reason
248
+ };
249
+ }
292
250
  }
293
251
  };
294
252
  }
@@ -300,6 +258,25 @@ function workflow(input) {
300
258
  steps: input.steps,
301
259
  ...input.triggers?.length && { triggers: input.triggers },
302
260
  ...input.notes && { notes: input.notes }
261
+ },
262
+ codec: {
263
+ encode() {
264
+ return {
265
+ type: "workflow",
266
+ task: input.task,
267
+ steps: input.steps,
268
+ ...input.triggers?.length && { triggers: input.triggers },
269
+ ...input.notes && { notes: input.notes }
270
+ };
271
+ },
272
+ decode() {
273
+ return {
274
+ task: input.task,
275
+ steps: input.steps,
276
+ ...input.triggers?.length && { triggers: input.triggers },
277
+ ...input.notes && { notes: input.notes }
278
+ };
279
+ }
303
280
  }
304
281
  };
305
282
  }
@@ -309,6 +286,21 @@ function quirk(input) {
309
286
  data: {
310
287
  issue: input.issue,
311
288
  workaround: input.workaround
289
+ },
290
+ codec: {
291
+ encode() {
292
+ return {
293
+ type: "quirk",
294
+ issue: input.issue,
295
+ workaround: input.workaround
296
+ };
297
+ },
298
+ decode() {
299
+ return {
300
+ issue: input.issue,
301
+ workaround: input.workaround
302
+ };
303
+ }
312
304
  }
313
305
  };
314
306
  }
@@ -319,6 +311,23 @@ function styleGuide(input) {
319
311
  prefer: input.prefer,
320
312
  ...input.never && { never: input.never },
321
313
  ...input.always && { always: input.always }
314
+ },
315
+ codec: {
316
+ encode() {
317
+ return {
318
+ type: "styleGuide",
319
+ prefer: input.prefer,
320
+ ...input.never && { never: input.never },
321
+ ...input.always && { always: input.always }
322
+ };
323
+ },
324
+ decode() {
325
+ return {
326
+ prefer: input.prefer,
327
+ ...input.never && { never: input.never },
328
+ ...input.always && { always: input.always }
329
+ };
330
+ }
322
331
  }
323
332
  };
324
333
  }
@@ -331,43 +340,562 @@ function analogy(input) {
331
340
  ...input.insight && { insight: input.insight },
332
341
  ...input.therefore && { therefore: input.therefore },
333
342
  ...input.pitfall && { pitfall: input.pitfall }
343
+ },
344
+ codec: {
345
+ encode() {
346
+ return {
347
+ type: "analogy",
348
+ concepts: input.concepts,
349
+ relationship: input.relationship,
350
+ ...input.insight && { insight: input.insight },
351
+ ...input.therefore && { therefore: input.therefore },
352
+ ...input.pitfall && { pitfall: input.pitfall }
353
+ };
354
+ },
355
+ decode() {
356
+ return {
357
+ concepts: input.concepts,
358
+ relationship: input.relationship,
359
+ ...input.insight && { insight: input.insight },
360
+ ...input.therefore && { therefore: input.therefore },
361
+ ...input.pitfall && { pitfall: input.pitfall }
362
+ };
363
+ }
364
+ }
365
+ };
366
+ }
367
+ function glossary(entries) {
368
+ return {
369
+ name: "glossary",
370
+ data: Object.entries(entries).map(([term2, expression]) => ({
371
+ term: term2,
372
+ expression
373
+ })),
374
+ codec: {
375
+ encode() {
376
+ return { type: "glossary", entries };
377
+ },
378
+ decode() {
379
+ return Object.entries(entries).map(([term2, expression]) => ({
380
+ term: term2,
381
+ expression
382
+ }));
383
+ }
384
+ }
385
+ };
386
+ }
387
+ function role(content) {
388
+ return {
389
+ name: "role",
390
+ data: content,
391
+ codec: {
392
+ encode() {
393
+ return { type: "role", content };
394
+ },
395
+ decode() {
396
+ return content;
397
+ }
398
+ }
399
+ };
400
+ }
401
+ function principle(input) {
402
+ return {
403
+ name: "principle",
404
+ data: {
405
+ title: input.title,
406
+ description: input.description,
407
+ ...input.policies?.length && { policies: input.policies }
408
+ },
409
+ codec: {
410
+ encode() {
411
+ return {
412
+ type: "principle",
413
+ title: input.title,
414
+ description: input.description,
415
+ ...input.policies?.length && {
416
+ policies: input.policies.map((item) => encodeSerializedValue(item))
417
+ }
418
+ };
419
+ },
420
+ decode() {
421
+ return {
422
+ title: input.title,
423
+ description: input.description,
424
+ ...input.policies?.length && { policies: input.policies }
425
+ };
426
+ }
427
+ }
428
+ };
429
+ }
430
+ function policy(input) {
431
+ return {
432
+ name: "policy",
433
+ data: {
434
+ rule: input.rule,
435
+ ...input.before && { before: input.before },
436
+ ...input.reason && { reason: input.reason },
437
+ ...input.policies?.length && { policies: input.policies }
438
+ },
439
+ codec: {
440
+ encode() {
441
+ return {
442
+ type: "policy",
443
+ rule: input.rule,
444
+ ...input.before && { before: input.before },
445
+ ...input.reason && { reason: input.reason },
446
+ ...input.policies?.length && {
447
+ policies: input.policies.map((item) => encodeSerializedValue(item))
448
+ }
449
+ };
450
+ },
451
+ decode() {
452
+ return {
453
+ rule: input.rule,
454
+ ...input.before && { before: input.before },
455
+ ...input.reason && { reason: input.reason },
456
+ ...input.policies?.length && { policies: input.policies }
457
+ };
458
+ }
459
+ }
460
+ };
461
+ }
462
+
463
+ // packages/context/src/lib/fragments/user.ts
464
+ function identity(input) {
465
+ return {
466
+ name: "identity",
467
+ data: {
468
+ ...input.name && { name: input.name },
469
+ ...input.role && { role: input.role }
470
+ },
471
+ codec: {
472
+ encode() {
473
+ return {
474
+ type: "identity",
475
+ ...input.name && { name: input.name },
476
+ ...input.role && { role: input.role }
477
+ };
478
+ },
479
+ decode() {
480
+ return {
481
+ ...input.name && { name: input.name },
482
+ ...input.role && { role: input.role }
483
+ };
484
+ }
485
+ }
486
+ };
487
+ }
488
+ function persona(input) {
489
+ return {
490
+ name: "persona",
491
+ data: {
492
+ name: input.name,
493
+ ...input.role && { role: input.role },
494
+ ...input.objective && { objective: input.objective },
495
+ ...input.tone && { tone: input.tone }
496
+ },
497
+ codec: {
498
+ encode() {
499
+ return {
500
+ type: "persona",
501
+ name: input.name,
502
+ ...input.role && { role: input.role },
503
+ ...input.objective && { objective: input.objective },
504
+ ...input.tone && { tone: input.tone }
505
+ };
506
+ },
507
+ decode() {
508
+ return {
509
+ name: input.name,
510
+ ...input.role && { role: input.role },
511
+ ...input.objective && { objective: input.objective },
512
+ ...input.tone && { tone: input.tone }
513
+ };
514
+ }
515
+ }
516
+ };
517
+ }
518
+ function alias(term2, meaning) {
519
+ return {
520
+ name: "alias",
521
+ data: { term: term2, meaning },
522
+ codec: {
523
+ encode() {
524
+ return { type: "alias", term: term2, meaning };
525
+ },
526
+ decode() {
527
+ return { term: term2, meaning };
528
+ }
529
+ }
530
+ };
531
+ }
532
+ function preference(aspect, value) {
533
+ return {
534
+ name: "preference",
535
+ data: { aspect, value },
536
+ codec: {
537
+ encode() {
538
+ return { type: "preference", aspect, value };
539
+ },
540
+ decode() {
541
+ return { aspect, value };
542
+ }
543
+ }
544
+ };
545
+ }
546
+ function correction(subject, clarification2) {
547
+ return {
548
+ name: "correction",
549
+ data: { subject, clarification: clarification2 },
550
+ codec: {
551
+ encode() {
552
+ return { type: "correction", subject, clarification: clarification2 };
553
+ },
554
+ decode() {
555
+ return { subject, clarification: clarification2 };
556
+ }
557
+ }
558
+ };
559
+ }
560
+
561
+ // packages/context/src/lib/codec/serialized-fragments.ts
562
+ function isSerializedFragmentLike(value) {
563
+ return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
564
+ }
565
+ function toFragmentData(value, options) {
566
+ if (isSerializedFragmentLike(value)) {
567
+ return toFragment(value, options);
568
+ }
569
+ if (Array.isArray(value)) {
570
+ return value.map((item) => toFragmentData(item, options));
571
+ }
572
+ if (isFragmentObject(value)) {
573
+ return Object.fromEntries(
574
+ Object.entries(value).map(([key, entry]) => [
575
+ key,
576
+ toFragmentData(entry, options)
577
+ ])
578
+ );
579
+ }
580
+ return value;
581
+ }
582
+ var builtInSerializedRegistry = {
583
+ term: {
584
+ toFragment: (input) => term(input.name, input.definition)
585
+ },
586
+ hint: {
587
+ toFragment: (input) => hint(input.text)
588
+ },
589
+ guardrail: {
590
+ toFragment: (input) => guardrail({
591
+ rule: input.rule,
592
+ reason: input.reason,
593
+ action: input.action
594
+ })
595
+ },
596
+ explain: {
597
+ toFragment: (input) => explain({
598
+ concept: input.concept,
599
+ explanation: input.explanation,
600
+ therefore: input.therefore
601
+ })
602
+ },
603
+ example: {
604
+ toFragment: (input) => example({
605
+ question: input.question,
606
+ answer: input.answer,
607
+ note: input.note
608
+ })
609
+ },
610
+ clarification: {
611
+ toFragment: (input) => clarification({
612
+ when: input.when,
613
+ ask: input.ask,
614
+ reason: input.reason
615
+ })
616
+ },
617
+ workflow: {
618
+ toFragment: (input) => workflow({
619
+ task: input.task,
620
+ steps: input.steps,
621
+ triggers: input.triggers,
622
+ notes: input.notes
623
+ })
624
+ },
625
+ quirk: {
626
+ toFragment: (input) => quirk({
627
+ issue: input.issue,
628
+ workaround: input.workaround
629
+ })
630
+ },
631
+ styleGuide: {
632
+ toFragment: (input) => styleGuide({
633
+ prefer: input.prefer,
634
+ never: input.never,
635
+ always: input.always
636
+ })
637
+ },
638
+ analogy: {
639
+ toFragment: (input) => analogy({
640
+ concepts: input.concepts,
641
+ relationship: input.relationship,
642
+ insight: input.insight,
643
+ therefore: input.therefore,
644
+ pitfall: input.pitfall
645
+ })
646
+ },
647
+ glossary: {
648
+ toFragment: (input) => glossary(input.entries)
649
+ },
650
+ role: {
651
+ toFragment: (input) => role(input.content)
652
+ },
653
+ principle: {
654
+ toFragment: (input, options) => principle({
655
+ title: input.title,
656
+ description: input.description,
657
+ policies: input.policies?.map((item) => toFragmentData(item, options))
658
+ })
659
+ },
660
+ policy: {
661
+ toFragment: (input, options) => policy({
662
+ rule: input.rule,
663
+ before: input.before,
664
+ reason: input.reason,
665
+ policies: input.policies?.map((item) => toFragmentData(item, options))
666
+ })
667
+ },
668
+ identity: {
669
+ toFragment: (input) => identity({
670
+ name: input.name,
671
+ role: input.role
672
+ })
673
+ },
674
+ persona: {
675
+ toFragment: (input) => persona({
676
+ name: input.name,
677
+ role: input.role,
678
+ objective: input.objective,
679
+ tone: input.tone
680
+ })
681
+ },
682
+ alias: {
683
+ toFragment: (input) => alias(input.term, input.meaning)
684
+ },
685
+ preference: {
686
+ toFragment: (input) => preference(input.aspect, input.value)
687
+ },
688
+ correction: {
689
+ toFragment: (input) => correction(input.subject, input.clarification)
690
+ }
691
+ };
692
+ var messageLikeTypes = /* @__PURE__ */ new Set(["user", "assistant", "message"]);
693
+ function findCustomSerializedFragment(fragment2, options) {
694
+ if (!options?.registry) {
695
+ return void 0;
696
+ }
697
+ for (const entry of Object.values(options.registry)) {
698
+ const serialized = entry.fromFragment?.(fragment2, options);
699
+ if (serialized !== void 0) {
700
+ return serialized;
334
701
  }
335
- };
702
+ }
703
+ return void 0;
336
704
  }
337
- function glossary(entries) {
338
- return {
339
- name: "glossary",
340
- data: Object.entries(entries).map(([term2, expression]) => ({
341
- term: term2,
342
- expression
343
- }))
344
- };
705
+ function toFragment(input, options) {
706
+ if (messageLikeTypes.has(input.type)) {
707
+ throw new Error(
708
+ "Message fragments are not supported by serialized fragment conversion"
709
+ );
710
+ }
711
+ const entry = options?.registry?.[input.type] ?? builtInSerializedRegistry[input.type];
712
+ if (!entry) {
713
+ throw new Error(`Unsupported serialized fragment type: ${input.type}`);
714
+ }
715
+ return entry.toFragment(input, options);
345
716
  }
346
- function role(content) {
347
- return {
348
- name: "role",
349
- data: content
350
- };
717
+ function fromFragment(fragment2, options) {
718
+ if (isMessageFragment(fragment2)) {
719
+ throw new Error(
720
+ "Message fragments are not supported by serialized fragment conversion"
721
+ );
722
+ }
723
+ const customSerialized = findCustomSerializedFragment(fragment2, options);
724
+ if (customSerialized !== void 0) {
725
+ return customSerialized;
726
+ }
727
+ if (fragment2.codec) {
728
+ const encoded = fragment2.codec.encode();
729
+ if (!isSerializedFragmentLike(encoded)) {
730
+ throw new Error(
731
+ `Fragment "${fragment2.name}" codec must encode to a serialized fragment object`
732
+ );
733
+ }
734
+ return encoded;
735
+ }
736
+ if (!builtInSerializedRegistry[fragment2.name]) {
737
+ throw new Error(`Unsupported fragment name: ${fragment2.name}`);
738
+ }
739
+ throw new Error(`Fragment "${fragment2.name}" is missing codec`);
351
740
  }
352
- function principle(input) {
353
- return {
354
- name: "principle",
355
- data: {
356
- title: input.title,
357
- description: input.description,
358
- ...input.policies?.length && { policies: input.policies }
741
+
742
+ // packages/context/src/lib/estimate.ts
743
+ import { encode } from "gpt-tokenizer";
744
+ var defaultTokenizer = {
745
+ encode(text) {
746
+ return encode(text);
747
+ },
748
+ count(text) {
749
+ return encode(text).length;
750
+ }
751
+ };
752
+ var ModelsRegistry = class {
753
+ #cache = /* @__PURE__ */ new Map();
754
+ #loaded = false;
755
+ #tokenizers = /* @__PURE__ */ new Map();
756
+ #defaultTokenizer = defaultTokenizer;
757
+ /**
758
+ * Load models data from models.dev API
759
+ */
760
+ async load() {
761
+ if (this.#loaded) return;
762
+ const response = await fetch("https://models.dev/api.json");
763
+ if (!response.ok) {
764
+ throw new Error(`Failed to fetch models: ${response.statusText}`);
359
765
  }
360
- };
766
+ const data = await response.json();
767
+ for (const [providerId, provider] of Object.entries(data)) {
768
+ for (const [modelId, model] of Object.entries(provider.models)) {
769
+ const info = {
770
+ id: model.id,
771
+ name: model.name,
772
+ family: model.family,
773
+ cost: model.cost,
774
+ limit: model.limit,
775
+ provider: providerId
776
+ };
777
+ this.#cache.set(`${providerId}:${modelId}`, info);
778
+ }
779
+ }
780
+ this.#loaded = true;
781
+ }
782
+ /**
783
+ * Get model info by ID
784
+ * @param modelId - Model ID (e.g., "openai:gpt-4o")
785
+ */
786
+ get(modelId) {
787
+ return this.#cache.get(modelId);
788
+ }
789
+ /**
790
+ * Check if a model exists in the registry
791
+ */
792
+ has(modelId) {
793
+ return this.#cache.has(modelId);
794
+ }
795
+ /**
796
+ * List all available model IDs
797
+ */
798
+ list() {
799
+ return [...this.#cache.keys()];
800
+ }
801
+ /**
802
+ * Register a custom tokenizer for specific model families
803
+ * @param family - Model family name (e.g., "llama", "claude")
804
+ * @param tokenizer - Tokenizer implementation
805
+ */
806
+ registerTokenizer(family, tokenizer) {
807
+ this.#tokenizers.set(family, tokenizer);
808
+ }
809
+ /**
810
+ * Set the default tokenizer used when no family-specific tokenizer is registered
811
+ */
812
+ setDefaultTokenizer(tokenizer) {
813
+ this.#defaultTokenizer = tokenizer;
814
+ }
815
+ /**
816
+ * Get the appropriate tokenizer for a model
817
+ */
818
+ getTokenizer(modelId) {
819
+ const model = this.get(modelId);
820
+ if (model) {
821
+ const familyTokenizer = this.#tokenizers.get(model.family);
822
+ if (familyTokenizer) {
823
+ return familyTokenizer;
824
+ }
825
+ }
826
+ return this.#defaultTokenizer;
827
+ }
828
+ /**
829
+ * Estimate token count and cost for given text and model
830
+ * @param modelId - Model ID to use for pricing (e.g., "openai:gpt-4o")
831
+ * @param input - Input text (prompt)
832
+ */
833
+ estimate(modelId, input) {
834
+ const model = this.get(modelId);
835
+ if (!model) {
836
+ throw new Error(
837
+ `Model "${modelId}" not found. Call load() first or check model ID.`
838
+ );
839
+ }
840
+ const tokenizer = this.getTokenizer(modelId);
841
+ const tokens = tokenizer.count(input);
842
+ const cost = tokens / 1e6 * model.cost.input;
843
+ return {
844
+ model: model.id,
845
+ provider: model.provider,
846
+ tokens,
847
+ cost,
848
+ limits: {
849
+ context: model.limit.context,
850
+ output: model.limit.output,
851
+ exceedsContext: tokens > model.limit.context
852
+ },
853
+ fragments: []
854
+ };
855
+ }
856
+ };
857
+ var _registry = null;
858
+ function getModelsRegistry() {
859
+ if (!_registry) {
860
+ _registry = new ModelsRegistry();
861
+ }
862
+ return _registry;
361
863
  }
362
- function policy(input) {
864
+ async function estimate(modelId, renderer, ...fragments) {
865
+ const registry = getModelsRegistry();
866
+ await registry.load();
867
+ const input = renderer.render(fragments);
868
+ const model = registry.get(modelId);
869
+ if (!model) {
870
+ throw new Error(
871
+ `Model "${modelId}" not found. Call load() first or check model ID.`
872
+ );
873
+ }
874
+ const tokenizer = registry.getTokenizer(modelId);
875
+ const totalTokens = tokenizer.count(input);
876
+ const totalCost = totalTokens / 1e6 * model.cost.input;
877
+ const fragmentEstimates = fragments.map((fragment2) => {
878
+ const rendered = renderer.render([fragment2]);
879
+ const tokens = tokenizer.count(rendered);
880
+ const cost = tokens / 1e6 * model.cost.input;
881
+ return {
882
+ id: fragment2.id,
883
+ name: fragment2.name,
884
+ tokens,
885
+ cost
886
+ };
887
+ });
363
888
  return {
364
- name: "policy",
365
- data: {
366
- rule: input.rule,
367
- ...input.before && { before: input.before },
368
- ...input.reason && { reason: input.reason },
369
- ...input.policies?.length && { policies: input.policies }
370
- }
889
+ model: model.id,
890
+ provider: model.provider,
891
+ tokens: totalTokens,
892
+ cost: totalCost,
893
+ limits: {
894
+ context: model.limit.context,
895
+ output: model.limit.output,
896
+ exceedsContext: totalTokens > model.limit.context
897
+ },
898
+ fragments: fragmentEstimates
371
899
  };
372
900
  }
373
901
 
@@ -507,26 +1035,51 @@ function applyPartReminder(message2, value) {
507
1035
  mode: "part"
508
1036
  };
509
1037
  }
1038
+ function hasSchedule(reminder2) {
1039
+ return reminder2.everyNTurns !== void 0 || reminder2.once !== void 0 || reminder2.firstN !== void 0 || reminder2.afterTurn !== void 0 || reminder2.when !== void 0;
1040
+ }
1041
+ function shouldIncludeReminder(reminder2, turn) {
1042
+ if (reminder2.once && turn !== 1) return false;
1043
+ if (reminder2.firstN !== void 0 && turn > reminder2.firstN) return false;
1044
+ if (reminder2.afterTurn !== void 0 && turn <= reminder2.afterTurn)
1045
+ return false;
1046
+ if (reminder2.everyNTurns !== void 0 && turn % reminder2.everyNTurns !== 0)
1047
+ return false;
1048
+ if (reminder2.when && !reminder2.when(turn)) return false;
1049
+ return true;
1050
+ }
510
1051
  function reminder(text, options) {
511
1052
  if (typeof text === "string") {
512
1053
  assertReminderText(text);
513
1054
  }
514
1055
  return {
515
1056
  text,
516
- asPart: options?.asPart ?? false
1057
+ asPart: options?.asPart ?? false,
1058
+ ...options?.everyNTurns !== void 0 && {
1059
+ everyNTurns: options.everyNTurns
1060
+ },
1061
+ ...options?.once !== void 0 && { once: options.once },
1062
+ ...options?.firstN !== void 0 && { firstN: options.firstN },
1063
+ ...options?.afterTurn !== void 0 && { afterTurn: options.afterTurn },
1064
+ ...options?.when !== void 0 && { when: options.when }
517
1065
  };
518
1066
  }
1067
+ function resolveReminderText(item, ctx) {
1068
+ return typeof item.text === "function" ? item.text(ctx) : item.text;
1069
+ }
519
1070
  function user(content, ...reminders) {
520
1071
  const message2 = typeof content === "string" ? {
521
1072
  id: generateId2(),
522
1073
  role: "user",
523
1074
  parts: [{ type: "text", text: content }]
524
1075
  } : { ...content, role: "user", parts: [...content.parts] };
525
- if (reminders.length > 0) {
1076
+ const immediateReminders = reminders.filter((r) => !hasSchedule(r));
1077
+ const scheduledReminders = reminders.filter((r) => hasSchedule(r));
1078
+ if (immediateReminders.length > 0) {
526
1079
  const addedReminders = [];
527
1080
  const plainText = extractPlainText(message2);
528
- for (const item of reminders) {
529
- const resolvedText = typeof item.text === "function" ? item.text(plainText) : item.text;
1081
+ for (const item of immediateReminders) {
1082
+ const resolvedText = resolveReminderText(item, { content: plainText });
530
1083
  if (resolvedText.trim().length === 0) {
531
1084
  continue;
532
1085
  }
@@ -541,10 +1094,10 @@ function user(content, ...reminders) {
541
1094
  message2.metadata = metadata;
542
1095
  }
543
1096
  }
1097
+ const fragmentMetadata = scheduledReminders.length > 0 ? { scheduledReminders } : void 0;
544
1098
  return {
545
1099
  id: message2.id,
546
1100
  name: "user",
547
- data: "content",
548
1101
  type: "message",
549
1102
  persist: true,
550
1103
  codec: {
@@ -554,53 +1107,8 @@ function user(content, ...reminders) {
554
1107
  encode() {
555
1108
  return message2;
556
1109
  }
557
- }
558
- };
559
- }
560
-
561
- // packages/context/src/lib/fragments/user.ts
562
- function identity(input) {
563
- return {
564
- name: "identity",
565
- data: {
566
- ...input.name && { name: input.name },
567
- ...input.role && { role: input.role }
568
- }
569
- };
570
- }
571
- function persona(input) {
572
- return {
573
- name: "persona",
574
- data: {
575
- name: input.name,
576
- ...input.role && { role: input.role },
577
- ...input.objective && { objective: input.objective },
578
- ...input.tone && { tone: input.tone }
579
- }
580
- };
581
- }
582
- function alias(term2, meaning) {
583
- return {
584
- name: "alias",
585
- data: { term: term2, meaning }
586
- };
587
- }
588
- function preference(aspect, value) {
589
- return {
590
- name: "preference",
591
- data: { aspect, value }
592
- };
593
- }
594
- function userContext(description) {
595
- return {
596
- name: "userContext",
597
- data: description
598
- };
599
- }
600
- function correction(subject, clarification2) {
601
- return {
602
- name: "correction",
603
- data: { subject, clarification: clarification2 }
1110
+ },
1111
+ metadata: fragmentMetadata
604
1112
  };
605
1113
  }
606
1114
 
@@ -668,7 +1176,7 @@ var ContextRenderer = class {
668
1176
  return sanitized;
669
1177
  }
670
1178
  sanitizeFragment(fragment2, seen) {
671
- const data = this.sanitizeData(fragment2.data, seen);
1179
+ const data = this.sanitizeData(getFragmentData(fragment2), seen);
672
1180
  if (data == null) {
673
1181
  return null;
674
1182
  }
@@ -745,12 +1253,13 @@ var XmlRenderer = class extends ContextRenderer {
745
1253
  return sanitized.map((f) => this.#renderTopLevel(f)).filter(Boolean).join("\n");
746
1254
  }
747
1255
  #renderTopLevel(fragment2) {
748
- if (this.isPrimitive(fragment2.data)) {
749
- return this.#leafRoot(fragment2.name, String(fragment2.data));
1256
+ const data = getFragmentData(fragment2);
1257
+ if (this.isPrimitive(data)) {
1258
+ return this.#leafRoot(fragment2.name, String(data));
750
1259
  }
751
- if (Array.isArray(fragment2.data)) {
752
- if (fragment2.data.length === 1) {
753
- const single = fragment2.data[0];
1260
+ if (Array.isArray(data)) {
1261
+ if (data.length === 1) {
1262
+ const single = data[0];
754
1263
  if (this.isPrimitive(single)) {
755
1264
  return this.#leafRoot(fragment2.name, String(single));
756
1265
  }
@@ -768,19 +1277,15 @@ var XmlRenderer = class extends ContextRenderer {
768
1277
  );
769
1278
  }
770
1279
  }
771
- return this.#renderArray(fragment2.name, fragment2.data, 0);
1280
+ return this.#renderArray(fragment2.name, data, 0);
772
1281
  }
773
- if (isFragment(fragment2.data)) {
774
- return this.#renderFragmentContentsUnderParent(
775
- fragment2.name,
776
- fragment2.data,
777
- 0
778
- );
1282
+ if (isFragment(data)) {
1283
+ return this.#renderFragmentContentsUnderParent(fragment2.name, data, 0);
779
1284
  }
780
- if (isFragmentObject(fragment2.data)) {
1285
+ if (isFragmentObject(data)) {
781
1286
  return this.#wrap(
782
1287
  fragment2.name,
783
- this.renderEntries(fragment2.data, { depth: 1, path: [] })
1288
+ this.renderEntries(data, { depth: 1, path: [] })
784
1289
  );
785
1290
  }
786
1291
  return "";
@@ -912,23 +1417,23 @@ ${this.#indent(safe, 2)}
912
1417
  return `<${tag}>${safe}</${tag}>`;
913
1418
  }
914
1419
  renderFragment(fragment2, ctx) {
915
- const { name, data } = fragment2;
1420
+ const data = getFragmentData(fragment2);
916
1421
  if (this.isPrimitive(data)) {
917
- return this.#leaf(name, String(data), ctx.depth);
1422
+ return this.#leaf(fragment2.name, String(data), ctx.depth);
918
1423
  }
919
1424
  if (isFragment(data)) {
920
1425
  const child = this.renderFragment(data, { ...ctx, depth: ctx.depth + 1 });
921
- return this.#wrapIndented(name, [child], ctx.depth);
1426
+ return this.#wrapIndented(fragment2.name, [child], ctx.depth);
922
1427
  }
923
1428
  if (Array.isArray(data)) {
924
- return this.#renderArrayIndented(name, data, ctx.depth);
1429
+ return this.#renderArrayIndented(fragment2.name, data, ctx.depth);
925
1430
  }
926
1431
  if (isFragmentObject(data)) {
927
1432
  const children = this.renderEntries(data, {
928
1433
  ...ctx,
929
1434
  depth: ctx.depth + 1
930
1435
  });
931
- return this.#wrapIndented(name, children, ctx.depth);
1436
+ return this.#wrapIndented(fragment2.name, children, ctx.depth);
932
1437
  }
933
1438
  return "";
934
1439
  }
@@ -1045,21 +1550,22 @@ var MarkdownRenderer = class extends ContextRenderer {
1045
1550
  render(fragments) {
1046
1551
  return this.sanitizeFragments(fragments).map((f) => {
1047
1552
  const title = `## ${titlecase(f.name)}`;
1048
- if (this.isPrimitive(f.data)) {
1553
+ const data = getFragmentData(f);
1554
+ if (this.isPrimitive(data)) {
1049
1555
  return `${title}
1050
- ${String(f.data)}`;
1556
+ ${String(data)}`;
1051
1557
  }
1052
- if (Array.isArray(f.data)) {
1558
+ if (Array.isArray(data)) {
1053
1559
  return `${title}
1054
- ${this.#renderArray(f.data, 0)}`;
1560
+ ${this.#renderArray(data, 0)}`;
1055
1561
  }
1056
- if (isFragment(f.data)) {
1562
+ if (isFragment(data)) {
1057
1563
  return `${title}
1058
- ${this.renderFragment(f.data, { depth: 0, path: [] })}`;
1564
+ ${this.renderFragment(data, { depth: 0, path: [] })}`;
1059
1565
  }
1060
- if (isFragmentObject(f.data)) {
1566
+ if (isFragmentObject(data)) {
1061
1567
  return `${title}
1062
- ${this.renderEntries(f.data, { depth: 0, path: [] }).join("\n")}`;
1568
+ ${this.renderEntries(data, { depth: 0, path: [] }).join("\n")}`;
1063
1569
  }
1064
1570
  return `${title}
1065
1571
  `;
@@ -1109,10 +1615,10 @@ ${this.renderEntries(f.data, { depth: 0, path: [] }).join("\n")}`;
1109
1615
  return `${this.#pad(depth)}- ${String(item)}`;
1110
1616
  }
1111
1617
  renderFragment(fragment2, ctx) {
1112
- const { name, data } = fragment2;
1113
- const header = `${this.#pad(ctx.depth)}- **${name}**:`;
1618
+ const data = getFragmentData(fragment2);
1619
+ const header = `${this.#pad(ctx.depth)}- **${fragment2.name}**:`;
1114
1620
  if (this.isPrimitive(data)) {
1115
- return `${this.#pad(ctx.depth)}- **${name}**: ${String(data)}`;
1621
+ return `${this.#pad(ctx.depth)}- **${fragment2.name}**: ${String(data)}`;
1116
1622
  }
1117
1623
  if (isFragment(data)) {
1118
1624
  const child = this.renderFragment(data, { ...ctx, depth: ctx.depth + 1 });
@@ -1151,21 +1657,22 @@ ${this.renderEntries(f.data, { depth: 0, path: [] }).join("\n")}`;
1151
1657
  var TomlRenderer = class extends ContextRenderer {
1152
1658
  render(fragments) {
1153
1659
  const rendered = [];
1154
- for (const f of this.sanitizeFragments(fragments)) {
1155
- if (this.isPrimitive(f.data)) {
1156
- rendered.push(`${f.name} = ${this.#formatValue(f.data)}`);
1157
- } else if (Array.isArray(f.data)) {
1158
- rendered.push(this.#renderTopLevelArray(f.name, f.data));
1159
- } else if (isFragment(f.data)) {
1660
+ for (const it of this.sanitizeFragments(fragments)) {
1661
+ const data = getFragmentData(it);
1662
+ if (this.isPrimitive(data)) {
1663
+ rendered.push(`${it.name} = ${this.#formatValue(data)}`);
1664
+ } else if (Array.isArray(data)) {
1665
+ rendered.push(this.#renderTopLevelArray(it.name, data));
1666
+ } else if (isFragment(data)) {
1160
1667
  rendered.push(
1161
1668
  [
1162
- `[${f.name}]`,
1163
- this.renderFragment(f.data, { depth: 0, path: [f.name] })
1669
+ `[${it.name}]`,
1670
+ this.renderFragment(data, { depth: 0, path: [it.name] })
1164
1671
  ].join("\n")
1165
1672
  );
1166
- } else if (isFragmentObject(f.data)) {
1167
- const entries = this.#renderObjectEntries(f.data, [f.name]);
1168
- rendered.push([`[${f.name}]`, ...entries].join("\n"));
1673
+ } else if (isFragmentObject(data)) {
1674
+ const entries = this.#renderObjectEntries(data, [it.name]);
1675
+ rendered.push([`[${it.name}]`, ...entries].join("\n"));
1169
1676
  }
1170
1677
  }
1171
1678
  return rendered.join("\n\n");
@@ -1235,10 +1742,10 @@ var TomlRenderer = class extends ContextRenderer {
1235
1742
  }).filter(Boolean);
1236
1743
  }
1237
1744
  renderFragment(fragment2, ctx) {
1238
- const { name, data } = fragment2;
1239
- const newPath = [...ctx.path, name];
1745
+ const data = getFragmentData(fragment2);
1746
+ const newPath = [...ctx.path, fragment2.name];
1240
1747
  if (this.isPrimitive(data)) {
1241
- return `${name} = ${this.#formatValue(data)}`;
1748
+ return `${fragment2.name} = ${this.#formatValue(data)}`;
1242
1749
  }
1243
1750
  if (isFragment(data)) {
1244
1751
  return [
@@ -1260,7 +1767,7 @@ var TomlRenderer = class extends ContextRenderer {
1260
1767
  return parts.join("\n");
1261
1768
  }
1262
1769
  const values = nonFragmentItems.map((item) => this.#formatValue(item));
1263
- return `${name} = [${values.join(", ")}]`;
1770
+ return `${fragment2.name} = [${values.join(", ")}]`;
1264
1771
  }
1265
1772
  if (isFragmentObject(data)) {
1266
1773
  const entries = this.#renderObjectEntries(data, newPath);
@@ -1290,27 +1797,27 @@ var ToonRenderer = class extends ContextRenderer {
1290
1797
  return sanitized.map((f) => this.#renderTopLevel(f)).filter(Boolean).join("\n");
1291
1798
  }
1292
1799
  #renderTopLevel(fragment2) {
1293
- const { name, data } = fragment2;
1800
+ const data = getFragmentData(fragment2);
1294
1801
  if (this.isPrimitive(data)) {
1295
- return `${name}: ${this.#formatValue(data)}`;
1802
+ return `${fragment2.name}: ${this.#formatValue(data)}`;
1296
1803
  }
1297
1804
  if (Array.isArray(data)) {
1298
- return this.#renderArrayField(name, data, 0);
1805
+ return this.#renderArrayField(fragment2.name, data, 0);
1299
1806
  }
1300
1807
  if (isFragment(data)) {
1301
1808
  const child = this.renderFragment(data, { depth: 1, path: [] });
1302
- return `${name}:
1809
+ return `${fragment2.name}:
1303
1810
  ${child}`;
1304
1811
  }
1305
1812
  if (isFragmentObject(data)) {
1306
1813
  const entries = this.#renderObjectEntries(data, 1);
1307
1814
  if (!entries) {
1308
- return `${name}:`;
1815
+ return `${fragment2.name}:`;
1309
1816
  }
1310
- return `${name}:
1817
+ return `${fragment2.name}:
1311
1818
  ${entries}`;
1312
1819
  }
1313
- return `${name}:`;
1820
+ return `${fragment2.name}:`;
1314
1821
  }
1315
1822
  #renderArrayField(key, items, depth) {
1316
1823
  const filtered = items.filter((item) => item != null);
@@ -1385,8 +1892,9 @@ ${entries}`;
1385
1892
  depth: depth + 1,
1386
1893
  path: []
1387
1894
  });
1388
- if (this.isPrimitive(item.data)) {
1389
- return `${this.#pad(depth)}- ${item.name}: ${this.#formatValue(item.data)}`;
1895
+ const itemData = getFragmentData(item);
1896
+ if (this.isPrimitive(itemData)) {
1897
+ return `${this.#pad(depth)}- ${item.name}: ${this.#formatValue(itemData)}`;
1390
1898
  }
1391
1899
  return `${this.#pad(depth)}- ${item.name}:
1392
1900
  ${rendered.split("\n").slice(1).join("\n")}`;
@@ -1429,30 +1937,30 @@ ${nested}`);
1429
1937
  return lines.join("\n");
1430
1938
  }
1431
1939
  renderFragment(fragment2, ctx) {
1432
- const { name, data } = fragment2;
1940
+ const data = getFragmentData(fragment2);
1433
1941
  if (this.isPrimitive(data)) {
1434
- return `${this.#pad(ctx.depth)}${name}: ${this.#formatValue(data)}`;
1942
+ return `${this.#pad(ctx.depth)}${fragment2.name}: ${this.#formatValue(data)}`;
1435
1943
  }
1436
1944
  if (isFragment(data)) {
1437
1945
  const child = this.renderFragment(data, {
1438
1946
  ...ctx,
1439
1947
  depth: ctx.depth + 1
1440
1948
  });
1441
- return `${this.#pad(ctx.depth)}${name}:
1949
+ return `${this.#pad(ctx.depth)}${fragment2.name}:
1442
1950
  ${child}`;
1443
1951
  }
1444
1952
  if (Array.isArray(data)) {
1445
- return this.#renderArrayField(name, data, ctx.depth);
1953
+ return this.#renderArrayField(fragment2.name, data, ctx.depth);
1446
1954
  }
1447
1955
  if (isFragmentObject(data)) {
1448
1956
  const entries = this.#renderObjectEntries(data, ctx.depth + 1);
1449
1957
  if (!entries) {
1450
- return `${this.#pad(ctx.depth)}${name}:`;
1958
+ return `${this.#pad(ctx.depth)}${fragment2.name}:`;
1451
1959
  }
1452
- return `${this.#pad(ctx.depth)}${name}:
1960
+ return `${this.#pad(ctx.depth)}${fragment2.name}:
1453
1961
  ${entries}`;
1454
1962
  }
1455
- return `${this.#pad(ctx.depth)}${name}:`;
1963
+ return `${this.#pad(ctx.depth)}${fragment2.name}:`;
1456
1964
  }
1457
1965
  renderPrimitive(key, value, ctx) {
1458
1966
  return `${this.#pad(ctx.depth)}${key}: ${this.#formatValue(value)}`;
@@ -1668,6 +2176,8 @@ export {
1668
2176
  XmlRenderer,
1669
2177
  alias,
1670
2178
  analogy,
2179
+ applyInlineReminder,
2180
+ applyPartReminder,
1671
2181
  assistant,
1672
2182
  assistantText,
1673
2183
  clarification,
@@ -1678,10 +2188,13 @@ export {
1678
2188
  explain,
1679
2189
  fail,
1680
2190
  fragment,
2191
+ fromFragment,
2192
+ getFragmentData,
1681
2193
  getModelsRegistry,
1682
2194
  getReminderRanges,
1683
2195
  glossary,
1684
2196
  guardrail,
2197
+ hasSchedule,
1685
2198
  hint,
1686
2199
  identity,
1687
2200
  isFragment,
@@ -1699,16 +2212,18 @@ export {
1699
2212
  quirk,
1700
2213
  reminder,
1701
2214
  render,
2215
+ resolveReminderText,
1702
2216
  role,
1703
2217
  runGuardrailChain,
2218
+ shouldIncludeReminder,
1704
2219
  soul,
1705
2220
  stop,
1706
2221
  stripReminders,
1707
2222
  stripTextByRanges,
1708
2223
  styleGuide,
1709
2224
  term,
2225
+ toFragment,
1710
2226
  user,
1711
- userContext,
1712
2227
  visualizeGraph,
1713
2228
  workflow
1714
2229
  };