@deepagents/context 0.34.0 → 0.35.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 +441 -421
- package/dist/browser.js.map +4 -4
- package/dist/index.js +479 -447
- package/dist/index.js.map +4 -4
- package/dist/lib/agent.d.ts.map +1 -1
- package/dist/lib/engine.d.ts.map +1 -1
- package/dist/lib/fragments/message/user.d.ts +57 -13
- package/dist/lib/fragments/message/user.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -151,8 +151,10 @@ var Agent = class _Agent {
|
|
|
151
151
|
providerOptions: this.#options.providerOptions,
|
|
152
152
|
model: this.#options.model,
|
|
153
153
|
system: systemPrompt,
|
|
154
|
-
messages: await convertToModelMessages(messages
|
|
155
|
-
|
|
154
|
+
messages: await convertToModelMessages(messages, {
|
|
155
|
+
ignoreIncompleteToolCalls: true
|
|
156
|
+
}),
|
|
157
|
+
stopWhen: stepCountIs(200),
|
|
156
158
|
tools: this.#options.tools,
|
|
157
159
|
experimental_context: contextVariables,
|
|
158
160
|
experimental_repairToolCall: createRepairToolCall(this.#options.model),
|
|
@@ -218,9 +220,11 @@ var Agent = class _Agent {
|
|
|
218
220
|
providerOptions: this.#options.providerOptions,
|
|
219
221
|
model,
|
|
220
222
|
system: systemPrompt,
|
|
221
|
-
messages: await convertToModelMessages(messages
|
|
223
|
+
messages: await convertToModelMessages(messages, {
|
|
224
|
+
ignoreIncompleteToolCalls: true
|
|
225
|
+
}),
|
|
222
226
|
experimental_repairToolCall: createRepairToolCall(model),
|
|
223
|
-
stopWhen: stepCountIs(
|
|
227
|
+
stopWhen: stepCountIs(200),
|
|
224
228
|
experimental_transform: config?.transform ?? smoothStream(),
|
|
225
229
|
tools: this.#options.tools,
|
|
226
230
|
experimental_context: contextVariables,
|
|
@@ -360,8 +364,10 @@ function structuredOutput(options) {
|
|
|
360
364
|
providerOptions: options.providerOptions,
|
|
361
365
|
model: options.model,
|
|
362
366
|
system: systemPrompt,
|
|
363
|
-
messages: await convertToModelMessages(messages
|
|
364
|
-
|
|
367
|
+
messages: await convertToModelMessages(messages, {
|
|
368
|
+
ignoreIncompleteToolCalls: true
|
|
369
|
+
}),
|
|
370
|
+
stopWhen: stepCountIs(200),
|
|
365
371
|
experimental_repairToolCall: createRepairToolCall(options.model),
|
|
366
372
|
experimental_context: contextVariables,
|
|
367
373
|
output: Output.object({ schema: options.schema }),
|
|
@@ -385,8 +391,10 @@ function structuredOutput(options) {
|
|
|
385
391
|
model: options.model,
|
|
386
392
|
system: systemPrompt,
|
|
387
393
|
experimental_repairToolCall: createRepairToolCall(options.model),
|
|
388
|
-
messages: await convertToModelMessages(messages
|
|
389
|
-
|
|
394
|
+
messages: await convertToModelMessages(messages, {
|
|
395
|
+
ignoreIncompleteToolCalls: true
|
|
396
|
+
}),
|
|
397
|
+
stopWhen: stepCountIs(200),
|
|
390
398
|
experimental_transform: config?.transform ?? smoothStream(),
|
|
391
399
|
experimental_context: contextVariables,
|
|
392
400
|
output: Output.object({ schema: options.schema }),
|
|
@@ -593,438 +601,93 @@ async function estimate(modelId, renderer, ...fragments) {
|
|
|
593
601
|
// packages/context/src/lib/fragments/message/user.ts
|
|
594
602
|
import { generateId as generateId3 } from "ai";
|
|
595
603
|
|
|
596
|
-
// packages/context/src/lib/
|
|
597
|
-
import
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
// packages/context/src/lib/fragments/message/user.ts
|
|
606
|
-
function everyNTurns(n) {
|
|
607
|
-
return ({ turn }) => turn % n === 0;
|
|
608
|
-
}
|
|
609
|
-
function once() {
|
|
610
|
-
return ({ turn }) => turn === 1;
|
|
611
|
-
}
|
|
612
|
-
function firstN(n) {
|
|
613
|
-
return ({ turn }) => turn <= n;
|
|
614
|
-
}
|
|
615
|
-
function afterTurn(n) {
|
|
616
|
-
return ({ turn }) => turn > n;
|
|
617
|
-
}
|
|
618
|
-
function and(...predicates) {
|
|
619
|
-
return (ctx) => predicates.every((p) => p(ctx));
|
|
620
|
-
}
|
|
621
|
-
function or(...predicates) {
|
|
622
|
-
return (ctx) => predicates.some((p) => p(ctx));
|
|
623
|
-
}
|
|
624
|
-
function not(predicate) {
|
|
625
|
-
return (ctx) => !predicate(ctx);
|
|
626
|
-
}
|
|
627
|
-
function contentIncludes(keywords) {
|
|
628
|
-
const lower = keywords.map((k) => k.toLowerCase());
|
|
629
|
-
return (ctx) => {
|
|
630
|
-
const text = ctx.content.toLowerCase();
|
|
631
|
-
return lower.some((kw) => text.includes(kw));
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
function contentPattern(pattern) {
|
|
635
|
-
return (ctx) => {
|
|
636
|
-
pattern.lastIndex = 0;
|
|
637
|
-
return pattern.test(ctx.content);
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
|
-
function toDateParts(date, tz) {
|
|
641
|
-
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
642
|
-
timeZone: tz,
|
|
643
|
-
year: "numeric",
|
|
644
|
-
month: "2-digit",
|
|
645
|
-
day: "2-digit",
|
|
646
|
-
hour: "2-digit",
|
|
647
|
-
hourCycle: "h23"
|
|
648
|
-
}).formatToParts(date);
|
|
649
|
-
const get = (type) => parts.find((p) => p.type === type).value;
|
|
650
|
-
return {
|
|
651
|
-
year: get("year"),
|
|
652
|
-
month: get("month"),
|
|
653
|
-
day: get("day"),
|
|
654
|
-
hour: get("hour")
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
function temporalChanged(ctx, tz, getKey) {
|
|
658
|
-
if (ctx.lastMessageAt === void 0) return true;
|
|
659
|
-
const nowParts = toDateParts(/* @__PURE__ */ new Date(), tz);
|
|
660
|
-
const prevParts = toDateParts(new Date(ctx.lastMessageAt), tz);
|
|
661
|
-
return getKey(nowParts) !== getKey(prevParts);
|
|
662
|
-
}
|
|
663
|
-
function getSeason(month) {
|
|
664
|
-
if (month >= 2 && month <= 4) return "Spring";
|
|
665
|
-
if (month >= 5 && month <= 7) return "Summer";
|
|
666
|
-
if (month >= 8 && month <= 10) return "Fall";
|
|
667
|
-
return "Winter";
|
|
668
|
-
}
|
|
669
|
-
function isoWeekKey(parts) {
|
|
670
|
-
const d = new Date(
|
|
671
|
-
Date.UTC(
|
|
672
|
-
parseInt(parts.year),
|
|
673
|
-
parseInt(parts.month) - 1,
|
|
674
|
-
parseInt(parts.day)
|
|
675
|
-
)
|
|
676
|
-
);
|
|
677
|
-
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
|
|
678
|
-
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
679
|
-
const weekNo = Math.ceil(
|
|
680
|
-
((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7
|
|
681
|
-
);
|
|
682
|
-
return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
|
|
683
|
-
}
|
|
684
|
-
function dayChanged(tz = "UTC") {
|
|
685
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}`);
|
|
686
|
-
}
|
|
687
|
-
function hourChanged(tz = "UTC") {
|
|
688
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}-${p.hour}`);
|
|
689
|
-
}
|
|
690
|
-
function monthChanged(tz = "UTC") {
|
|
691
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}`);
|
|
692
|
-
}
|
|
693
|
-
function yearChanged(tz = "UTC") {
|
|
694
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => p.year);
|
|
695
|
-
}
|
|
696
|
-
function seasonChanged(tz = "UTC") {
|
|
697
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => getSeason(parseInt(p.month) - 1));
|
|
698
|
-
}
|
|
699
|
-
function weekChanged(tz = "UTC") {
|
|
700
|
-
return (ctx) => temporalChanged(ctx, tz, isoWeekKey);
|
|
701
|
-
}
|
|
702
|
-
function isConditionalReminder(fragment2) {
|
|
703
|
-
return fragment2.name === "reminder" && !!fragment2.metadata?.reminder;
|
|
704
|
-
}
|
|
705
|
-
function getConditionalReminder(fragment2) {
|
|
706
|
-
return fragment2.metadata.reminder;
|
|
707
|
-
}
|
|
708
|
-
var SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
|
|
709
|
-
var SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
|
|
710
|
-
function getReminderRanges(metadata) {
|
|
711
|
-
return metadata?.reminders ?? [];
|
|
712
|
-
}
|
|
713
|
-
function stripTextByRanges(text, ranges) {
|
|
714
|
-
if (ranges.length === 0) {
|
|
715
|
-
return text;
|
|
604
|
+
// packages/context/src/lib/renderers/abstract.renderer.ts
|
|
605
|
+
import pluralize from "pluralize";
|
|
606
|
+
import { titlecase } from "stringcase";
|
|
607
|
+
var ContextRenderer = class {
|
|
608
|
+
options;
|
|
609
|
+
constructor(options = {}) {
|
|
610
|
+
this.options = options;
|
|
716
611
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
return text;
|
|
612
|
+
/**
|
|
613
|
+
* Check if data is a primitive (string, number, boolean).
|
|
614
|
+
*/
|
|
615
|
+
isPrimitive(data) {
|
|
616
|
+
return typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
723
617
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
618
|
+
/**
|
|
619
|
+
* Group fragments by name for groupFragments option.
|
|
620
|
+
*/
|
|
621
|
+
groupByName(fragments) {
|
|
622
|
+
const groups = /* @__PURE__ */ new Map();
|
|
623
|
+
for (const fragment2 of fragments) {
|
|
624
|
+
const existing = groups.get(fragment2.name) ?? [];
|
|
625
|
+
existing.push(fragment2);
|
|
626
|
+
groups.set(fragment2.name, existing);
|
|
627
|
+
}
|
|
628
|
+
return groups;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Remove null/undefined from fragments and fragment data recursively.
|
|
632
|
+
* This protects renderers from nullish values and ensures they are ignored
|
|
633
|
+
* consistently across all output formats.
|
|
634
|
+
*/
|
|
635
|
+
sanitizeFragments(fragments) {
|
|
636
|
+
const sanitized = [];
|
|
637
|
+
for (const fragment2 of fragments) {
|
|
638
|
+
const cleaned = this.sanitizeFragment(fragment2, /* @__PURE__ */ new WeakSet());
|
|
639
|
+
if (cleaned) {
|
|
640
|
+
sanitized.push(cleaned);
|
|
730
641
|
}
|
|
731
|
-
continue;
|
|
732
642
|
}
|
|
733
|
-
|
|
734
|
-
cursor = range.end;
|
|
643
|
+
return sanitized;
|
|
735
644
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
const partRanges = rangesByPartIndex.get(range.partIndex) ?? [];
|
|
746
|
-
partRanges.push({ start: range.start, end: range.end });
|
|
747
|
-
rangesByPartIndex.set(range.partIndex, partRanges);
|
|
645
|
+
sanitizeFragment(fragment2, seen) {
|
|
646
|
+
const data = this.sanitizeData(getFragmentData(fragment2), seen);
|
|
647
|
+
if (data == null) {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
...fragment2,
|
|
652
|
+
data
|
|
653
|
+
};
|
|
748
654
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
if (clonedPart.type !== "text" || ranges === void 0) {
|
|
753
|
-
return [clonedPart];
|
|
655
|
+
sanitizeData(data, seen) {
|
|
656
|
+
if (data == null) {
|
|
657
|
+
return void 0;
|
|
754
658
|
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
return [];
|
|
659
|
+
if (isFragment(data)) {
|
|
660
|
+
return this.sanitizeFragment(data, seen) ?? void 0;
|
|
758
661
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
662
|
+
if (Array.isArray(data)) {
|
|
663
|
+
if (seen.has(data)) {
|
|
664
|
+
return void 0;
|
|
665
|
+
}
|
|
666
|
+
seen.add(data);
|
|
667
|
+
const cleaned = [];
|
|
668
|
+
for (const item of data) {
|
|
669
|
+
const sanitizedItem = this.sanitizeData(item, seen);
|
|
670
|
+
if (sanitizedItem != null) {
|
|
671
|
+
cleaned.push(sanitizedItem);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return cleaned;
|
|
772
675
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
for (let i = message2.parts.length - 1; i >= 0; i--) {
|
|
789
|
-
if (message2.parts[i].type === "text") {
|
|
790
|
-
return i;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
return void 0;
|
|
794
|
-
}
|
|
795
|
-
function ensureTextPart(message2) {
|
|
796
|
-
const existingIndex = findLastTextPartIndex(message2);
|
|
797
|
-
if (existingIndex !== void 0) {
|
|
798
|
-
return existingIndex;
|
|
799
|
-
}
|
|
800
|
-
const reminderPart = {
|
|
801
|
-
type: "text",
|
|
802
|
-
text: ""
|
|
803
|
-
};
|
|
804
|
-
message2.parts.push(reminderPart);
|
|
805
|
-
return message2.parts.length - 1;
|
|
806
|
-
}
|
|
807
|
-
function applyInlineReminder(message2, value) {
|
|
808
|
-
const partIndex = ensureTextPart(message2);
|
|
809
|
-
const textPart = message2.parts[partIndex];
|
|
810
|
-
if (textPart.type !== "text") {
|
|
811
|
-
throw new Error("Failed to resolve text part for inline reminder");
|
|
812
|
-
}
|
|
813
|
-
const reminderText = formatTaggedReminder(value);
|
|
814
|
-
const start = textPart.text.length;
|
|
815
|
-
const updatedText = `${textPart.text}${reminderText}`;
|
|
816
|
-
message2.parts[partIndex] = { ...textPart, text: updatedText };
|
|
817
|
-
return {
|
|
818
|
-
id: generateId3(),
|
|
819
|
-
text: value,
|
|
820
|
-
partIndex,
|
|
821
|
-
start,
|
|
822
|
-
end: start + reminderText.length,
|
|
823
|
-
mode: "inline"
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
function applyPartReminder(message2, value) {
|
|
827
|
-
const part = { type: "text", text: value };
|
|
828
|
-
message2.parts.push(part);
|
|
829
|
-
const partIndex = message2.parts.length - 1;
|
|
830
|
-
return {
|
|
831
|
-
id: generateId3(),
|
|
832
|
-
text: value,
|
|
833
|
-
partIndex,
|
|
834
|
-
start: 0,
|
|
835
|
-
end: value.length,
|
|
836
|
-
mode: "part"
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
function resolveReminderText(item, ctx) {
|
|
840
|
-
return resolveReminder(item, ctx)?.text ?? "";
|
|
841
|
-
}
|
|
842
|
-
function normalizeReminderResolution(value) {
|
|
843
|
-
if (typeof value === "string") {
|
|
844
|
-
return value.trim().length === 0 ? null : { text: value };
|
|
845
|
-
}
|
|
846
|
-
if (value.text.trim().length === 0) {
|
|
847
|
-
return null;
|
|
848
|
-
}
|
|
849
|
-
return value;
|
|
850
|
-
}
|
|
851
|
-
function resolveReminder(item, ctx) {
|
|
852
|
-
const resolvedText = typeof item.text === "function" ? item.text(ctx) : item.text;
|
|
853
|
-
const resolved = normalizeReminderResolution(resolvedText);
|
|
854
|
-
if (!resolved) {
|
|
855
|
-
return null;
|
|
856
|
-
}
|
|
857
|
-
const metadata = item.metadata || resolved.metadata ? {
|
|
858
|
-
...item.metadata ?? {},
|
|
859
|
-
...resolved.metadata ?? {}
|
|
860
|
-
} : void 0;
|
|
861
|
-
return metadata ? { ...resolved, metadata } : resolved;
|
|
862
|
-
}
|
|
863
|
-
function mergeMessageMetadata(message2, addedMetadata) {
|
|
864
|
-
if (Object.keys(addedMetadata).length === 0) {
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
868
|
-
message2.metadata = { ...metadata, ...addedMetadata };
|
|
869
|
-
}
|
|
870
|
-
function applyReminderToMessage(message2, item, ctx) {
|
|
871
|
-
const resolved = resolveReminder(item, ctx);
|
|
872
|
-
if (!resolved) {
|
|
873
|
-
return null;
|
|
874
|
-
}
|
|
875
|
-
if (resolved.metadata) {
|
|
876
|
-
mergeMessageMetadata(message2, resolved.metadata);
|
|
877
|
-
}
|
|
878
|
-
return item.asPart ? applyPartReminder(message2, resolved.text) : applyInlineReminder(message2, resolved.text);
|
|
879
|
-
}
|
|
880
|
-
function mergeReminderMetadata(message2, addedReminders) {
|
|
881
|
-
if (addedReminders.length === 0) return;
|
|
882
|
-
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
883
|
-
const existing = Array.isArray(metadata.reminders) ? metadata.reminders : [];
|
|
884
|
-
metadata.reminders = [...existing, ...addedReminders];
|
|
885
|
-
message2.metadata = metadata;
|
|
886
|
-
}
|
|
887
|
-
function reminder(text, options) {
|
|
888
|
-
if (typeof text === "string") {
|
|
889
|
-
assertReminderText(text);
|
|
890
|
-
}
|
|
891
|
-
if (options && "when" in options && options.when) {
|
|
892
|
-
return {
|
|
893
|
-
name: "reminder",
|
|
894
|
-
metadata: {
|
|
895
|
-
reminder: {
|
|
896
|
-
text,
|
|
897
|
-
when: options.when,
|
|
898
|
-
asPart: options.asPart ?? false
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
return {
|
|
904
|
-
text,
|
|
905
|
-
asPart: options?.asPart ?? false
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
function user(content, ...reminders) {
|
|
909
|
-
const message2 = typeof content === "string" ? {
|
|
910
|
-
id: generateId3(),
|
|
911
|
-
role: "user",
|
|
912
|
-
parts: [{ type: "text", text: content }]
|
|
913
|
-
} : { ...content, role: "user", parts: [...content.parts] };
|
|
914
|
-
if (reminders.length > 0) {
|
|
915
|
-
const plainText = extractPlainText(message2);
|
|
916
|
-
const added = [];
|
|
917
|
-
for (const item of reminders) {
|
|
918
|
-
const meta = applyReminderToMessage(message2, item, {
|
|
919
|
-
content: plainText
|
|
920
|
-
});
|
|
921
|
-
if (meta) added.push(meta);
|
|
922
|
-
}
|
|
923
|
-
mergeReminderMetadata(message2, added);
|
|
924
|
-
}
|
|
925
|
-
return {
|
|
926
|
-
id: message2.id,
|
|
927
|
-
name: "user",
|
|
928
|
-
type: "message",
|
|
929
|
-
persist: true,
|
|
930
|
-
codec: {
|
|
931
|
-
decode() {
|
|
932
|
-
return message2;
|
|
933
|
-
},
|
|
934
|
-
encode() {
|
|
935
|
-
return message2;
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
// packages/context/src/lib/renderers/abstract.renderer.ts
|
|
942
|
-
import pluralize from "pluralize";
|
|
943
|
-
import { titlecase } from "stringcase";
|
|
944
|
-
var ContextRenderer = class {
|
|
945
|
-
options;
|
|
946
|
-
constructor(options = {}) {
|
|
947
|
-
this.options = options;
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Check if data is a primitive (string, number, boolean).
|
|
951
|
-
*/
|
|
952
|
-
isPrimitive(data) {
|
|
953
|
-
return typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
954
|
-
}
|
|
955
|
-
/**
|
|
956
|
-
* Group fragments by name for groupFragments option.
|
|
957
|
-
*/
|
|
958
|
-
groupByName(fragments) {
|
|
959
|
-
const groups = /* @__PURE__ */ new Map();
|
|
960
|
-
for (const fragment2 of fragments) {
|
|
961
|
-
const existing = groups.get(fragment2.name) ?? [];
|
|
962
|
-
existing.push(fragment2);
|
|
963
|
-
groups.set(fragment2.name, existing);
|
|
964
|
-
}
|
|
965
|
-
return groups;
|
|
966
|
-
}
|
|
967
|
-
/**
|
|
968
|
-
* Remove null/undefined from fragments and fragment data recursively.
|
|
969
|
-
* This protects renderers from nullish values and ensures they are ignored
|
|
970
|
-
* consistently across all output formats.
|
|
971
|
-
*/
|
|
972
|
-
sanitizeFragments(fragments) {
|
|
973
|
-
const sanitized = [];
|
|
974
|
-
for (const fragment2 of fragments) {
|
|
975
|
-
const cleaned = this.sanitizeFragment(fragment2, /* @__PURE__ */ new WeakSet());
|
|
976
|
-
if (cleaned) {
|
|
977
|
-
sanitized.push(cleaned);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
return sanitized;
|
|
981
|
-
}
|
|
982
|
-
sanitizeFragment(fragment2, seen) {
|
|
983
|
-
const data = this.sanitizeData(getFragmentData(fragment2), seen);
|
|
984
|
-
if (data == null) {
|
|
985
|
-
return null;
|
|
986
|
-
}
|
|
987
|
-
return {
|
|
988
|
-
...fragment2,
|
|
989
|
-
data
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
sanitizeData(data, seen) {
|
|
993
|
-
if (data == null) {
|
|
994
|
-
return void 0;
|
|
995
|
-
}
|
|
996
|
-
if (isFragment(data)) {
|
|
997
|
-
return this.sanitizeFragment(data, seen) ?? void 0;
|
|
998
|
-
}
|
|
999
|
-
if (Array.isArray(data)) {
|
|
1000
|
-
if (seen.has(data)) {
|
|
1001
|
-
return void 0;
|
|
1002
|
-
}
|
|
1003
|
-
seen.add(data);
|
|
1004
|
-
const cleaned = [];
|
|
1005
|
-
for (const item of data) {
|
|
1006
|
-
const sanitizedItem = this.sanitizeData(item, seen);
|
|
1007
|
-
if (sanitizedItem != null) {
|
|
1008
|
-
cleaned.push(sanitizedItem);
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
return cleaned;
|
|
1012
|
-
}
|
|
1013
|
-
if (isFragmentObject(data)) {
|
|
1014
|
-
if (seen.has(data)) {
|
|
1015
|
-
return void 0;
|
|
1016
|
-
}
|
|
1017
|
-
seen.add(data);
|
|
1018
|
-
const cleaned = {};
|
|
1019
|
-
for (const [key, value] of Object.entries(data)) {
|
|
1020
|
-
const sanitizedValue = this.sanitizeData(value, seen);
|
|
1021
|
-
if (sanitizedValue != null) {
|
|
1022
|
-
cleaned[key] = sanitizedValue;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
return cleaned;
|
|
1026
|
-
}
|
|
1027
|
-
return data;
|
|
676
|
+
if (isFragmentObject(data)) {
|
|
677
|
+
if (seen.has(data)) {
|
|
678
|
+
return void 0;
|
|
679
|
+
}
|
|
680
|
+
seen.add(data);
|
|
681
|
+
const cleaned = {};
|
|
682
|
+
for (const [key, value] of Object.entries(data)) {
|
|
683
|
+
const sanitizedValue = this.sanitizeData(value, seen);
|
|
684
|
+
if (sanitizedValue != null) {
|
|
685
|
+
cleaned[key] = sanitizedValue;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return cleaned;
|
|
689
|
+
}
|
|
690
|
+
return data;
|
|
1028
691
|
}
|
|
1029
692
|
/**
|
|
1030
693
|
* Template method - dispatches value to appropriate handler.
|
|
@@ -1814,16 +1477,380 @@ ${entries}`;
|
|
|
1814
1477
|
}
|
|
1815
1478
|
};
|
|
1816
1479
|
|
|
1817
|
-
// packages/context/src/lib/
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
// packages/context/src/lib/engine.ts
|
|
1822
|
-
function estimateMessageContent(data) {
|
|
1823
|
-
return typeof data === "string" ? data : JSON.stringify(data);
|
|
1480
|
+
// packages/context/src/lib/text.ts
|
|
1481
|
+
import { isTextUIPart } from "ai";
|
|
1482
|
+
function getTextParts(message2) {
|
|
1483
|
+
return message2.parts.filter(isTextUIPart).map((part) => part.text);
|
|
1824
1484
|
}
|
|
1825
|
-
function
|
|
1826
|
-
return
|
|
1485
|
+
function extractPlainText(message2) {
|
|
1486
|
+
return getTextParts(message2).join(" ");
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
// packages/context/src/lib/fragments/message/user.ts
|
|
1490
|
+
function everyNTurns(n) {
|
|
1491
|
+
return ({ turn }) => turn % n === 0;
|
|
1492
|
+
}
|
|
1493
|
+
function once() {
|
|
1494
|
+
return ({ turn }) => turn === 1;
|
|
1495
|
+
}
|
|
1496
|
+
function firstN(n) {
|
|
1497
|
+
return ({ turn }) => turn <= n;
|
|
1498
|
+
}
|
|
1499
|
+
function afterTurn(n) {
|
|
1500
|
+
return ({ turn }) => turn > n;
|
|
1501
|
+
}
|
|
1502
|
+
function and(...predicates) {
|
|
1503
|
+
return async (ctx) => {
|
|
1504
|
+
for (const it of predicates) {
|
|
1505
|
+
if (!await it(ctx)) return false;
|
|
1506
|
+
}
|
|
1507
|
+
return true;
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
function or(...predicates) {
|
|
1511
|
+
return async (ctx) => {
|
|
1512
|
+
for (const it of predicates) {
|
|
1513
|
+
if (await it(ctx)) return true;
|
|
1514
|
+
}
|
|
1515
|
+
return false;
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
function not(predicate) {
|
|
1519
|
+
return async (ctx) => !await predicate(ctx);
|
|
1520
|
+
}
|
|
1521
|
+
function contentIncludes(keywords) {
|
|
1522
|
+
const lower = keywords.map((k) => k.toLowerCase());
|
|
1523
|
+
return (ctx) => {
|
|
1524
|
+
const text = ctx.content.toLowerCase();
|
|
1525
|
+
return lower.some((kw) => text.includes(kw));
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
function contentPattern(pattern) {
|
|
1529
|
+
return (ctx) => {
|
|
1530
|
+
pattern.lastIndex = 0;
|
|
1531
|
+
return pattern.test(ctx.content);
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
function toDateParts(date, tz) {
|
|
1535
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
1536
|
+
timeZone: tz,
|
|
1537
|
+
year: "numeric",
|
|
1538
|
+
month: "2-digit",
|
|
1539
|
+
day: "2-digit",
|
|
1540
|
+
hour: "2-digit",
|
|
1541
|
+
hourCycle: "h23"
|
|
1542
|
+
}).formatToParts(date);
|
|
1543
|
+
const get = (type) => parts.find((p) => p.type === type).value;
|
|
1544
|
+
return {
|
|
1545
|
+
year: get("year"),
|
|
1546
|
+
month: get("month"),
|
|
1547
|
+
day: get("day"),
|
|
1548
|
+
hour: get("hour")
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
function temporalChanged(ctx, tz, getKey) {
|
|
1552
|
+
if (ctx.lastMessageAt === void 0) return true;
|
|
1553
|
+
const nowParts = toDateParts(/* @__PURE__ */ new Date(), tz);
|
|
1554
|
+
const prevParts = toDateParts(new Date(ctx.lastMessageAt), tz);
|
|
1555
|
+
return getKey(nowParts) !== getKey(prevParts);
|
|
1556
|
+
}
|
|
1557
|
+
function getSeason(month) {
|
|
1558
|
+
if (month >= 2 && month <= 4) return "Spring";
|
|
1559
|
+
if (month >= 5 && month <= 7) return "Summer";
|
|
1560
|
+
if (month >= 8 && month <= 10) return "Fall";
|
|
1561
|
+
return "Winter";
|
|
1562
|
+
}
|
|
1563
|
+
function isoWeekKey(parts) {
|
|
1564
|
+
const d = new Date(
|
|
1565
|
+
Date.UTC(
|
|
1566
|
+
parseInt(parts.year),
|
|
1567
|
+
parseInt(parts.month) - 1,
|
|
1568
|
+
parseInt(parts.day)
|
|
1569
|
+
)
|
|
1570
|
+
);
|
|
1571
|
+
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
|
|
1572
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
1573
|
+
const weekNo = Math.ceil(
|
|
1574
|
+
((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7
|
|
1575
|
+
);
|
|
1576
|
+
return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
|
|
1577
|
+
}
|
|
1578
|
+
function dayChanged(tz = "UTC") {
|
|
1579
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}`);
|
|
1580
|
+
}
|
|
1581
|
+
function hourChanged(tz = "UTC") {
|
|
1582
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}-${p.hour}`);
|
|
1583
|
+
}
|
|
1584
|
+
function monthChanged(tz = "UTC") {
|
|
1585
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}`);
|
|
1586
|
+
}
|
|
1587
|
+
function yearChanged(tz = "UTC") {
|
|
1588
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => p.year);
|
|
1589
|
+
}
|
|
1590
|
+
function seasonChanged(tz = "UTC") {
|
|
1591
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => getSeason(parseInt(p.month) - 1));
|
|
1592
|
+
}
|
|
1593
|
+
function weekChanged(tz = "UTC") {
|
|
1594
|
+
return (ctx) => temporalChanged(ctx, tz, isoWeekKey);
|
|
1595
|
+
}
|
|
1596
|
+
function isConditionalReminder(fragment2) {
|
|
1597
|
+
return fragment2.name === "reminder" && !!fragment2.metadata?.reminder;
|
|
1598
|
+
}
|
|
1599
|
+
function getConditionalReminder(fragment2) {
|
|
1600
|
+
return fragment2.metadata.reminder;
|
|
1601
|
+
}
|
|
1602
|
+
var SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
|
|
1603
|
+
var SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
|
|
1604
|
+
function getReminderRanges(metadata) {
|
|
1605
|
+
return metadata?.reminders ?? [];
|
|
1606
|
+
}
|
|
1607
|
+
function stripTextByRanges(text, ranges) {
|
|
1608
|
+
if (ranges.length === 0) {
|
|
1609
|
+
return text;
|
|
1610
|
+
}
|
|
1611
|
+
const normalized = ranges.map((range) => ({
|
|
1612
|
+
start: Math.max(0, Math.min(text.length, range.start)),
|
|
1613
|
+
end: Math.max(0, Math.min(text.length, range.end))
|
|
1614
|
+
})).filter((range) => range.end > range.start).sort((a, b) => a.start - b.start);
|
|
1615
|
+
if (normalized.length === 0) {
|
|
1616
|
+
return text;
|
|
1617
|
+
}
|
|
1618
|
+
let cursor = 0;
|
|
1619
|
+
let output = "";
|
|
1620
|
+
for (const range of normalized) {
|
|
1621
|
+
if (range.start < cursor) {
|
|
1622
|
+
if (range.end > cursor) {
|
|
1623
|
+
cursor = range.end;
|
|
1624
|
+
}
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
output += text.slice(cursor, range.start);
|
|
1628
|
+
cursor = range.end;
|
|
1629
|
+
}
|
|
1630
|
+
output += text.slice(cursor);
|
|
1631
|
+
return output.trimEnd();
|
|
1632
|
+
}
|
|
1633
|
+
function stripReminders(message2) {
|
|
1634
|
+
const reminderRanges = getReminderRanges(
|
|
1635
|
+
isRecord(message2.metadata) ? message2.metadata : void 0
|
|
1636
|
+
);
|
|
1637
|
+
const rangesByPartIndex = /* @__PURE__ */ new Map();
|
|
1638
|
+
for (const range of reminderRanges) {
|
|
1639
|
+
const partRanges = rangesByPartIndex.get(range.partIndex) ?? [];
|
|
1640
|
+
partRanges.push({ start: range.start, end: range.end });
|
|
1641
|
+
rangesByPartIndex.set(range.partIndex, partRanges);
|
|
1642
|
+
}
|
|
1643
|
+
const strippedParts = message2.parts.flatMap((part, partIndex) => {
|
|
1644
|
+
const clonedPart = { ...part };
|
|
1645
|
+
const ranges = rangesByPartIndex.get(partIndex);
|
|
1646
|
+
if (clonedPart.type !== "text" || ranges === void 0) {
|
|
1647
|
+
return [clonedPart];
|
|
1648
|
+
}
|
|
1649
|
+
const strippedText = stripTextByRanges(clonedPart.text, ranges);
|
|
1650
|
+
if (strippedText.length === 0) {
|
|
1651
|
+
return [];
|
|
1652
|
+
}
|
|
1653
|
+
return [{ ...clonedPart, text: strippedText }];
|
|
1654
|
+
});
|
|
1655
|
+
const nextMessage = {
|
|
1656
|
+
...message2,
|
|
1657
|
+
parts: strippedParts
|
|
1658
|
+
};
|
|
1659
|
+
if (isRecord(message2.metadata)) {
|
|
1660
|
+
const metadata = { ...message2.metadata };
|
|
1661
|
+
delete metadata.reminders;
|
|
1662
|
+
if (Object.keys(metadata).length > 0) {
|
|
1663
|
+
nextMessage.metadata = metadata;
|
|
1664
|
+
} else {
|
|
1665
|
+
delete nextMessage.metadata;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
return nextMessage;
|
|
1669
|
+
}
|
|
1670
|
+
function isRecord(value) {
|
|
1671
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1672
|
+
}
|
|
1673
|
+
function assertReminderText(text) {
|
|
1674
|
+
if (text.trim().length === 0) {
|
|
1675
|
+
throw new Error("Reminder text must not be empty");
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
function formatTaggedReminder(text) {
|
|
1679
|
+
return `${SYSTEM_REMINDER_OPEN_TAG}${text}${SYSTEM_REMINDER_CLOSE_TAG}`;
|
|
1680
|
+
}
|
|
1681
|
+
function findLastTextPartIndex(message2) {
|
|
1682
|
+
for (let i = message2.parts.length - 1; i >= 0; i--) {
|
|
1683
|
+
if (message2.parts[i].type === "text") {
|
|
1684
|
+
return i;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
return void 0;
|
|
1688
|
+
}
|
|
1689
|
+
function ensureTextPart(message2) {
|
|
1690
|
+
const existingIndex = findLastTextPartIndex(message2);
|
|
1691
|
+
if (existingIndex !== void 0) {
|
|
1692
|
+
return existingIndex;
|
|
1693
|
+
}
|
|
1694
|
+
const reminderPart = {
|
|
1695
|
+
type: "text",
|
|
1696
|
+
text: ""
|
|
1697
|
+
};
|
|
1698
|
+
message2.parts.push(reminderPart);
|
|
1699
|
+
return message2.parts.length - 1;
|
|
1700
|
+
}
|
|
1701
|
+
function applyInlineReminder(message2, value) {
|
|
1702
|
+
const partIndex = ensureTextPart(message2);
|
|
1703
|
+
const textPart = message2.parts[partIndex];
|
|
1704
|
+
if (textPart.type !== "text") {
|
|
1705
|
+
throw new Error("Failed to resolve text part for inline reminder");
|
|
1706
|
+
}
|
|
1707
|
+
const reminderText = formatTaggedReminder(value);
|
|
1708
|
+
const start = textPart.text.length;
|
|
1709
|
+
const updatedText = `${textPart.text}${reminderText}`;
|
|
1710
|
+
message2.parts[partIndex] = { ...textPart, text: updatedText };
|
|
1711
|
+
return {
|
|
1712
|
+
id: generateId3(),
|
|
1713
|
+
text: value,
|
|
1714
|
+
partIndex,
|
|
1715
|
+
start,
|
|
1716
|
+
end: start + reminderText.length,
|
|
1717
|
+
mode: "inline"
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
function applyPartReminder(message2, value) {
|
|
1721
|
+
const part = { type: "text", text: value };
|
|
1722
|
+
message2.parts.push(part);
|
|
1723
|
+
const partIndex = message2.parts.length - 1;
|
|
1724
|
+
return {
|
|
1725
|
+
id: generateId3(),
|
|
1726
|
+
text: value,
|
|
1727
|
+
partIndex,
|
|
1728
|
+
start: 0,
|
|
1729
|
+
end: value.length,
|
|
1730
|
+
mode: "part"
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
function resolveReminderText(item, ctx) {
|
|
1734
|
+
return resolveReminder(item, ctx)?.text ?? "";
|
|
1735
|
+
}
|
|
1736
|
+
function normalizeReminderResolution(value) {
|
|
1737
|
+
if (typeof value === "string") {
|
|
1738
|
+
return value.trim().length === 0 ? null : { text: value };
|
|
1739
|
+
}
|
|
1740
|
+
if (value.text.trim().length === 0) {
|
|
1741
|
+
return null;
|
|
1742
|
+
}
|
|
1743
|
+
return value;
|
|
1744
|
+
}
|
|
1745
|
+
function resolveReminder(item, ctx) {
|
|
1746
|
+
const resolvedText = typeof item.text === "function" ? item.text(ctx) : item.text;
|
|
1747
|
+
const resolved = normalizeReminderResolution(resolvedText);
|
|
1748
|
+
if (!resolved) {
|
|
1749
|
+
return null;
|
|
1750
|
+
}
|
|
1751
|
+
const metadata = item.metadata || resolved.metadata ? {
|
|
1752
|
+
...item.metadata ?? {},
|
|
1753
|
+
...resolved.metadata ?? {}
|
|
1754
|
+
} : void 0;
|
|
1755
|
+
return metadata ? { ...resolved, metadata } : resolved;
|
|
1756
|
+
}
|
|
1757
|
+
async function resolveReminderAsync(item, ctx) {
|
|
1758
|
+
const text = await (typeof item.text === "function" ? item.text(ctx) : item.text);
|
|
1759
|
+
const resolved = normalizeReminderResolution(text);
|
|
1760
|
+
if (!resolved) return null;
|
|
1761
|
+
const metadata = item.metadata || resolved.metadata ? { ...item.metadata ?? {}, ...resolved.metadata ?? {} } : void 0;
|
|
1762
|
+
return metadata ? { ...resolved, metadata } : resolved;
|
|
1763
|
+
}
|
|
1764
|
+
function mergeMessageMetadata(message2, addedMetadata) {
|
|
1765
|
+
if (Object.keys(addedMetadata).length === 0) {
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
1769
|
+
message2.metadata = { ...metadata, ...addedMetadata };
|
|
1770
|
+
}
|
|
1771
|
+
function applyReminderToMessage(message2, item, ctx) {
|
|
1772
|
+
const resolved = resolveReminder(item, ctx);
|
|
1773
|
+
if (!resolved) {
|
|
1774
|
+
return null;
|
|
1775
|
+
}
|
|
1776
|
+
if (resolved.metadata) {
|
|
1777
|
+
mergeMessageMetadata(message2, resolved.metadata);
|
|
1778
|
+
}
|
|
1779
|
+
return item.asPart ? applyPartReminder(message2, resolved.text) : applyInlineReminder(message2, resolved.text);
|
|
1780
|
+
}
|
|
1781
|
+
function mergeReminderMetadata(message2, addedReminders) {
|
|
1782
|
+
if (addedReminders.length === 0) return;
|
|
1783
|
+
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
1784
|
+
const existing = Array.isArray(metadata.reminders) ? metadata.reminders : [];
|
|
1785
|
+
metadata.reminders = [...existing, ...addedReminders];
|
|
1786
|
+
message2.metadata = metadata;
|
|
1787
|
+
}
|
|
1788
|
+
function reminder(textOrFragment, options) {
|
|
1789
|
+
const text = isFragment(textOrFragment) ? new XmlRenderer().render([textOrFragment]) : textOrFragment;
|
|
1790
|
+
if (typeof text === "string") {
|
|
1791
|
+
assertReminderText(text);
|
|
1792
|
+
}
|
|
1793
|
+
if (options && "when" in options && options.when) {
|
|
1794
|
+
return {
|
|
1795
|
+
name: "reminder",
|
|
1796
|
+
data: null,
|
|
1797
|
+
metadata: {
|
|
1798
|
+
reminder: {
|
|
1799
|
+
text,
|
|
1800
|
+
when: options.when,
|
|
1801
|
+
asPart: options.asPart ?? false
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
return {
|
|
1807
|
+
text,
|
|
1808
|
+
asPart: options?.asPart ?? false
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
function user(content, ...reminders) {
|
|
1812
|
+
const message2 = typeof content === "string" ? {
|
|
1813
|
+
id: generateId3(),
|
|
1814
|
+
role: "user",
|
|
1815
|
+
parts: [{ type: "text", text: content }]
|
|
1816
|
+
} : { ...content, role: "user", parts: [...content.parts] };
|
|
1817
|
+
if (reminders.length > 0) {
|
|
1818
|
+
const plainText = extractPlainText(message2);
|
|
1819
|
+
const added = [];
|
|
1820
|
+
for (const item of reminders) {
|
|
1821
|
+
const meta = applyReminderToMessage(message2, item, {
|
|
1822
|
+
content: plainText
|
|
1823
|
+
});
|
|
1824
|
+
if (meta) added.push(meta);
|
|
1825
|
+
}
|
|
1826
|
+
mergeReminderMetadata(message2, added);
|
|
1827
|
+
}
|
|
1828
|
+
return {
|
|
1829
|
+
id: message2.id,
|
|
1830
|
+
name: "user",
|
|
1831
|
+
type: "message",
|
|
1832
|
+
persist: true,
|
|
1833
|
+
codec: {
|
|
1834
|
+
decode() {
|
|
1835
|
+
return message2;
|
|
1836
|
+
},
|
|
1837
|
+
encode() {
|
|
1838
|
+
return message2;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
// packages/context/src/lib/store/store.ts
|
|
1845
|
+
var ContextStore = class {
|
|
1846
|
+
};
|
|
1847
|
+
|
|
1848
|
+
// packages/context/src/lib/engine.ts
|
|
1849
|
+
function estimateMessageContent(data) {
|
|
1850
|
+
return typeof data === "string" ? data : JSON.stringify(data);
|
|
1851
|
+
}
|
|
1852
|
+
function isLanguageModelUsage(value) {
|
|
1853
|
+
return typeof value === "object" && value !== null && "totalTokens" in value;
|
|
1827
1854
|
}
|
|
1828
1855
|
var ContextEngine = class {
|
|
1829
1856
|
/** Non-message fragments (role, hints, etc.) - not persisted in graph */
|
|
@@ -2154,17 +2181,21 @@ var ContextEngine = class {
|
|
|
2154
2181
|
messageCount,
|
|
2155
2182
|
lastAssistantMessage: lastAssistantMessage2
|
|
2156
2183
|
};
|
|
2157
|
-
const
|
|
2184
|
+
const configs = conditionalReminders.map(getConditionalReminder);
|
|
2185
|
+
const whenResults = await Promise.all(
|
|
2186
|
+
configs.map((it) => it.when(whenCtx))
|
|
2187
|
+
);
|
|
2188
|
+
const firedReminders = configs.filter((_, i) => whenResults[i]);
|
|
2158
2189
|
if (firedReminders.length > 0) {
|
|
2159
|
-
const
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2190
|
+
const resolvedOrNull = await Promise.all(
|
|
2191
|
+
firedReminders.map((it) => resolveReminderAsync(it, whenCtx))
|
|
2192
|
+
);
|
|
2193
|
+
const reminders = resolvedOrNull.flatMap((resolved, i) => {
|
|
2194
|
+
if (!resolved) return [];
|
|
2164
2195
|
return [
|
|
2165
2196
|
{
|
|
2166
2197
|
text: resolved.text,
|
|
2167
|
-
asPart:
|
|
2198
|
+
asPart: firedReminders[i].asPart,
|
|
2168
2199
|
metadata: resolved.metadata
|
|
2169
2200
|
}
|
|
2170
2201
|
];
|
|
@@ -8032,6 +8063,7 @@ export {
|
|
|
8032
8063
|
render,
|
|
8033
8064
|
resetAdaptivePolling,
|
|
8034
8065
|
resolveReminder,
|
|
8066
|
+
resolveReminderAsync,
|
|
8035
8067
|
resolveReminderText,
|
|
8036
8068
|
role,
|
|
8037
8069
|
runGuardrailChain,
|