@deepagents/context 0.11.0 → 0.12.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/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +479 -134
- package/dist/index.js.map +4 -4
- package/dist/lib/agent.d.ts +7 -6
- package/dist/lib/agent.d.ts.map +1 -1
- package/dist/lib/engine.d.ts +7 -5
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/fragments/domain.d.ts +98 -1
- package/dist/lib/fragments/domain.d.ts.map +1 -1
- package/dist/lib/fragments/user.d.ts +8 -8
- package/dist/lib/fragments/user.d.ts.map +1 -1
- package/dist/lib/fragments.d.ts +2 -6
- package/dist/lib/fragments.d.ts.map +1 -1
- package/dist/lib/guardrails/error-recovery.guardrail.d.ts +3 -0
- package/dist/lib/guardrails/error-recovery.guardrail.d.ts.map +1 -0
- package/dist/lib/render.d.ts +21 -0
- package/dist/lib/render.d.ts.map +1 -0
- package/dist/lib/renderers/abstract.renderer.d.ts +10 -2
- package/dist/lib/renderers/abstract.renderer.d.ts.map +1 -1
- package/dist/lib/sandbox/binary-bridges.d.ts.map +1 -1
- package/dist/lib/skills/fragments.d.ts +1 -1
- package/dist/lib/skills/index.d.ts +1 -1
- package/dist/lib/skills/loader.d.ts.map +1 -1
- package/dist/lib/store/sqlite.store.d.ts +4 -2
- package/dist/lib/store/sqlite.store.d.ts.map +1 -1
- package/dist/lib/store/store.d.ts +36 -2
- package/dist/lib/store/store.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -175,12 +175,6 @@ function fragment(name, ...children) {
|
|
|
175
175
|
data: children
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
|
-
function role(content) {
|
|
179
|
-
return {
|
|
180
|
-
name: "role",
|
|
181
|
-
data: content
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
178
|
function user(content) {
|
|
185
179
|
const message2 = typeof content === "string" ? {
|
|
186
180
|
id: generateId(),
|
|
@@ -277,6 +271,68 @@ var ContextRenderer = class {
|
|
|
277
271
|
}
|
|
278
272
|
return groups;
|
|
279
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* Remove null/undefined from fragments and fragment data recursively.
|
|
276
|
+
* This protects renderers from nullish values and ensures they are ignored
|
|
277
|
+
* consistently across all output formats.
|
|
278
|
+
*/
|
|
279
|
+
sanitizeFragments(fragments) {
|
|
280
|
+
const sanitized = [];
|
|
281
|
+
for (const fragment2 of fragments) {
|
|
282
|
+
const cleaned = this.sanitizeFragment(fragment2, /* @__PURE__ */ new WeakSet());
|
|
283
|
+
if (cleaned) {
|
|
284
|
+
sanitized.push(cleaned);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return sanitized;
|
|
288
|
+
}
|
|
289
|
+
sanitizeFragment(fragment2, seen) {
|
|
290
|
+
const data = this.sanitizeData(fragment2.data, seen);
|
|
291
|
+
if (data == null) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
...fragment2,
|
|
296
|
+
data
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
sanitizeData(data, seen) {
|
|
300
|
+
if (data == null) {
|
|
301
|
+
return void 0;
|
|
302
|
+
}
|
|
303
|
+
if (isFragment(data)) {
|
|
304
|
+
return this.sanitizeFragment(data, seen) ?? void 0;
|
|
305
|
+
}
|
|
306
|
+
if (Array.isArray(data)) {
|
|
307
|
+
if (seen.has(data)) {
|
|
308
|
+
return void 0;
|
|
309
|
+
}
|
|
310
|
+
seen.add(data);
|
|
311
|
+
const cleaned = [];
|
|
312
|
+
for (const item of data) {
|
|
313
|
+
const sanitizedItem = this.sanitizeData(item, seen);
|
|
314
|
+
if (sanitizedItem != null) {
|
|
315
|
+
cleaned.push(sanitizedItem);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return cleaned;
|
|
319
|
+
}
|
|
320
|
+
if (isFragmentObject(data)) {
|
|
321
|
+
if (seen.has(data)) {
|
|
322
|
+
return void 0;
|
|
323
|
+
}
|
|
324
|
+
seen.add(data);
|
|
325
|
+
const cleaned = {};
|
|
326
|
+
for (const [key, value] of Object.entries(data)) {
|
|
327
|
+
const sanitizedValue = this.sanitizeData(value, seen);
|
|
328
|
+
if (sanitizedValue != null) {
|
|
329
|
+
cleaned[key] = sanitizedValue;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return cleaned;
|
|
333
|
+
}
|
|
334
|
+
return data;
|
|
335
|
+
}
|
|
280
336
|
/**
|
|
281
337
|
* Template method - dispatches value to appropriate handler.
|
|
282
338
|
*/
|
|
@@ -304,7 +360,8 @@ var ContextRenderer = class {
|
|
|
304
360
|
};
|
|
305
361
|
var XmlRenderer = class extends ContextRenderer {
|
|
306
362
|
render(fragments) {
|
|
307
|
-
|
|
363
|
+
const sanitized = this.sanitizeFragments(fragments);
|
|
364
|
+
return sanitized.map((f) => this.#renderTopLevel(f)).filter(Boolean).join("\n");
|
|
308
365
|
}
|
|
309
366
|
#renderTopLevel(fragment2) {
|
|
310
367
|
if (this.isPrimitive(fragment2.data)) {
|
|
@@ -317,10 +374,13 @@ var XmlRenderer = class extends ContextRenderer {
|
|
|
317
374
|
const child = this.renderFragment(fragment2.data, { depth: 1, path: [] });
|
|
318
375
|
return this.#wrap(fragment2.name, [child]);
|
|
319
376
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
377
|
+
if (isFragmentObject(fragment2.data)) {
|
|
378
|
+
return this.#wrap(
|
|
379
|
+
fragment2.name,
|
|
380
|
+
this.renderEntries(fragment2.data, { depth: 1, path: [] })
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
return "";
|
|
324
384
|
}
|
|
325
385
|
#renderArray(name, items, depth) {
|
|
326
386
|
const fragmentItems = items.filter(isFragment);
|
|
@@ -328,9 +388,19 @@ var XmlRenderer = class extends ContextRenderer {
|
|
|
328
388
|
const children = [];
|
|
329
389
|
for (const item of nonFragmentItems) {
|
|
330
390
|
if (item != null) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
391
|
+
if (isFragmentObject(item)) {
|
|
392
|
+
children.push(
|
|
393
|
+
this.#wrapIndented(
|
|
394
|
+
pluralize.singular(name),
|
|
395
|
+
this.renderEntries(item, { depth: depth + 2, path: [] }),
|
|
396
|
+
depth + 1
|
|
397
|
+
)
|
|
398
|
+
);
|
|
399
|
+
} else {
|
|
400
|
+
children.push(
|
|
401
|
+
this.#leaf(pluralize.singular(name), String(item), depth + 1)
|
|
402
|
+
);
|
|
403
|
+
}
|
|
334
404
|
}
|
|
335
405
|
}
|
|
336
406
|
if (this.options.groupFragments && fragmentItems.length > 0) {
|
|
@@ -372,8 +442,14 @@ ${this.#indent(safe, 2)}
|
|
|
372
442
|
if (Array.isArray(data)) {
|
|
373
443
|
return this.#renderArrayIndented(name, data, ctx.depth);
|
|
374
444
|
}
|
|
375
|
-
|
|
376
|
-
|
|
445
|
+
if (isFragmentObject(data)) {
|
|
446
|
+
const children = this.renderEntries(data, {
|
|
447
|
+
...ctx,
|
|
448
|
+
depth: ctx.depth + 1
|
|
449
|
+
});
|
|
450
|
+
return this.#wrapIndented(name, children, ctx.depth);
|
|
451
|
+
}
|
|
452
|
+
return "";
|
|
377
453
|
}
|
|
378
454
|
#renderArrayIndented(name, items, depth) {
|
|
379
455
|
const fragmentItems = items.filter(isFragment);
|
|
@@ -381,9 +457,19 @@ ${this.#indent(safe, 2)}
|
|
|
381
457
|
const children = [];
|
|
382
458
|
for (const item of nonFragmentItems) {
|
|
383
459
|
if (item != null) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
460
|
+
if (isFragmentObject(item)) {
|
|
461
|
+
children.push(
|
|
462
|
+
this.#wrapIndented(
|
|
463
|
+
pluralize.singular(name),
|
|
464
|
+
this.renderEntries(item, { depth: depth + 2, path: [] }),
|
|
465
|
+
depth + 1
|
|
466
|
+
)
|
|
467
|
+
);
|
|
468
|
+
} else {
|
|
469
|
+
children.push(
|
|
470
|
+
this.#leaf(pluralize.singular(name), String(item), depth + 1)
|
|
471
|
+
);
|
|
472
|
+
}
|
|
387
473
|
}
|
|
388
474
|
}
|
|
389
475
|
if (this.options.groupFragments && fragmentItems.length > 0) {
|
|
@@ -412,7 +498,19 @@ ${this.#indent(safe, 2)}
|
|
|
412
498
|
return "";
|
|
413
499
|
}
|
|
414
500
|
const itemTag = pluralize.singular(key);
|
|
415
|
-
const children = items.filter((item) => item != null).map((item) =>
|
|
501
|
+
const children = items.filter((item) => item != null).map((item) => {
|
|
502
|
+
if (isFragment(item)) {
|
|
503
|
+
return this.renderFragment(item, { ...ctx, depth: ctx.depth + 1 });
|
|
504
|
+
}
|
|
505
|
+
if (isFragmentObject(item)) {
|
|
506
|
+
return this.#wrapIndented(
|
|
507
|
+
itemTag,
|
|
508
|
+
this.renderEntries(item, { ...ctx, depth: ctx.depth + 2 }),
|
|
509
|
+
ctx.depth + 1
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
return this.#leaf(itemTag, String(item), ctx.depth + 1);
|
|
513
|
+
});
|
|
416
514
|
return this.#wrapIndented(key, children, ctx.depth);
|
|
417
515
|
}
|
|
418
516
|
renderObject(key, obj, ctx) {
|
|
@@ -464,7 +562,7 @@ ${pad}</${tag}>`;
|
|
|
464
562
|
};
|
|
465
563
|
var MarkdownRenderer = class extends ContextRenderer {
|
|
466
564
|
render(fragments) {
|
|
467
|
-
return fragments.map((f) => {
|
|
565
|
+
return this.sanitizeFragments(fragments).map((f) => {
|
|
468
566
|
const title = `## ${titlecase(f.name)}`;
|
|
469
567
|
if (this.isPrimitive(f.data)) {
|
|
470
568
|
return `${title}
|
|
@@ -478,8 +576,12 @@ ${this.#renderArray(f.data, 0)}`;
|
|
|
478
576
|
return `${title}
|
|
479
577
|
${this.renderFragment(f.data, { depth: 0, path: [] })}`;
|
|
480
578
|
}
|
|
481
|
-
|
|
579
|
+
if (isFragmentObject(f.data)) {
|
|
580
|
+
return `${title}
|
|
482
581
|
${this.renderEntries(f.data, { depth: 0, path: [] }).join("\n")}`;
|
|
582
|
+
}
|
|
583
|
+
return `${title}
|
|
584
|
+
`;
|
|
483
585
|
}).join("\n\n");
|
|
484
586
|
}
|
|
485
587
|
#renderArray(items, depth) {
|
|
@@ -536,14 +638,17 @@ ${this.renderEntries(f.data, { depth: 0, path: [] }).join("\n")}`;
|
|
|
536
638
|
return [header, child].join("\n");
|
|
537
639
|
}
|
|
538
640
|
if (Array.isArray(data)) {
|
|
539
|
-
const
|
|
540
|
-
return [header, ...
|
|
641
|
+
const children = data.filter((item) => item != null).map((item) => this.#arrayItem(item, ctx.depth + 1));
|
|
642
|
+
return [header, ...children].join("\n");
|
|
541
643
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
644
|
+
if (isFragmentObject(data)) {
|
|
645
|
+
const children = this.renderEntries(data, {
|
|
646
|
+
...ctx,
|
|
647
|
+
depth: ctx.depth + 1
|
|
648
|
+
}).join("\n");
|
|
649
|
+
return [header, children].join("\n");
|
|
650
|
+
}
|
|
651
|
+
return header;
|
|
547
652
|
}
|
|
548
653
|
renderPrimitive(key, value, ctx) {
|
|
549
654
|
return this.#leaf(key, value, ctx.depth);
|
|
@@ -564,22 +669,25 @@ ${this.renderEntries(f.data, { depth: 0, path: [] }).join("\n")}`;
|
|
|
564
669
|
};
|
|
565
670
|
var TomlRenderer = class extends ContextRenderer {
|
|
566
671
|
render(fragments) {
|
|
567
|
-
|
|
672
|
+
const rendered = [];
|
|
673
|
+
for (const f of this.sanitizeFragments(fragments)) {
|
|
568
674
|
if (this.isPrimitive(f.data)) {
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
675
|
+
rendered.push(`${f.name} = ${this.#formatValue(f.data)}`);
|
|
676
|
+
} else if (Array.isArray(f.data)) {
|
|
677
|
+
rendered.push(this.#renderTopLevelArray(f.name, f.data));
|
|
678
|
+
} else if (isFragment(f.data)) {
|
|
679
|
+
rendered.push(
|
|
680
|
+
[
|
|
681
|
+
`[${f.name}]`,
|
|
682
|
+
this.renderFragment(f.data, { depth: 0, path: [f.name] })
|
|
683
|
+
].join("\n")
|
|
684
|
+
);
|
|
685
|
+
} else if (isFragmentObject(f.data)) {
|
|
686
|
+
const entries = this.#renderObjectEntries(f.data, [f.name]);
|
|
687
|
+
rendered.push([`[${f.name}]`, ...entries].join("\n"));
|
|
579
688
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
}).join("\n\n");
|
|
689
|
+
}
|
|
690
|
+
return rendered.join("\n\n");
|
|
583
691
|
}
|
|
584
692
|
#renderTopLevelArray(name, items) {
|
|
585
693
|
const fragmentItems = items.filter(isFragment);
|
|
@@ -614,10 +722,12 @@ var TomlRenderer = class extends ContextRenderer {
|
|
|
614
722
|
}
|
|
615
723
|
return `${key} = ${this.#formatValue(value)}`;
|
|
616
724
|
}
|
|
617
|
-
renderPrimitive(key, value,
|
|
725
|
+
renderPrimitive(key, value, ctx) {
|
|
726
|
+
void ctx;
|
|
618
727
|
return `${key} = ${this.#formatValue(value)}`;
|
|
619
728
|
}
|
|
620
|
-
renderArray(key, items,
|
|
729
|
+
renderArray(key, items, ctx) {
|
|
730
|
+
void ctx;
|
|
621
731
|
const values = items.filter((item) => item != null).map((item) => this.#formatValue(item));
|
|
622
732
|
return `${key} = [${values.join(", ")}]`;
|
|
623
733
|
}
|
|
@@ -671,8 +781,11 @@ var TomlRenderer = class extends ContextRenderer {
|
|
|
671
781
|
const values = nonFragmentItems.map((item) => this.#formatValue(item));
|
|
672
782
|
return `${name} = [${values.join(", ")}]`;
|
|
673
783
|
}
|
|
674
|
-
|
|
675
|
-
|
|
784
|
+
if (isFragmentObject(data)) {
|
|
785
|
+
const entries = this.#renderObjectEntries(data, newPath);
|
|
786
|
+
return ["", `[${newPath.join(".")}]`, ...entries].join("\n");
|
|
787
|
+
}
|
|
788
|
+
return "";
|
|
676
789
|
}
|
|
677
790
|
#escape(value) {
|
|
678
791
|
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -692,7 +805,8 @@ var TomlRenderer = class extends ContextRenderer {
|
|
|
692
805
|
};
|
|
693
806
|
var ToonRenderer = class extends ContextRenderer {
|
|
694
807
|
render(fragments) {
|
|
695
|
-
|
|
808
|
+
const sanitized = this.sanitizeFragments(fragments);
|
|
809
|
+
return sanitized.map((f) => this.#renderTopLevel(f)).filter(Boolean).join("\n");
|
|
696
810
|
}
|
|
697
811
|
#renderTopLevel(fragment2) {
|
|
698
812
|
const { name, data } = fragment2;
|
|
@@ -741,18 +855,18 @@ ${entries}`;
|
|
|
741
855
|
if (items.length === 0) return false;
|
|
742
856
|
const objects = items.filter(isFragmentObject);
|
|
743
857
|
if (objects.length !== items.length) return false;
|
|
744
|
-
|
|
858
|
+
let intersection = new Set(Object.keys(objects[0]));
|
|
745
859
|
for (const obj of objects) {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
860
|
+
const keys = new Set(Object.keys(obj));
|
|
861
|
+
intersection = new Set([...intersection].filter((k) => keys.has(k)));
|
|
749
862
|
for (const value of Object.values(obj)) {
|
|
750
|
-
if (
|
|
863
|
+
if (value == null) continue;
|
|
864
|
+
if (!this.#isPrimitiveValue(value)) {
|
|
751
865
|
return false;
|
|
752
866
|
}
|
|
753
867
|
}
|
|
754
868
|
}
|
|
755
|
-
return
|
|
869
|
+
return intersection.size > 0;
|
|
756
870
|
}
|
|
757
871
|
#renderPrimitiveArray(key, items, depth) {
|
|
758
872
|
const values = items.map((item) => this.#formatValue(item)).join(",");
|
|
@@ -762,10 +876,16 @@ ${entries}`;
|
|
|
762
876
|
if (items.length === 0) {
|
|
763
877
|
return `${this.#pad(depth)}${key}[0]:`;
|
|
764
878
|
}
|
|
765
|
-
const fields =
|
|
879
|
+
const fields = Array.from(
|
|
880
|
+
new Set(items.flatMap((obj) => Object.keys(obj)))
|
|
881
|
+
);
|
|
766
882
|
const header = `${this.#pad(depth)}${key}[${items.length}]{${fields.join(",")}}:`;
|
|
767
883
|
const rows = items.map((obj) => {
|
|
768
|
-
const values = fields.map((f) =>
|
|
884
|
+
const values = fields.map((f) => {
|
|
885
|
+
const value = obj[f];
|
|
886
|
+
if (value == null) return "";
|
|
887
|
+
return this.#formatValue(value);
|
|
888
|
+
});
|
|
769
889
|
return `${this.#pad(depth + 1)}${values.join(",")}`;
|
|
770
890
|
});
|
|
771
891
|
return [header, ...rows].join("\n");
|
|
@@ -913,6 +1033,7 @@ var ContextEngine = class {
|
|
|
913
1033
|
#pendingMessages = [];
|
|
914
1034
|
#store;
|
|
915
1035
|
#chatId;
|
|
1036
|
+
#userId;
|
|
916
1037
|
#branchName;
|
|
917
1038
|
#branch = null;
|
|
918
1039
|
#chatData = null;
|
|
@@ -921,9 +1042,13 @@ var ContextEngine = class {
|
|
|
921
1042
|
if (!options.chatId) {
|
|
922
1043
|
throw new Error("chatId is required");
|
|
923
1044
|
}
|
|
1045
|
+
if (!options.userId) {
|
|
1046
|
+
throw new Error("userId is required");
|
|
1047
|
+
}
|
|
924
1048
|
this.#store = options.store;
|
|
925
1049
|
this.#chatId = options.chatId;
|
|
926
|
-
this.#
|
|
1050
|
+
this.#userId = options.userId;
|
|
1051
|
+
this.#branchName = "main";
|
|
927
1052
|
}
|
|
928
1053
|
/**
|
|
929
1054
|
* Initialize the chat and branch if they don't exist.
|
|
@@ -932,24 +1057,11 @@ var ContextEngine = class {
|
|
|
932
1057
|
if (this.#initialized) {
|
|
933
1058
|
return;
|
|
934
1059
|
}
|
|
935
|
-
this.#chatData = await this.#store.upsertChat({
|
|
936
|
-
|
|
937
|
-
this.#
|
|
938
|
-
|
|
939
|
-
);
|
|
940
|
-
if (existingBranch) {
|
|
941
|
-
this.#branch = existingBranch;
|
|
942
|
-
} else {
|
|
943
|
-
this.#branch = {
|
|
944
|
-
id: crypto.randomUUID(),
|
|
945
|
-
chatId: this.#chatId,
|
|
946
|
-
name: this.#branchName,
|
|
947
|
-
headMessageId: null,
|
|
948
|
-
isActive: true,
|
|
949
|
-
createdAt: Date.now()
|
|
950
|
-
};
|
|
951
|
-
await this.#store.createBranch(this.#branch);
|
|
952
|
-
}
|
|
1060
|
+
this.#chatData = await this.#store.upsertChat({
|
|
1061
|
+
id: this.#chatId,
|
|
1062
|
+
userId: this.#userId
|
|
1063
|
+
});
|
|
1064
|
+
this.#branch = await this.#store.getActiveBranch(this.#chatId);
|
|
953
1065
|
this.#initialized = true;
|
|
954
1066
|
}
|
|
955
1067
|
/**
|
|
@@ -1009,6 +1121,7 @@ var ContextEngine = class {
|
|
|
1009
1121
|
}
|
|
1010
1122
|
return {
|
|
1011
1123
|
id: this.#chatData.id,
|
|
1124
|
+
userId: this.#chatData.userId,
|
|
1012
1125
|
createdAt: this.#chatData.createdAt,
|
|
1013
1126
|
updatedAt: this.#chatData.updatedAt,
|
|
1014
1127
|
title: this.#chatData.title,
|
|
@@ -1051,7 +1164,7 @@ var ContextEngine = class {
|
|
|
1051
1164
|
*
|
|
1052
1165
|
* @example
|
|
1053
1166
|
* ```ts
|
|
1054
|
-
* const context = new ContextEngine({ store, chatId: 'chat-1' })
|
|
1167
|
+
* const context = new ContextEngine({ store, chatId: 'chat-1', userId: 'user-1' })
|
|
1055
1168
|
* .set(role('You are helpful'), user('Hello'));
|
|
1056
1169
|
*
|
|
1057
1170
|
* const { systemPrompt, messages } = await context.resolve();
|
|
@@ -1395,7 +1508,7 @@ var ContextEngine = class {
|
|
|
1395
1508
|
}
|
|
1396
1509
|
/**
|
|
1397
1510
|
* Inspect the full context state for debugging.
|
|
1398
|
-
* Returns a
|
|
1511
|
+
* Returns a JSON-serializable object with context information.
|
|
1399
1512
|
*
|
|
1400
1513
|
* @param options - Inspection options (modelId and renderer required)
|
|
1401
1514
|
* @returns Complete inspection data including estimates, rendered output, fragments, and graph
|
|
@@ -1547,6 +1660,33 @@ function glossary(entries) {
|
|
|
1547
1660
|
}))
|
|
1548
1661
|
};
|
|
1549
1662
|
}
|
|
1663
|
+
function role(content) {
|
|
1664
|
+
return {
|
|
1665
|
+
name: "role",
|
|
1666
|
+
data: content
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
function principle(input) {
|
|
1670
|
+
return {
|
|
1671
|
+
name: "principle",
|
|
1672
|
+
data: {
|
|
1673
|
+
title: input.title,
|
|
1674
|
+
description: input.description,
|
|
1675
|
+
...input.policies?.length && { policies: input.policies }
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
function policy(input) {
|
|
1680
|
+
return {
|
|
1681
|
+
name: "policy",
|
|
1682
|
+
data: {
|
|
1683
|
+
rule: input.rule,
|
|
1684
|
+
...input.before && { before: input.before },
|
|
1685
|
+
...input.reason && { reason: input.reason },
|
|
1686
|
+
...input.policies?.length && { policies: input.policies }
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1550
1690
|
|
|
1551
1691
|
// packages/context/src/lib/fragments/user.ts
|
|
1552
1692
|
function identity(input) {
|
|
@@ -1563,7 +1703,8 @@ function persona(input) {
|
|
|
1563
1703
|
name: "persona",
|
|
1564
1704
|
data: {
|
|
1565
1705
|
name: input.name,
|
|
1566
|
-
role: input.role,
|
|
1706
|
+
...input.role && { role: input.role },
|
|
1707
|
+
...input.objective && { objective: input.objective },
|
|
1567
1708
|
...input.tone && { tone: input.tone }
|
|
1568
1709
|
}
|
|
1569
1710
|
};
|
|
@@ -1612,11 +1753,79 @@ function runGuardrailChain(part, guardrails, context) {
|
|
|
1612
1753
|
return pass(currentPart);
|
|
1613
1754
|
}
|
|
1614
1755
|
|
|
1756
|
+
// packages/context/src/lib/guardrails/error-recovery.guardrail.ts
|
|
1757
|
+
import chalk from "chalk";
|
|
1758
|
+
var errorRecoveryGuardrail = {
|
|
1759
|
+
id: "error-recovery",
|
|
1760
|
+
name: "API Error Recovery",
|
|
1761
|
+
handle: (part, context) => {
|
|
1762
|
+
if (part.type !== "error") {
|
|
1763
|
+
return pass(part);
|
|
1764
|
+
}
|
|
1765
|
+
const errorText = part.errorText || "";
|
|
1766
|
+
const prefix = chalk.bold.magenta("[ErrorRecovery]");
|
|
1767
|
+
console.log(
|
|
1768
|
+
`${prefix} ${chalk.red("Caught error:")} ${chalk.dim(errorText.slice(0, 150))}`
|
|
1769
|
+
);
|
|
1770
|
+
const logAndFail = (pattern, feedback) => {
|
|
1771
|
+
console.log(
|
|
1772
|
+
`${prefix} ${chalk.yellow("Pattern:")} ${chalk.cyan(pattern)}`
|
|
1773
|
+
);
|
|
1774
|
+
console.log(
|
|
1775
|
+
`${prefix} ${chalk.green("Feedback:")} ${chalk.dim(feedback.slice(0, 80))}...`
|
|
1776
|
+
);
|
|
1777
|
+
return fail(feedback);
|
|
1778
|
+
};
|
|
1779
|
+
if (errorText.includes("Tool choice is none")) {
|
|
1780
|
+
if (context.availableTools.length > 0) {
|
|
1781
|
+
return logAndFail(
|
|
1782
|
+
"Tool choice is none",
|
|
1783
|
+
`I tried to call a tool that doesn't exist. Available tools: ${context.availableTools.join(", ")}. Let me use one of these instead.`
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
return logAndFail(
|
|
1787
|
+
"Tool choice is none (no tools)",
|
|
1788
|
+
"I tried to call a tool, but no tools are available. Let me respond with plain text instead."
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1791
|
+
if (errorText.includes("not in request.tools") || errorText.includes("tool") && errorText.includes("not found")) {
|
|
1792
|
+
const toolMatch = errorText.match(/tool '([^']+)'/);
|
|
1793
|
+
const toolName = toolMatch ? toolMatch[1] : "unknown";
|
|
1794
|
+
if (context.availableTools.length > 0) {
|
|
1795
|
+
return logAndFail(
|
|
1796
|
+
`Unregistered tool: ${toolName}`,
|
|
1797
|
+
`I tried to call "${toolName}" but it doesn't exist. Available tools: ${context.availableTools.join(", ")}. Let me use one of these instead.`
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
return logAndFail(
|
|
1801
|
+
`Unregistered tool: ${toolName} (no tools)`,
|
|
1802
|
+
`I tried to call "${toolName}" but no tools are available. Let me respond with plain text instead.`
|
|
1803
|
+
);
|
|
1804
|
+
}
|
|
1805
|
+
if (errorText.includes("Failed to parse tool call arguments") || errorText.includes("parse tool call") || errorText.includes("invalid JSON")) {
|
|
1806
|
+
return logAndFail(
|
|
1807
|
+
"Malformed JSON arguments",
|
|
1808
|
+
"I generated malformed JSON for the tool arguments. Let me format my tool call properly with valid JSON."
|
|
1809
|
+
);
|
|
1810
|
+
}
|
|
1811
|
+
if (errorText.includes("Parsing failed")) {
|
|
1812
|
+
return logAndFail(
|
|
1813
|
+
"Parsing failed",
|
|
1814
|
+
"My response format was invalid. Let me try again with a properly formatted response."
|
|
1815
|
+
);
|
|
1816
|
+
}
|
|
1817
|
+
return logAndFail(
|
|
1818
|
+
"Unknown error",
|
|
1819
|
+
`An error occurred: ${errorText.slice(0, 100)}. Let me try a different approach.`
|
|
1820
|
+
);
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1615
1824
|
// packages/context/src/lib/sandbox/binary-bridges.ts
|
|
1825
|
+
import { existsSync } from "fs";
|
|
1616
1826
|
import { defineCommand } from "just-bash";
|
|
1617
1827
|
import spawn from "nano-spawn";
|
|
1618
1828
|
import * as path from "path";
|
|
1619
|
-
import { existsSync } from "fs";
|
|
1620
1829
|
function createBinaryBridges(...binaries) {
|
|
1621
1830
|
return binaries.map((input) => {
|
|
1622
1831
|
const config = typeof input === "string" ? { name: input } : input;
|
|
@@ -1662,6 +1871,17 @@ function createBinaryBridges(...binaries) {
|
|
|
1662
1871
|
exitCode: 0
|
|
1663
1872
|
};
|
|
1664
1873
|
} catch (error) {
|
|
1874
|
+
if (error && typeof error === "object") {
|
|
1875
|
+
const err = error;
|
|
1876
|
+
const cause = err.cause;
|
|
1877
|
+
if (cause?.code === "ENOENT") {
|
|
1878
|
+
return {
|
|
1879
|
+
stdout: "",
|
|
1880
|
+
stderr: `${name}: ${binaryPath} not found`,
|
|
1881
|
+
exitCode: 127
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1665
1885
|
if (error && typeof error === "object" && "exitCode" in error) {
|
|
1666
1886
|
const subprocessError = error;
|
|
1667
1887
|
return {
|
|
@@ -2379,7 +2599,9 @@ function parseFrontmatter(content) {
|
|
|
2379
2599
|
throw new Error('Invalid SKILL.md: frontmatter must have a "name" field');
|
|
2380
2600
|
}
|
|
2381
2601
|
if (!frontmatter.description || typeof frontmatter.description !== "string") {
|
|
2382
|
-
throw new Error(
|
|
2602
|
+
throw new Error(
|
|
2603
|
+
'Invalid SKILL.md: frontmatter must have a "description" field'
|
|
2604
|
+
);
|
|
2383
2605
|
}
|
|
2384
2606
|
return {
|
|
2385
2607
|
frontmatter,
|
|
@@ -2472,6 +2694,7 @@ var STORE_DDL = `
|
|
|
2472
2694
|
-- createdAt/updatedAt: DEFAULT for insert, inline SET for updates
|
|
2473
2695
|
CREATE TABLE IF NOT EXISTS chats (
|
|
2474
2696
|
id TEXT PRIMARY KEY,
|
|
2697
|
+
userId TEXT NOT NULL,
|
|
2475
2698
|
title TEXT,
|
|
2476
2699
|
metadata TEXT,
|
|
2477
2700
|
createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
|
|
@@ -2479,6 +2702,7 @@ CREATE TABLE IF NOT EXISTS chats (
|
|
|
2479
2702
|
);
|
|
2480
2703
|
|
|
2481
2704
|
CREATE INDEX IF NOT EXISTS idx_chats_updatedAt ON chats(updatedAt);
|
|
2705
|
+
CREATE INDEX IF NOT EXISTS idx_chats_userId ON chats(userId);
|
|
2482
2706
|
|
|
2483
2707
|
-- Messages table (nodes in the DAG)
|
|
2484
2708
|
CREATE TABLE IF NOT EXISTS messages (
|
|
@@ -2544,37 +2768,67 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2544
2768
|
this.#db.exec("PRAGMA foreign_keys = ON");
|
|
2545
2769
|
this.#db.exec(STORE_DDL);
|
|
2546
2770
|
}
|
|
2771
|
+
/**
|
|
2772
|
+
* Execute a function within a transaction.
|
|
2773
|
+
* Automatically commits on success or rolls back on error.
|
|
2774
|
+
*/
|
|
2775
|
+
#useTransaction(fn) {
|
|
2776
|
+
this.#db.exec("BEGIN TRANSACTION");
|
|
2777
|
+
try {
|
|
2778
|
+
const result = fn();
|
|
2779
|
+
this.#db.exec("COMMIT");
|
|
2780
|
+
return result;
|
|
2781
|
+
} catch (error) {
|
|
2782
|
+
this.#db.exec("ROLLBACK");
|
|
2783
|
+
throw error;
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2547
2786
|
// ==========================================================================
|
|
2548
2787
|
// Chat Operations
|
|
2549
2788
|
// ==========================================================================
|
|
2550
2789
|
async createChat(chat) {
|
|
2551
|
-
this.#
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2790
|
+
this.#useTransaction(() => {
|
|
2791
|
+
this.#db.prepare(
|
|
2792
|
+
`INSERT INTO chats (id, userId, title, metadata)
|
|
2793
|
+
VALUES (?, ?, ?, ?)`
|
|
2794
|
+
).run(
|
|
2795
|
+
chat.id,
|
|
2796
|
+
chat.userId,
|
|
2797
|
+
chat.title ?? null,
|
|
2798
|
+
chat.metadata ? JSON.stringify(chat.metadata) : null
|
|
2799
|
+
);
|
|
2800
|
+
this.#db.prepare(
|
|
2801
|
+
`INSERT INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
|
|
2802
|
+
VALUES (?, ?, 'main', NULL, 1, ?)`
|
|
2803
|
+
).run(crypto.randomUUID(), chat.id, Date.now());
|
|
2804
|
+
});
|
|
2559
2805
|
}
|
|
2560
2806
|
async upsertChat(chat) {
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2807
|
+
return this.#useTransaction(() => {
|
|
2808
|
+
const row = this.#db.prepare(
|
|
2809
|
+
`INSERT INTO chats (id, userId, title, metadata)
|
|
2810
|
+
VALUES (?, ?, ?, ?)
|
|
2811
|
+
ON CONFLICT(id) DO UPDATE SET id = excluded.id
|
|
2812
|
+
RETURNING *`
|
|
2813
|
+
).get(
|
|
2814
|
+
chat.id,
|
|
2815
|
+
chat.userId,
|
|
2816
|
+
chat.title ?? null,
|
|
2817
|
+
chat.metadata ? JSON.stringify(chat.metadata) : null
|
|
2818
|
+
);
|
|
2819
|
+
this.#db.prepare(
|
|
2820
|
+
`INSERT OR IGNORE INTO branches (id, chatId, name, headMessageId, isActive, createdAt)
|
|
2821
|
+
VALUES (?, ?, 'main', NULL, 1, ?)`
|
|
2822
|
+
).run(crypto.randomUUID(), chat.id, Date.now());
|
|
2823
|
+
return {
|
|
2824
|
+
id: row.id,
|
|
2825
|
+
userId: row.userId,
|
|
2826
|
+
title: row.title ?? void 0,
|
|
2827
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
2828
|
+
createdAt: row.createdAt,
|
|
2829
|
+
updatedAt: row.updatedAt
|
|
2830
|
+
};
|
|
2831
|
+
});
|
|
2578
2832
|
}
|
|
2579
2833
|
async getChat(chatId) {
|
|
2580
2834
|
const row = this.#db.prepare("SELECT * FROM chats WHERE id = ?").get(chatId);
|
|
@@ -2583,6 +2837,7 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2583
2837
|
}
|
|
2584
2838
|
return {
|
|
2585
2839
|
id: row.id,
|
|
2840
|
+
userId: row.userId,
|
|
2586
2841
|
title: row.title ?? void 0,
|
|
2587
2842
|
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
2588
2843
|
createdAt: row.createdAt,
|
|
@@ -2606,16 +2861,33 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2606
2861
|
).get(...params);
|
|
2607
2862
|
return {
|
|
2608
2863
|
id: row.id,
|
|
2864
|
+
userId: row.userId,
|
|
2609
2865
|
title: row.title ?? void 0,
|
|
2610
2866
|
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
2611
2867
|
createdAt: row.createdAt,
|
|
2612
2868
|
updatedAt: row.updatedAt
|
|
2613
2869
|
};
|
|
2614
2870
|
}
|
|
2615
|
-
async listChats() {
|
|
2871
|
+
async listChats(options) {
|
|
2872
|
+
const params = [];
|
|
2873
|
+
let whereClause = "";
|
|
2874
|
+
let limitClause = "";
|
|
2875
|
+
if (options?.userId) {
|
|
2876
|
+
whereClause = "WHERE c.userId = ?";
|
|
2877
|
+
params.push(options.userId);
|
|
2878
|
+
}
|
|
2879
|
+
if (options?.limit !== void 0) {
|
|
2880
|
+
limitClause = " LIMIT ?";
|
|
2881
|
+
params.push(options.limit);
|
|
2882
|
+
if (options.offset !== void 0) {
|
|
2883
|
+
limitClause += " OFFSET ?";
|
|
2884
|
+
params.push(options.offset);
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2616
2887
|
const rows = this.#db.prepare(
|
|
2617
2888
|
`SELECT
|
|
2618
2889
|
c.id,
|
|
2890
|
+
c.userId,
|
|
2619
2891
|
c.title,
|
|
2620
2892
|
c.createdAt,
|
|
2621
2893
|
c.updatedAt,
|
|
@@ -2624,11 +2896,13 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2624
2896
|
FROM chats c
|
|
2625
2897
|
LEFT JOIN messages m ON m.chatId = c.id
|
|
2626
2898
|
LEFT JOIN branches b ON b.chatId = c.id
|
|
2899
|
+
${whereClause}
|
|
2627
2900
|
GROUP BY c.id
|
|
2628
|
-
ORDER BY c.updatedAt DESC`
|
|
2629
|
-
).all();
|
|
2901
|
+
ORDER BY c.updatedAt DESC${limitClause}`
|
|
2902
|
+
).all(...params);
|
|
2630
2903
|
return rows.map((row) => ({
|
|
2631
2904
|
id: row.id,
|
|
2905
|
+
userId: row.userId,
|
|
2632
2906
|
title: row.title ?? void 0,
|
|
2633
2907
|
messageCount: row.messageCount,
|
|
2634
2908
|
branchCount: row.branchCount,
|
|
@@ -2636,6 +2910,25 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2636
2910
|
updatedAt: row.updatedAt
|
|
2637
2911
|
}));
|
|
2638
2912
|
}
|
|
2913
|
+
async deleteChat(chatId, options) {
|
|
2914
|
+
return this.#useTransaction(() => {
|
|
2915
|
+
const messageIds = this.#db.prepare("SELECT id FROM messages WHERE chatId = ?").all(chatId);
|
|
2916
|
+
let sql = "DELETE FROM chats WHERE id = ?";
|
|
2917
|
+
const params = [chatId];
|
|
2918
|
+
if (options?.userId !== void 0) {
|
|
2919
|
+
sql += " AND userId = ?";
|
|
2920
|
+
params.push(options.userId);
|
|
2921
|
+
}
|
|
2922
|
+
const result = this.#db.prepare(sql).run(...params);
|
|
2923
|
+
if (result.changes > 0 && messageIds.length > 0) {
|
|
2924
|
+
const placeholders = messageIds.map(() => "?").join(", ");
|
|
2925
|
+
this.#db.prepare(
|
|
2926
|
+
`DELETE FROM messages_fts WHERE messageId IN (${placeholders})`
|
|
2927
|
+
).run(...messageIds.map((m) => m.id));
|
|
2928
|
+
}
|
|
2929
|
+
return result.changes > 0;
|
|
2930
|
+
});
|
|
2931
|
+
}
|
|
2639
2932
|
// ==========================================================================
|
|
2640
2933
|
// Message Operations (Graph Nodes)
|
|
2641
2934
|
// ==========================================================================
|
|
@@ -2706,6 +2999,17 @@ var SqliteContextStore = class extends ContextStore {
|
|
|
2706
2999
|
).get(messageId);
|
|
2707
3000
|
return row.hasChildren === 1;
|
|
2708
3001
|
}
|
|
3002
|
+
async getMessages(chatId) {
|
|
3003
|
+
const chat = await this.getChat(chatId);
|
|
3004
|
+
if (!chat) {
|
|
3005
|
+
throw new Error(`Chat "${chatId}" not found`);
|
|
3006
|
+
}
|
|
3007
|
+
const activeBranch = await this.getActiveBranch(chatId);
|
|
3008
|
+
if (!activeBranch?.headMessageId) {
|
|
3009
|
+
return [];
|
|
3010
|
+
}
|
|
3011
|
+
return this.getMessageChain(activeBranch.headMessageId);
|
|
3012
|
+
}
|
|
2709
3013
|
// ==========================================================================
|
|
2710
3014
|
// Branch Operations
|
|
2711
3015
|
// ==========================================================================
|
|
@@ -3003,7 +3307,9 @@ function visualizeGraph(data) {
|
|
|
3003
3307
|
}
|
|
3004
3308
|
|
|
3005
3309
|
// packages/context/src/lib/agent.ts
|
|
3310
|
+
import { groq } from "@ai-sdk/groq";
|
|
3006
3311
|
import {
|
|
3312
|
+
NoSuchToolError,
|
|
3007
3313
|
Output,
|
|
3008
3314
|
convertToModelMessages,
|
|
3009
3315
|
createUIMessageStream,
|
|
@@ -3013,7 +3319,7 @@ import {
|
|
|
3013
3319
|
stepCountIs,
|
|
3014
3320
|
streamText
|
|
3015
3321
|
} from "ai";
|
|
3016
|
-
import
|
|
3322
|
+
import chalk2 from "chalk";
|
|
3017
3323
|
import "zod";
|
|
3018
3324
|
import "@deepagents/agent";
|
|
3019
3325
|
var Agent = class _Agent {
|
|
@@ -3040,16 +3346,17 @@ var Agent = class _Agent {
|
|
|
3040
3346
|
providerOptions: this.#options.providerOptions,
|
|
3041
3347
|
model: this.#options.model,
|
|
3042
3348
|
system: systemPrompt,
|
|
3043
|
-
messages: convertToModelMessages(messages),
|
|
3349
|
+
messages: await convertToModelMessages(messages),
|
|
3044
3350
|
stopWhen: stepCountIs(25),
|
|
3045
3351
|
tools: this.#options.tools,
|
|
3046
3352
|
experimental_context: contextVariables,
|
|
3353
|
+
experimental_repairToolCall: repairToolCall,
|
|
3047
3354
|
toolChoice: this.#options.toolChoice,
|
|
3048
3355
|
onStepFinish: (step) => {
|
|
3049
3356
|
const toolCall = step.toolCalls.at(-1);
|
|
3050
3357
|
if (toolCall) {
|
|
3051
3358
|
console.log(
|
|
3052
|
-
`Debug: ${
|
|
3359
|
+
`Debug: ${chalk2.yellow("ToolCalled")}: ${toolCall.toolName}(${JSON.stringify(toolCall.input)})`
|
|
3053
3360
|
);
|
|
3054
3361
|
}
|
|
3055
3362
|
}
|
|
@@ -3098,8 +3405,9 @@ var Agent = class _Agent {
|
|
|
3098
3405
|
providerOptions: this.#options.providerOptions,
|
|
3099
3406
|
model: this.#options.model,
|
|
3100
3407
|
system: systemPrompt,
|
|
3101
|
-
messages: convertToModelMessages(messages),
|
|
3102
|
-
|
|
3408
|
+
messages: await convertToModelMessages(messages),
|
|
3409
|
+
experimental_repairToolCall: repairToolCall,
|
|
3410
|
+
stopWhen: stepCountIs(50),
|
|
3103
3411
|
experimental_transform: config?.transform ?? smoothStream(),
|
|
3104
3412
|
tools: this.#options.tools,
|
|
3105
3413
|
experimental_context: contextVariables,
|
|
@@ -3108,7 +3416,7 @@ var Agent = class _Agent {
|
|
|
3108
3416
|
const toolCall = step.toolCalls.at(-1);
|
|
3109
3417
|
if (toolCall) {
|
|
3110
3418
|
console.log(
|
|
3111
|
-
`Debug: (${runId}) ${
|
|
3419
|
+
`Debug: (${runId}) ${chalk2.bold.yellow("ToolCalled")}: ${toolCall.toolName}(${JSON.stringify(toolCall.input)})`
|
|
3112
3420
|
);
|
|
3113
3421
|
}
|
|
3114
3422
|
}
|
|
@@ -3155,7 +3463,7 @@ var Agent = class _Agent {
|
|
|
3155
3463
|
guardrailFailed = true;
|
|
3156
3464
|
failureFeedback = checkResult.feedback;
|
|
3157
3465
|
console.log(
|
|
3158
|
-
|
|
3466
|
+
chalk2.yellow(
|
|
3159
3467
|
`[${this.#options.name}] Guardrail triggered (attempt ${attempt}/${maxRetries}): ${failureFeedback.slice(0, 50)}...`
|
|
3160
3468
|
)
|
|
3161
3469
|
);
|
|
@@ -3172,7 +3480,7 @@ var Agent = class _Agent {
|
|
|
3172
3480
|
}
|
|
3173
3481
|
if (attempt >= maxRetries) {
|
|
3174
3482
|
console.error(
|
|
3175
|
-
|
|
3483
|
+
chalk2.red(
|
|
3176
3484
|
`[${this.#options.name}] Guardrail retry limit (${maxRetries}) exceeded.`
|
|
3177
3485
|
)
|
|
3178
3486
|
);
|
|
@@ -3215,14 +3523,10 @@ function structuredOutput(options) {
|
|
|
3215
3523
|
return {
|
|
3216
3524
|
async generate(contextVariables, config) {
|
|
3217
3525
|
if (!options.context) {
|
|
3218
|
-
throw new Error(
|
|
3219
|
-
`structuredOutput "${options.name}" is missing a context.`
|
|
3220
|
-
);
|
|
3526
|
+
throw new Error(`structuredOutput is missing a context.`);
|
|
3221
3527
|
}
|
|
3222
3528
|
if (!options.model) {
|
|
3223
|
-
throw new Error(
|
|
3224
|
-
`structuredOutput "${options.name}" is missing a model.`
|
|
3225
|
-
);
|
|
3529
|
+
throw new Error(`structuredOutput is missing a model.`);
|
|
3226
3530
|
}
|
|
3227
3531
|
const { messages, systemPrompt } = await options.context.resolve({
|
|
3228
3532
|
renderer: new XmlRenderer()
|
|
@@ -3232,23 +3536,21 @@ function structuredOutput(options) {
|
|
|
3232
3536
|
providerOptions: options.providerOptions,
|
|
3233
3537
|
model: options.model,
|
|
3234
3538
|
system: systemPrompt,
|
|
3235
|
-
messages: convertToModelMessages(messages),
|
|
3539
|
+
messages: await convertToModelMessages(messages),
|
|
3236
3540
|
stopWhen: stepCountIs(25),
|
|
3541
|
+
experimental_repairToolCall: repairToolCall,
|
|
3237
3542
|
experimental_context: contextVariables,
|
|
3238
|
-
|
|
3543
|
+
output: Output.object({ schema: options.schema }),
|
|
3544
|
+
tools: options.tools
|
|
3239
3545
|
});
|
|
3240
|
-
return result.
|
|
3546
|
+
return result.output;
|
|
3241
3547
|
},
|
|
3242
3548
|
async stream(contextVariables, config) {
|
|
3243
3549
|
if (!options.context) {
|
|
3244
|
-
throw new Error(
|
|
3245
|
-
`structuredOutput "${options.name}" is missing a context.`
|
|
3246
|
-
);
|
|
3550
|
+
throw new Error(`structuredOutput is missing a context.`);
|
|
3247
3551
|
}
|
|
3248
3552
|
if (!options.model) {
|
|
3249
|
-
throw new Error(
|
|
3250
|
-
`structuredOutput "${options.name}" is missing a model.`
|
|
3251
|
-
);
|
|
3553
|
+
throw new Error(`structuredOutput is missing a model.`);
|
|
3252
3554
|
}
|
|
3253
3555
|
const { messages, systemPrompt } = await options.context.resolve({
|
|
3254
3556
|
renderer: new XmlRenderer()
|
|
@@ -3258,15 +3560,54 @@ function structuredOutput(options) {
|
|
|
3258
3560
|
providerOptions: options.providerOptions,
|
|
3259
3561
|
model: options.model,
|
|
3260
3562
|
system: systemPrompt,
|
|
3261
|
-
|
|
3262
|
-
|
|
3563
|
+
experimental_repairToolCall: repairToolCall,
|
|
3564
|
+
messages: await convertToModelMessages(messages),
|
|
3565
|
+
stopWhen: stepCountIs(50),
|
|
3263
3566
|
experimental_transform: config?.transform ?? smoothStream(),
|
|
3264
3567
|
experimental_context: contextVariables,
|
|
3265
|
-
|
|
3568
|
+
output: Output.object({ schema: options.schema }),
|
|
3569
|
+
tools: options.tools
|
|
3266
3570
|
});
|
|
3267
3571
|
}
|
|
3268
3572
|
};
|
|
3269
3573
|
}
|
|
3574
|
+
var repairToolCall = async ({
|
|
3575
|
+
toolCall,
|
|
3576
|
+
tools,
|
|
3577
|
+
inputSchema,
|
|
3578
|
+
error
|
|
3579
|
+
}) => {
|
|
3580
|
+
console.log(
|
|
3581
|
+
`Debug: ${chalk2.yellow("RepairingToolCall")}: ${toolCall.toolName}`,
|
|
3582
|
+
error.name
|
|
3583
|
+
);
|
|
3584
|
+
if (NoSuchToolError.isInstance(error)) {
|
|
3585
|
+
return null;
|
|
3586
|
+
}
|
|
3587
|
+
const tool = tools[toolCall.toolName];
|
|
3588
|
+
const { output } = await generateText({
|
|
3589
|
+
model: groq("openai/gpt-oss-20b"),
|
|
3590
|
+
output: Output.object({ schema: tool.inputSchema }),
|
|
3591
|
+
prompt: [
|
|
3592
|
+
`The model tried to call the tool "${toolCall.toolName}" with the following inputs:`,
|
|
3593
|
+
JSON.stringify(toolCall.input),
|
|
3594
|
+
`The tool accepts the following schema:`,
|
|
3595
|
+
JSON.stringify(inputSchema(toolCall)),
|
|
3596
|
+
"Please fix the inputs."
|
|
3597
|
+
].join("\n")
|
|
3598
|
+
});
|
|
3599
|
+
return { ...toolCall, input: JSON.stringify(output) };
|
|
3600
|
+
};
|
|
3601
|
+
|
|
3602
|
+
// packages/context/src/lib/render.ts
|
|
3603
|
+
function render(tag, ...fragments) {
|
|
3604
|
+
if (fragments.length === 0) {
|
|
3605
|
+
return "";
|
|
3606
|
+
}
|
|
3607
|
+
const renderer = new XmlRenderer();
|
|
3608
|
+
const wrapped = fragment(tag, ...fragments);
|
|
3609
|
+
return renderer.render([wrapped]);
|
|
3610
|
+
}
|
|
3270
3611
|
export {
|
|
3271
3612
|
BinaryInstallError,
|
|
3272
3613
|
ComposeStartError,
|
|
@@ -3302,6 +3643,7 @@ export {
|
|
|
3302
3643
|
createDockerSandbox,
|
|
3303
3644
|
defaultTokenizer,
|
|
3304
3645
|
discoverSkillsInDirectory,
|
|
3646
|
+
errorRecoveryGuardrail,
|
|
3305
3647
|
estimate,
|
|
3306
3648
|
example,
|
|
3307
3649
|
explain,
|
|
@@ -3322,8 +3664,11 @@ export {
|
|
|
3322
3664
|
parseFrontmatter,
|
|
3323
3665
|
pass,
|
|
3324
3666
|
persona,
|
|
3667
|
+
policy,
|
|
3325
3668
|
preference,
|
|
3669
|
+
principle,
|
|
3326
3670
|
quirk,
|
|
3671
|
+
render,
|
|
3327
3672
|
role,
|
|
3328
3673
|
runGuardrailChain,
|
|
3329
3674
|
skills,
|