@deepagents/context 0.34.0 → 0.36.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 +519 -518
- package/dist/browser.js.map +4 -4
- package/dist/index.js +516 -530
- package/dist/index.js.map +4 -4
- package/dist/lib/agent.d.ts +2 -0
- 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/dist/lib/fragments.d.ts +0 -40
- package/dist/lib/fragments.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/browser.js
CHANGED
|
@@ -69,22 +69,6 @@ function assistantText(content, options) {
|
|
|
69
69
|
parts: [{ type: "text", text: content }]
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
|
-
var LAZY_ID = Symbol.for("@deepagents/context:lazy-id");
|
|
73
|
-
function isLazyFragment(fragment2) {
|
|
74
|
-
return LAZY_ID in fragment2;
|
|
75
|
-
}
|
|
76
|
-
function lastAssistantMessage(content) {
|
|
77
|
-
return {
|
|
78
|
-
name: "assistant",
|
|
79
|
-
type: "message",
|
|
80
|
-
persist: true,
|
|
81
|
-
data: "content",
|
|
82
|
-
[LAZY_ID]: {
|
|
83
|
-
type: "last-assistant",
|
|
84
|
-
content
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
72
|
|
|
89
73
|
// packages/context/src/lib/codec/serialized-codec.ts
|
|
90
74
|
function encodeSerializedValue(value) {
|
|
@@ -902,460 +886,93 @@ async function estimate(modelId, renderer, ...fragments) {
|
|
|
902
886
|
// packages/context/src/lib/fragments/message/user.ts
|
|
903
887
|
import { generateId as generateId2 } from "ai";
|
|
904
888
|
|
|
905
|
-
// packages/context/src/lib/
|
|
906
|
-
import
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// packages/context/src/lib/fragments/message/user.ts
|
|
915
|
-
function everyNTurns(n) {
|
|
916
|
-
return ({ turn }) => turn % n === 0;
|
|
917
|
-
}
|
|
918
|
-
function once() {
|
|
919
|
-
return ({ turn }) => turn === 1;
|
|
920
|
-
}
|
|
921
|
-
function firstN(n) {
|
|
922
|
-
return ({ turn }) => turn <= n;
|
|
923
|
-
}
|
|
924
|
-
function afterTurn(n) {
|
|
925
|
-
return ({ turn }) => turn > n;
|
|
926
|
-
}
|
|
927
|
-
function and(...predicates) {
|
|
928
|
-
return (ctx) => predicates.every((p) => p(ctx));
|
|
929
|
-
}
|
|
930
|
-
function or(...predicates) {
|
|
931
|
-
return (ctx) => predicates.some((p) => p(ctx));
|
|
932
|
-
}
|
|
933
|
-
function not(predicate) {
|
|
934
|
-
return (ctx) => !predicate(ctx);
|
|
935
|
-
}
|
|
936
|
-
function contentIncludes(keywords) {
|
|
937
|
-
const lower = keywords.map((k) => k.toLowerCase());
|
|
938
|
-
return (ctx) => {
|
|
939
|
-
const text = ctx.content.toLowerCase();
|
|
940
|
-
return lower.some((kw) => text.includes(kw));
|
|
941
|
-
};
|
|
942
|
-
}
|
|
943
|
-
function contentPattern(pattern) {
|
|
944
|
-
return (ctx) => {
|
|
945
|
-
pattern.lastIndex = 0;
|
|
946
|
-
return pattern.test(ctx.content);
|
|
947
|
-
};
|
|
948
|
-
}
|
|
949
|
-
function toDateParts(date, tz) {
|
|
950
|
-
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
951
|
-
timeZone: tz,
|
|
952
|
-
year: "numeric",
|
|
953
|
-
month: "2-digit",
|
|
954
|
-
day: "2-digit",
|
|
955
|
-
hour: "2-digit",
|
|
956
|
-
hourCycle: "h23"
|
|
957
|
-
}).formatToParts(date);
|
|
958
|
-
const get = (type) => parts.find((p) => p.type === type).value;
|
|
959
|
-
return {
|
|
960
|
-
year: get("year"),
|
|
961
|
-
month: get("month"),
|
|
962
|
-
day: get("day"),
|
|
963
|
-
hour: get("hour")
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
function temporalChanged(ctx, tz, getKey) {
|
|
967
|
-
if (ctx.lastMessageAt === void 0) return true;
|
|
968
|
-
const nowParts = toDateParts(/* @__PURE__ */ new Date(), tz);
|
|
969
|
-
const prevParts = toDateParts(new Date(ctx.lastMessageAt), tz);
|
|
970
|
-
return getKey(nowParts) !== getKey(prevParts);
|
|
971
|
-
}
|
|
972
|
-
function getSeason(month) {
|
|
973
|
-
if (month >= 2 && month <= 4) return "Spring";
|
|
974
|
-
if (month >= 5 && month <= 7) return "Summer";
|
|
975
|
-
if (month >= 8 && month <= 10) return "Fall";
|
|
976
|
-
return "Winter";
|
|
977
|
-
}
|
|
978
|
-
function isoWeekKey(parts) {
|
|
979
|
-
const d = new Date(
|
|
980
|
-
Date.UTC(
|
|
981
|
-
parseInt(parts.year),
|
|
982
|
-
parseInt(parts.month) - 1,
|
|
983
|
-
parseInt(parts.day)
|
|
984
|
-
)
|
|
985
|
-
);
|
|
986
|
-
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
|
|
987
|
-
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
988
|
-
const weekNo = Math.ceil(
|
|
989
|
-
((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7
|
|
990
|
-
);
|
|
991
|
-
return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
|
|
992
|
-
}
|
|
993
|
-
function dayChanged(tz = "UTC") {
|
|
994
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}`);
|
|
995
|
-
}
|
|
996
|
-
function hourChanged(tz = "UTC") {
|
|
997
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}-${p.hour}`);
|
|
998
|
-
}
|
|
999
|
-
function monthChanged(tz = "UTC") {
|
|
1000
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}`);
|
|
1001
|
-
}
|
|
1002
|
-
function yearChanged(tz = "UTC") {
|
|
1003
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => p.year);
|
|
1004
|
-
}
|
|
1005
|
-
function seasonChanged(tz = "UTC") {
|
|
1006
|
-
return (ctx) => temporalChanged(ctx, tz, (p) => getSeason(parseInt(p.month) - 1));
|
|
1007
|
-
}
|
|
1008
|
-
function weekChanged(tz = "UTC") {
|
|
1009
|
-
return (ctx) => temporalChanged(ctx, tz, isoWeekKey);
|
|
1010
|
-
}
|
|
1011
|
-
function isConditionalReminder(fragment2) {
|
|
1012
|
-
return fragment2.name === "reminder" && !!fragment2.metadata?.reminder;
|
|
1013
|
-
}
|
|
1014
|
-
function getConditionalReminder(fragment2) {
|
|
1015
|
-
return fragment2.metadata.reminder;
|
|
1016
|
-
}
|
|
1017
|
-
var SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
|
|
1018
|
-
var SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
|
|
1019
|
-
function getReminderRanges(metadata) {
|
|
1020
|
-
return metadata?.reminders ?? [];
|
|
1021
|
-
}
|
|
1022
|
-
function stripTextByRanges(text, ranges) {
|
|
1023
|
-
if (ranges.length === 0) {
|
|
1024
|
-
return text;
|
|
889
|
+
// packages/context/src/lib/renderers/abstract.renderer.ts
|
|
890
|
+
import pluralize from "pluralize";
|
|
891
|
+
import { titlecase } from "stringcase";
|
|
892
|
+
var ContextRenderer = class {
|
|
893
|
+
options;
|
|
894
|
+
constructor(options = {}) {
|
|
895
|
+
this.options = options;
|
|
1025
896
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
return text;
|
|
897
|
+
/**
|
|
898
|
+
* Check if data is a primitive (string, number, boolean).
|
|
899
|
+
*/
|
|
900
|
+
isPrimitive(data) {
|
|
901
|
+
return typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
1032
902
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
903
|
+
/**
|
|
904
|
+
* Group fragments by name for groupFragments option.
|
|
905
|
+
*/
|
|
906
|
+
groupByName(fragments) {
|
|
907
|
+
const groups = /* @__PURE__ */ new Map();
|
|
908
|
+
for (const fragment2 of fragments) {
|
|
909
|
+
const existing = groups.get(fragment2.name) ?? [];
|
|
910
|
+
existing.push(fragment2);
|
|
911
|
+
groups.set(fragment2.name, existing);
|
|
912
|
+
}
|
|
913
|
+
return groups;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Remove null/undefined from fragments and fragment data recursively.
|
|
917
|
+
* This protects renderers from nullish values and ensures they are ignored
|
|
918
|
+
* consistently across all output formats.
|
|
919
|
+
*/
|
|
920
|
+
sanitizeFragments(fragments) {
|
|
921
|
+
const sanitized = [];
|
|
922
|
+
for (const fragment2 of fragments) {
|
|
923
|
+
const cleaned = this.sanitizeFragment(fragment2, /* @__PURE__ */ new WeakSet());
|
|
924
|
+
if (cleaned) {
|
|
925
|
+
sanitized.push(cleaned);
|
|
1039
926
|
}
|
|
1040
|
-
continue;
|
|
1041
927
|
}
|
|
1042
|
-
|
|
1043
|
-
cursor = range.end;
|
|
928
|
+
return sanitized;
|
|
1044
929
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
const partRanges = rangesByPartIndex.get(range.partIndex) ?? [];
|
|
1055
|
-
partRanges.push({ start: range.start, end: range.end });
|
|
1056
|
-
rangesByPartIndex.set(range.partIndex, partRanges);
|
|
930
|
+
sanitizeFragment(fragment2, seen) {
|
|
931
|
+
const data = this.sanitizeData(getFragmentData(fragment2), seen);
|
|
932
|
+
if (data == null) {
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
return {
|
|
936
|
+
...fragment2,
|
|
937
|
+
data
|
|
938
|
+
};
|
|
1057
939
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
if (clonedPart.type !== "text" || ranges === void 0) {
|
|
1062
|
-
return [clonedPart];
|
|
940
|
+
sanitizeData(data, seen) {
|
|
941
|
+
if (data == null) {
|
|
942
|
+
return void 0;
|
|
1063
943
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
return [];
|
|
944
|
+
if (isFragment(data)) {
|
|
945
|
+
return this.sanitizeFragment(data, seen) ?? void 0;
|
|
1067
946
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
947
|
+
if (Array.isArray(data)) {
|
|
948
|
+
if (seen.has(data)) {
|
|
949
|
+
return void 0;
|
|
950
|
+
}
|
|
951
|
+
seen.add(data);
|
|
952
|
+
const cleaned = [];
|
|
953
|
+
for (const item of data) {
|
|
954
|
+
const sanitizedItem = this.sanitizeData(item, seen);
|
|
955
|
+
if (sanitizedItem != null) {
|
|
956
|
+
cleaned.push(sanitizedItem);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
return cleaned;
|
|
960
|
+
}
|
|
961
|
+
if (isFragmentObject(data)) {
|
|
962
|
+
if (seen.has(data)) {
|
|
963
|
+
return void 0;
|
|
964
|
+
}
|
|
965
|
+
seen.add(data);
|
|
966
|
+
const cleaned = {};
|
|
967
|
+
for (const [key, value] of Object.entries(data)) {
|
|
968
|
+
const sanitizedValue = this.sanitizeData(value, seen);
|
|
969
|
+
if (sanitizedValue != null) {
|
|
970
|
+
cleaned[key] = sanitizedValue;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return cleaned;
|
|
1081
974
|
}
|
|
1082
|
-
|
|
1083
|
-
return nextMessage;
|
|
1084
|
-
}
|
|
1085
|
-
function isRecord(value) {
|
|
1086
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1087
|
-
}
|
|
1088
|
-
function assertReminderText(text) {
|
|
1089
|
-
if (text.trim().length === 0) {
|
|
1090
|
-
throw new Error("Reminder text must not be empty");
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
function formatTaggedReminder(text) {
|
|
1094
|
-
return `${SYSTEM_REMINDER_OPEN_TAG}${text}${SYSTEM_REMINDER_CLOSE_TAG}`;
|
|
1095
|
-
}
|
|
1096
|
-
function findLastTextPartIndex(message2) {
|
|
1097
|
-
for (let i = message2.parts.length - 1; i >= 0; i--) {
|
|
1098
|
-
if (message2.parts[i].type === "text") {
|
|
1099
|
-
return i;
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
return void 0;
|
|
1103
|
-
}
|
|
1104
|
-
function ensureTextPart(message2) {
|
|
1105
|
-
const existingIndex = findLastTextPartIndex(message2);
|
|
1106
|
-
if (existingIndex !== void 0) {
|
|
1107
|
-
return existingIndex;
|
|
1108
|
-
}
|
|
1109
|
-
const reminderPart = {
|
|
1110
|
-
type: "text",
|
|
1111
|
-
text: ""
|
|
1112
|
-
};
|
|
1113
|
-
message2.parts.push(reminderPart);
|
|
1114
|
-
return message2.parts.length - 1;
|
|
1115
|
-
}
|
|
1116
|
-
function applyInlineReminder(message2, value) {
|
|
1117
|
-
const partIndex = ensureTextPart(message2);
|
|
1118
|
-
const textPart = message2.parts[partIndex];
|
|
1119
|
-
if (textPart.type !== "text") {
|
|
1120
|
-
throw new Error("Failed to resolve text part for inline reminder");
|
|
1121
|
-
}
|
|
1122
|
-
const reminderText = formatTaggedReminder(value);
|
|
1123
|
-
const start = textPart.text.length;
|
|
1124
|
-
const updatedText = `${textPart.text}${reminderText}`;
|
|
1125
|
-
message2.parts[partIndex] = { ...textPart, text: updatedText };
|
|
1126
|
-
return {
|
|
1127
|
-
id: generateId2(),
|
|
1128
|
-
text: value,
|
|
1129
|
-
partIndex,
|
|
1130
|
-
start,
|
|
1131
|
-
end: start + reminderText.length,
|
|
1132
|
-
mode: "inline"
|
|
1133
|
-
};
|
|
1134
|
-
}
|
|
1135
|
-
function applyPartReminder(message2, value) {
|
|
1136
|
-
const part = { type: "text", text: value };
|
|
1137
|
-
message2.parts.push(part);
|
|
1138
|
-
const partIndex = message2.parts.length - 1;
|
|
1139
|
-
return {
|
|
1140
|
-
id: generateId2(),
|
|
1141
|
-
text: value,
|
|
1142
|
-
partIndex,
|
|
1143
|
-
start: 0,
|
|
1144
|
-
end: value.length,
|
|
1145
|
-
mode: "part"
|
|
1146
|
-
};
|
|
1147
|
-
}
|
|
1148
|
-
function resolveReminderText(item, ctx) {
|
|
1149
|
-
return resolveReminder(item, ctx)?.text ?? "";
|
|
1150
|
-
}
|
|
1151
|
-
function normalizeReminderResolution(value) {
|
|
1152
|
-
if (typeof value === "string") {
|
|
1153
|
-
return value.trim().length === 0 ? null : { text: value };
|
|
1154
|
-
}
|
|
1155
|
-
if (value.text.trim().length === 0) {
|
|
1156
|
-
return null;
|
|
1157
|
-
}
|
|
1158
|
-
return value;
|
|
1159
|
-
}
|
|
1160
|
-
function resolveReminder(item, ctx) {
|
|
1161
|
-
const resolvedText = typeof item.text === "function" ? item.text(ctx) : item.text;
|
|
1162
|
-
const resolved = normalizeReminderResolution(resolvedText);
|
|
1163
|
-
if (!resolved) {
|
|
1164
|
-
return null;
|
|
1165
|
-
}
|
|
1166
|
-
const metadata = item.metadata || resolved.metadata ? {
|
|
1167
|
-
...item.metadata ?? {},
|
|
1168
|
-
...resolved.metadata ?? {}
|
|
1169
|
-
} : void 0;
|
|
1170
|
-
return metadata ? { ...resolved, metadata } : resolved;
|
|
1171
|
-
}
|
|
1172
|
-
function mergeMessageMetadata(message2, addedMetadata) {
|
|
1173
|
-
if (Object.keys(addedMetadata).length === 0) {
|
|
1174
|
-
return;
|
|
1175
|
-
}
|
|
1176
|
-
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
1177
|
-
message2.metadata = { ...metadata, ...addedMetadata };
|
|
1178
|
-
}
|
|
1179
|
-
function applyReminderToMessage(message2, item, ctx) {
|
|
1180
|
-
const resolved = resolveReminder(item, ctx);
|
|
1181
|
-
if (!resolved) {
|
|
1182
|
-
return null;
|
|
1183
|
-
}
|
|
1184
|
-
if (resolved.metadata) {
|
|
1185
|
-
mergeMessageMetadata(message2, resolved.metadata);
|
|
1186
|
-
}
|
|
1187
|
-
return item.asPart ? applyPartReminder(message2, resolved.text) : applyInlineReminder(message2, resolved.text);
|
|
1188
|
-
}
|
|
1189
|
-
function mergeReminderMetadata(message2, addedReminders) {
|
|
1190
|
-
if (addedReminders.length === 0) return;
|
|
1191
|
-
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
1192
|
-
const existing = Array.isArray(metadata.reminders) ? metadata.reminders : [];
|
|
1193
|
-
metadata.reminders = [...existing, ...addedReminders];
|
|
1194
|
-
message2.metadata = metadata;
|
|
1195
|
-
}
|
|
1196
|
-
function reminder(text, options) {
|
|
1197
|
-
if (typeof text === "string") {
|
|
1198
|
-
assertReminderText(text);
|
|
1199
|
-
}
|
|
1200
|
-
if (options && "when" in options && options.when) {
|
|
1201
|
-
return {
|
|
1202
|
-
name: "reminder",
|
|
1203
|
-
metadata: {
|
|
1204
|
-
reminder: {
|
|
1205
|
-
text,
|
|
1206
|
-
when: options.when,
|
|
1207
|
-
asPart: options.asPart ?? false
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
return {
|
|
1213
|
-
text,
|
|
1214
|
-
asPart: options?.asPart ?? false
|
|
1215
|
-
};
|
|
1216
|
-
}
|
|
1217
|
-
function user(content, ...reminders) {
|
|
1218
|
-
const message2 = typeof content === "string" ? {
|
|
1219
|
-
id: generateId2(),
|
|
1220
|
-
role: "user",
|
|
1221
|
-
parts: [{ type: "text", text: content }]
|
|
1222
|
-
} : { ...content, role: "user", parts: [...content.parts] };
|
|
1223
|
-
if (reminders.length > 0) {
|
|
1224
|
-
const plainText = extractPlainText(message2);
|
|
1225
|
-
const added = [];
|
|
1226
|
-
for (const item of reminders) {
|
|
1227
|
-
const meta = applyReminderToMessage(message2, item, {
|
|
1228
|
-
content: plainText
|
|
1229
|
-
});
|
|
1230
|
-
if (meta) added.push(meta);
|
|
1231
|
-
}
|
|
1232
|
-
mergeReminderMetadata(message2, added);
|
|
1233
|
-
}
|
|
1234
|
-
return {
|
|
1235
|
-
id: message2.id,
|
|
1236
|
-
name: "user",
|
|
1237
|
-
type: "message",
|
|
1238
|
-
persist: true,
|
|
1239
|
-
codec: {
|
|
1240
|
-
decode() {
|
|
1241
|
-
return message2;
|
|
1242
|
-
},
|
|
1243
|
-
encode() {
|
|
1244
|
-
return message2;
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
};
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
// packages/context/src/lib/guardrail.ts
|
|
1251
|
-
function pass(part) {
|
|
1252
|
-
return { type: "pass", part };
|
|
1253
|
-
}
|
|
1254
|
-
function fail(feedback) {
|
|
1255
|
-
return { type: "fail", feedback };
|
|
1256
|
-
}
|
|
1257
|
-
function stop(part) {
|
|
1258
|
-
return { type: "stop", part };
|
|
1259
|
-
}
|
|
1260
|
-
function runGuardrailChain(part, guardrails, context) {
|
|
1261
|
-
let currentPart = part;
|
|
1262
|
-
for (const guardrail2 of guardrails) {
|
|
1263
|
-
const result = guardrail2.handle(currentPart, context);
|
|
1264
|
-
if (result.type === "fail" || result.type === "stop") {
|
|
1265
|
-
return result;
|
|
1266
|
-
}
|
|
1267
|
-
currentPart = result.part;
|
|
1268
|
-
}
|
|
1269
|
-
return pass(currentPart);
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
// packages/context/src/lib/renderers/abstract.renderer.ts
|
|
1273
|
-
import pluralize from "pluralize";
|
|
1274
|
-
import { titlecase } from "stringcase";
|
|
1275
|
-
var ContextRenderer = class {
|
|
1276
|
-
options;
|
|
1277
|
-
constructor(options = {}) {
|
|
1278
|
-
this.options = options;
|
|
1279
|
-
}
|
|
1280
|
-
/**
|
|
1281
|
-
* Check if data is a primitive (string, number, boolean).
|
|
1282
|
-
*/
|
|
1283
|
-
isPrimitive(data) {
|
|
1284
|
-
return typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
1285
|
-
}
|
|
1286
|
-
/**
|
|
1287
|
-
* Group fragments by name for groupFragments option.
|
|
1288
|
-
*/
|
|
1289
|
-
groupByName(fragments) {
|
|
1290
|
-
const groups = /* @__PURE__ */ new Map();
|
|
1291
|
-
for (const fragment2 of fragments) {
|
|
1292
|
-
const existing = groups.get(fragment2.name) ?? [];
|
|
1293
|
-
existing.push(fragment2);
|
|
1294
|
-
groups.set(fragment2.name, existing);
|
|
1295
|
-
}
|
|
1296
|
-
return groups;
|
|
1297
|
-
}
|
|
1298
|
-
/**
|
|
1299
|
-
* Remove null/undefined from fragments and fragment data recursively.
|
|
1300
|
-
* This protects renderers from nullish values and ensures they are ignored
|
|
1301
|
-
* consistently across all output formats.
|
|
1302
|
-
*/
|
|
1303
|
-
sanitizeFragments(fragments) {
|
|
1304
|
-
const sanitized = [];
|
|
1305
|
-
for (const fragment2 of fragments) {
|
|
1306
|
-
const cleaned = this.sanitizeFragment(fragment2, /* @__PURE__ */ new WeakSet());
|
|
1307
|
-
if (cleaned) {
|
|
1308
|
-
sanitized.push(cleaned);
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
return sanitized;
|
|
1312
|
-
}
|
|
1313
|
-
sanitizeFragment(fragment2, seen) {
|
|
1314
|
-
const data = this.sanitizeData(getFragmentData(fragment2), seen);
|
|
1315
|
-
if (data == null) {
|
|
1316
|
-
return null;
|
|
1317
|
-
}
|
|
1318
|
-
return {
|
|
1319
|
-
...fragment2,
|
|
1320
|
-
data
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
|
-
sanitizeData(data, seen) {
|
|
1324
|
-
if (data == null) {
|
|
1325
|
-
return void 0;
|
|
1326
|
-
}
|
|
1327
|
-
if (isFragment(data)) {
|
|
1328
|
-
return this.sanitizeFragment(data, seen) ?? void 0;
|
|
1329
|
-
}
|
|
1330
|
-
if (Array.isArray(data)) {
|
|
1331
|
-
if (seen.has(data)) {
|
|
1332
|
-
return void 0;
|
|
1333
|
-
}
|
|
1334
|
-
seen.add(data);
|
|
1335
|
-
const cleaned = [];
|
|
1336
|
-
for (const item of data) {
|
|
1337
|
-
const sanitizedItem = this.sanitizeData(item, seen);
|
|
1338
|
-
if (sanitizedItem != null) {
|
|
1339
|
-
cleaned.push(sanitizedItem);
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
|
-
return cleaned;
|
|
1343
|
-
}
|
|
1344
|
-
if (isFragmentObject(data)) {
|
|
1345
|
-
if (seen.has(data)) {
|
|
1346
|
-
return void 0;
|
|
1347
|
-
}
|
|
1348
|
-
seen.add(data);
|
|
1349
|
-
const cleaned = {};
|
|
1350
|
-
for (const [key, value] of Object.entries(data)) {
|
|
1351
|
-
const sanitizedValue = this.sanitizeData(value, seen);
|
|
1352
|
-
if (sanitizedValue != null) {
|
|
1353
|
-
cleaned[key] = sanitizedValue;
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
return cleaned;
|
|
1357
|
-
}
|
|
1358
|
-
return data;
|
|
975
|
+
return data;
|
|
1359
976
|
}
|
|
1360
977
|
/**
|
|
1361
978
|
* Template method - dispatches value to appropriate handler.
|
|
@@ -2076,74 +1693,460 @@ ${nested}`);
|
|
|
2076
1693
|
if (this.isPrimitive(data)) {
|
|
2077
1694
|
return `${this.#pad(ctx.depth)}${fragment2.name}: ${this.#formatValue(data)}`;
|
|
2078
1695
|
}
|
|
2079
|
-
if (isFragment(data)) {
|
|
2080
|
-
const child = this.renderFragment(data, {
|
|
2081
|
-
...ctx,
|
|
2082
|
-
depth: ctx.depth + 1
|
|
2083
|
-
});
|
|
2084
|
-
return `${this.#pad(ctx.depth)}${fragment2.name}:
|
|
2085
|
-
${child}`;
|
|
1696
|
+
if (isFragment(data)) {
|
|
1697
|
+
const child = this.renderFragment(data, {
|
|
1698
|
+
...ctx,
|
|
1699
|
+
depth: ctx.depth + 1
|
|
1700
|
+
});
|
|
1701
|
+
return `${this.#pad(ctx.depth)}${fragment2.name}:
|
|
1702
|
+
${child}`;
|
|
1703
|
+
}
|
|
1704
|
+
if (Array.isArray(data)) {
|
|
1705
|
+
return this.#renderArrayField(fragment2.name, data, ctx.depth);
|
|
1706
|
+
}
|
|
1707
|
+
if (isFragmentObject(data)) {
|
|
1708
|
+
const entries = this.#renderObjectEntries(data, ctx.depth + 1);
|
|
1709
|
+
if (!entries) {
|
|
1710
|
+
return `${this.#pad(ctx.depth)}${fragment2.name}:`;
|
|
1711
|
+
}
|
|
1712
|
+
return `${this.#pad(ctx.depth)}${fragment2.name}:
|
|
1713
|
+
${entries}`;
|
|
1714
|
+
}
|
|
1715
|
+
return `${this.#pad(ctx.depth)}${fragment2.name}:`;
|
|
1716
|
+
}
|
|
1717
|
+
renderPrimitive(key, value, ctx) {
|
|
1718
|
+
return `${this.#pad(ctx.depth)}${key}: ${this.#formatValue(value)}`;
|
|
1719
|
+
}
|
|
1720
|
+
renderArray(key, items, ctx) {
|
|
1721
|
+
return this.#renderArrayField(key, items, ctx.depth);
|
|
1722
|
+
}
|
|
1723
|
+
renderObject(key, obj, ctx) {
|
|
1724
|
+
const entries = this.#renderObjectEntries(obj, ctx.depth + 1);
|
|
1725
|
+
if (!entries) {
|
|
1726
|
+
return `${this.#pad(ctx.depth)}${key}:`;
|
|
1727
|
+
}
|
|
1728
|
+
return `${this.#pad(ctx.depth)}${key}:
|
|
1729
|
+
${entries}`;
|
|
1730
|
+
}
|
|
1731
|
+
#pad(depth) {
|
|
1732
|
+
return " ".repeat(depth);
|
|
1733
|
+
}
|
|
1734
|
+
#needsQuoting(value) {
|
|
1735
|
+
if (value === "") return true;
|
|
1736
|
+
if (value !== value.trim()) return true;
|
|
1737
|
+
if (["true", "false", "null"].includes(value.toLowerCase())) return true;
|
|
1738
|
+
if (/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(value)) return true;
|
|
1739
|
+
if (/[:\\"'[\]{}|,\t\n\r]/.test(value)) return true;
|
|
1740
|
+
if (value.startsWith("-")) return true;
|
|
1741
|
+
return false;
|
|
1742
|
+
}
|
|
1743
|
+
#escape(value) {
|
|
1744
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
1745
|
+
}
|
|
1746
|
+
#canonicalizeNumber(n) {
|
|
1747
|
+
if (!Number.isFinite(n)) return "null";
|
|
1748
|
+
if (Object.is(n, -0)) return "0";
|
|
1749
|
+
return String(n);
|
|
1750
|
+
}
|
|
1751
|
+
#formatValue(value) {
|
|
1752
|
+
if (value === null) return "null";
|
|
1753
|
+
if (typeof value === "boolean") return String(value);
|
|
1754
|
+
if (typeof value === "number") return this.#canonicalizeNumber(value);
|
|
1755
|
+
if (typeof value === "string") {
|
|
1756
|
+
if (this.#needsQuoting(value)) {
|
|
1757
|
+
return `"${this.#escape(value)}"`;
|
|
1758
|
+
}
|
|
1759
|
+
return value;
|
|
1760
|
+
}
|
|
1761
|
+
return `"${this.#escape(JSON.stringify(value))}"`;
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
|
|
1765
|
+
// packages/context/src/lib/text.ts
|
|
1766
|
+
import { isTextUIPart } from "ai";
|
|
1767
|
+
function getTextParts(message2) {
|
|
1768
|
+
return message2.parts.filter(isTextUIPart).map((part) => part.text);
|
|
1769
|
+
}
|
|
1770
|
+
function extractPlainText(message2) {
|
|
1771
|
+
return getTextParts(message2).join(" ");
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
// packages/context/src/lib/fragments/message/user.ts
|
|
1775
|
+
function everyNTurns(n) {
|
|
1776
|
+
return ({ turn }) => turn % n === 0;
|
|
1777
|
+
}
|
|
1778
|
+
function once() {
|
|
1779
|
+
return ({ turn }) => turn === 1;
|
|
1780
|
+
}
|
|
1781
|
+
function firstN(n) {
|
|
1782
|
+
return ({ turn }) => turn <= n;
|
|
1783
|
+
}
|
|
1784
|
+
function afterTurn(n) {
|
|
1785
|
+
return ({ turn }) => turn > n;
|
|
1786
|
+
}
|
|
1787
|
+
function and(...predicates) {
|
|
1788
|
+
return async (ctx) => {
|
|
1789
|
+
for (const it of predicates) {
|
|
1790
|
+
if (!await it(ctx)) return false;
|
|
1791
|
+
}
|
|
1792
|
+
return true;
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
function or(...predicates) {
|
|
1796
|
+
return async (ctx) => {
|
|
1797
|
+
for (const it of predicates) {
|
|
1798
|
+
if (await it(ctx)) return true;
|
|
1799
|
+
}
|
|
1800
|
+
return false;
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
function not(predicate) {
|
|
1804
|
+
return async (ctx) => !await predicate(ctx);
|
|
1805
|
+
}
|
|
1806
|
+
function contentIncludes(keywords) {
|
|
1807
|
+
const lower = keywords.map((k) => k.toLowerCase());
|
|
1808
|
+
return (ctx) => {
|
|
1809
|
+
const text = ctx.content.toLowerCase();
|
|
1810
|
+
return lower.some((kw) => text.includes(kw));
|
|
1811
|
+
};
|
|
1812
|
+
}
|
|
1813
|
+
function contentPattern(pattern) {
|
|
1814
|
+
return (ctx) => {
|
|
1815
|
+
pattern.lastIndex = 0;
|
|
1816
|
+
return pattern.test(ctx.content);
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
function toDateParts(date, tz) {
|
|
1820
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
1821
|
+
timeZone: tz,
|
|
1822
|
+
year: "numeric",
|
|
1823
|
+
month: "2-digit",
|
|
1824
|
+
day: "2-digit",
|
|
1825
|
+
hour: "2-digit",
|
|
1826
|
+
hourCycle: "h23"
|
|
1827
|
+
}).formatToParts(date);
|
|
1828
|
+
const get = (type) => parts.find((p) => p.type === type).value;
|
|
1829
|
+
return {
|
|
1830
|
+
year: get("year"),
|
|
1831
|
+
month: get("month"),
|
|
1832
|
+
day: get("day"),
|
|
1833
|
+
hour: get("hour")
|
|
1834
|
+
};
|
|
1835
|
+
}
|
|
1836
|
+
function temporalChanged(ctx, tz, getKey) {
|
|
1837
|
+
if (ctx.lastMessageAt === void 0) return true;
|
|
1838
|
+
const nowParts = toDateParts(/* @__PURE__ */ new Date(), tz);
|
|
1839
|
+
const prevParts = toDateParts(new Date(ctx.lastMessageAt), tz);
|
|
1840
|
+
return getKey(nowParts) !== getKey(prevParts);
|
|
1841
|
+
}
|
|
1842
|
+
function getSeason(month) {
|
|
1843
|
+
if (month >= 2 && month <= 4) return "Spring";
|
|
1844
|
+
if (month >= 5 && month <= 7) return "Summer";
|
|
1845
|
+
if (month >= 8 && month <= 10) return "Fall";
|
|
1846
|
+
return "Winter";
|
|
1847
|
+
}
|
|
1848
|
+
function isoWeekKey(parts) {
|
|
1849
|
+
const d = new Date(
|
|
1850
|
+
Date.UTC(
|
|
1851
|
+
parseInt(parts.year),
|
|
1852
|
+
parseInt(parts.month) - 1,
|
|
1853
|
+
parseInt(parts.day)
|
|
1854
|
+
)
|
|
1855
|
+
);
|
|
1856
|
+
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
|
|
1857
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
1858
|
+
const weekNo = Math.ceil(
|
|
1859
|
+
((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7
|
|
1860
|
+
);
|
|
1861
|
+
return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
|
|
1862
|
+
}
|
|
1863
|
+
function dayChanged(tz = "UTC") {
|
|
1864
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}`);
|
|
1865
|
+
}
|
|
1866
|
+
function hourChanged(tz = "UTC") {
|
|
1867
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}-${p.day}-${p.hour}`);
|
|
1868
|
+
}
|
|
1869
|
+
function monthChanged(tz = "UTC") {
|
|
1870
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => `${p.year}-${p.month}`);
|
|
1871
|
+
}
|
|
1872
|
+
function yearChanged(tz = "UTC") {
|
|
1873
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => p.year);
|
|
1874
|
+
}
|
|
1875
|
+
function seasonChanged(tz = "UTC") {
|
|
1876
|
+
return (ctx) => temporalChanged(ctx, tz, (p) => getSeason(parseInt(p.month) - 1));
|
|
1877
|
+
}
|
|
1878
|
+
function weekChanged(tz = "UTC") {
|
|
1879
|
+
return (ctx) => temporalChanged(ctx, tz, isoWeekKey);
|
|
1880
|
+
}
|
|
1881
|
+
function isConditionalReminder(fragment2) {
|
|
1882
|
+
return fragment2.name === "reminder" && !!fragment2.metadata?.reminder;
|
|
1883
|
+
}
|
|
1884
|
+
function getConditionalReminder(fragment2) {
|
|
1885
|
+
return fragment2.metadata.reminder;
|
|
1886
|
+
}
|
|
1887
|
+
var SYSTEM_REMINDER_OPEN_TAG = "<system-reminder>";
|
|
1888
|
+
var SYSTEM_REMINDER_CLOSE_TAG = "</system-reminder>";
|
|
1889
|
+
function getReminderRanges(metadata) {
|
|
1890
|
+
return metadata?.reminders ?? [];
|
|
1891
|
+
}
|
|
1892
|
+
function stripTextByRanges(text, ranges) {
|
|
1893
|
+
if (ranges.length === 0) {
|
|
1894
|
+
return text;
|
|
1895
|
+
}
|
|
1896
|
+
const normalized = ranges.map((range) => ({
|
|
1897
|
+
start: Math.max(0, Math.min(text.length, range.start)),
|
|
1898
|
+
end: Math.max(0, Math.min(text.length, range.end))
|
|
1899
|
+
})).filter((range) => range.end > range.start).sort((a, b) => a.start - b.start);
|
|
1900
|
+
if (normalized.length === 0) {
|
|
1901
|
+
return text;
|
|
1902
|
+
}
|
|
1903
|
+
let cursor = 0;
|
|
1904
|
+
let output = "";
|
|
1905
|
+
for (const range of normalized) {
|
|
1906
|
+
if (range.start < cursor) {
|
|
1907
|
+
if (range.end > cursor) {
|
|
1908
|
+
cursor = range.end;
|
|
1909
|
+
}
|
|
1910
|
+
continue;
|
|
1911
|
+
}
|
|
1912
|
+
output += text.slice(cursor, range.start);
|
|
1913
|
+
cursor = range.end;
|
|
1914
|
+
}
|
|
1915
|
+
output += text.slice(cursor);
|
|
1916
|
+
return output.trimEnd();
|
|
1917
|
+
}
|
|
1918
|
+
function stripReminders(message2) {
|
|
1919
|
+
const reminderRanges = getReminderRanges(
|
|
1920
|
+
isRecord(message2.metadata) ? message2.metadata : void 0
|
|
1921
|
+
);
|
|
1922
|
+
const rangesByPartIndex = /* @__PURE__ */ new Map();
|
|
1923
|
+
for (const range of reminderRanges) {
|
|
1924
|
+
const partRanges = rangesByPartIndex.get(range.partIndex) ?? [];
|
|
1925
|
+
partRanges.push({ start: range.start, end: range.end });
|
|
1926
|
+
rangesByPartIndex.set(range.partIndex, partRanges);
|
|
1927
|
+
}
|
|
1928
|
+
const strippedParts = message2.parts.flatMap((part, partIndex) => {
|
|
1929
|
+
const clonedPart = { ...part };
|
|
1930
|
+
const ranges = rangesByPartIndex.get(partIndex);
|
|
1931
|
+
if (clonedPart.type !== "text" || ranges === void 0) {
|
|
1932
|
+
return [clonedPart];
|
|
1933
|
+
}
|
|
1934
|
+
const strippedText = stripTextByRanges(clonedPart.text, ranges);
|
|
1935
|
+
if (strippedText.length === 0) {
|
|
1936
|
+
return [];
|
|
2086
1937
|
}
|
|
2087
|
-
|
|
2088
|
-
|
|
1938
|
+
return [{ ...clonedPart, text: strippedText }];
|
|
1939
|
+
});
|
|
1940
|
+
const nextMessage = {
|
|
1941
|
+
...message2,
|
|
1942
|
+
parts: strippedParts
|
|
1943
|
+
};
|
|
1944
|
+
if (isRecord(message2.metadata)) {
|
|
1945
|
+
const metadata = { ...message2.metadata };
|
|
1946
|
+
delete metadata.reminders;
|
|
1947
|
+
if (Object.keys(metadata).length > 0) {
|
|
1948
|
+
nextMessage.metadata = metadata;
|
|
1949
|
+
} else {
|
|
1950
|
+
delete nextMessage.metadata;
|
|
2089
1951
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
1952
|
+
}
|
|
1953
|
+
return nextMessage;
|
|
1954
|
+
}
|
|
1955
|
+
function isRecord(value) {
|
|
1956
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1957
|
+
}
|
|
1958
|
+
function assertReminderText(text) {
|
|
1959
|
+
if (text.trim().length === 0) {
|
|
1960
|
+
throw new Error("Reminder text must not be empty");
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
function formatTaggedReminder(text) {
|
|
1964
|
+
return `${SYSTEM_REMINDER_OPEN_TAG}${text}${SYSTEM_REMINDER_CLOSE_TAG}`;
|
|
1965
|
+
}
|
|
1966
|
+
function findLastTextPartIndex(message2) {
|
|
1967
|
+
for (let i = message2.parts.length - 1; i >= 0; i--) {
|
|
1968
|
+
if (message2.parts[i].type === "text") {
|
|
1969
|
+
return i;
|
|
2097
1970
|
}
|
|
2098
|
-
return `${this.#pad(ctx.depth)}${fragment2.name}:`;
|
|
2099
1971
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
1972
|
+
return void 0;
|
|
1973
|
+
}
|
|
1974
|
+
function ensureTextPart(message2) {
|
|
1975
|
+
const existingIndex = findLastTextPartIndex(message2);
|
|
1976
|
+
if (existingIndex !== void 0) {
|
|
1977
|
+
return existingIndex;
|
|
2102
1978
|
}
|
|
2103
|
-
|
|
2104
|
-
|
|
1979
|
+
const reminderPart = {
|
|
1980
|
+
type: "text",
|
|
1981
|
+
text: ""
|
|
1982
|
+
};
|
|
1983
|
+
message2.parts.push(reminderPart);
|
|
1984
|
+
return message2.parts.length - 1;
|
|
1985
|
+
}
|
|
1986
|
+
function applyInlineReminder(message2, value) {
|
|
1987
|
+
const partIndex = ensureTextPart(message2);
|
|
1988
|
+
const textPart = message2.parts[partIndex];
|
|
1989
|
+
if (textPart.type !== "text") {
|
|
1990
|
+
throw new Error("Failed to resolve text part for inline reminder");
|
|
2105
1991
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
1992
|
+
const reminderText = formatTaggedReminder(value);
|
|
1993
|
+
const start = textPart.text.length;
|
|
1994
|
+
const updatedText = `${textPart.text}${reminderText}`;
|
|
1995
|
+
message2.parts[partIndex] = { ...textPart, text: updatedText };
|
|
1996
|
+
return {
|
|
1997
|
+
id: generateId2(),
|
|
1998
|
+
text: value,
|
|
1999
|
+
partIndex,
|
|
2000
|
+
start,
|
|
2001
|
+
end: start + reminderText.length,
|
|
2002
|
+
mode: "inline"
|
|
2003
|
+
};
|
|
2004
|
+
}
|
|
2005
|
+
function applyPartReminder(message2, value) {
|
|
2006
|
+
const part = { type: "text", text: value };
|
|
2007
|
+
message2.parts.push(part);
|
|
2008
|
+
const partIndex = message2.parts.length - 1;
|
|
2009
|
+
return {
|
|
2010
|
+
id: generateId2(),
|
|
2011
|
+
text: value,
|
|
2012
|
+
partIndex,
|
|
2013
|
+
start: 0,
|
|
2014
|
+
end: value.length,
|
|
2015
|
+
mode: "part"
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
function resolveReminderText(item, ctx) {
|
|
2019
|
+
return resolveReminder(item, ctx)?.text ?? "";
|
|
2020
|
+
}
|
|
2021
|
+
function normalizeReminderResolution(value) {
|
|
2022
|
+
if (typeof value === "string") {
|
|
2023
|
+
return value.trim().length === 0 ? null : { text: value };
|
|
2113
2024
|
}
|
|
2114
|
-
|
|
2115
|
-
return
|
|
2025
|
+
if (value.text.trim().length === 0) {
|
|
2026
|
+
return null;
|
|
2116
2027
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
return false;
|
|
2028
|
+
return value;
|
|
2029
|
+
}
|
|
2030
|
+
function resolveReminder(item, ctx) {
|
|
2031
|
+
const resolvedText = typeof item.text === "function" ? item.text(ctx) : item.text;
|
|
2032
|
+
const resolved = normalizeReminderResolution(resolvedText);
|
|
2033
|
+
if (!resolved) {
|
|
2034
|
+
return null;
|
|
2125
2035
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2036
|
+
const metadata = item.metadata || resolved.metadata ? {
|
|
2037
|
+
...item.metadata ?? {},
|
|
2038
|
+
...resolved.metadata ?? {}
|
|
2039
|
+
} : void 0;
|
|
2040
|
+
return metadata ? { ...resolved, metadata } : resolved;
|
|
2041
|
+
}
|
|
2042
|
+
async function resolveReminderAsync(item, ctx) {
|
|
2043
|
+
const text = await (typeof item.text === "function" ? item.text(ctx) : item.text);
|
|
2044
|
+
const resolved = normalizeReminderResolution(text);
|
|
2045
|
+
if (!resolved) return null;
|
|
2046
|
+
const metadata = item.metadata || resolved.metadata ? { ...item.metadata ?? {}, ...resolved.metadata ?? {} } : void 0;
|
|
2047
|
+
return metadata ? { ...resolved, metadata } : resolved;
|
|
2048
|
+
}
|
|
2049
|
+
function mergeMessageMetadata(message2, addedMetadata) {
|
|
2050
|
+
if (Object.keys(addedMetadata).length === 0) {
|
|
2051
|
+
return;
|
|
2128
2052
|
}
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2053
|
+
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
2054
|
+
message2.metadata = { ...metadata, ...addedMetadata };
|
|
2055
|
+
}
|
|
2056
|
+
function applyReminderToMessage(message2, item, ctx) {
|
|
2057
|
+
const resolved = resolveReminder(item, ctx);
|
|
2058
|
+
if (!resolved) {
|
|
2059
|
+
return null;
|
|
2133
2060
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2061
|
+
if (resolved.metadata) {
|
|
2062
|
+
mergeMessageMetadata(message2, resolved.metadata);
|
|
2063
|
+
}
|
|
2064
|
+
return item.asPart ? applyPartReminder(message2, resolved.text) : applyInlineReminder(message2, resolved.text);
|
|
2065
|
+
}
|
|
2066
|
+
function mergeReminderMetadata(message2, addedReminders) {
|
|
2067
|
+
if (addedReminders.length === 0) return;
|
|
2068
|
+
const metadata = isRecord(message2.metadata) ? { ...message2.metadata } : {};
|
|
2069
|
+
const existing = Array.isArray(metadata.reminders) ? metadata.reminders : [];
|
|
2070
|
+
metadata.reminders = [...existing, ...addedReminders];
|
|
2071
|
+
message2.metadata = metadata;
|
|
2072
|
+
}
|
|
2073
|
+
function reminder(textOrFragment, options) {
|
|
2074
|
+
const text = isFragment(textOrFragment) ? new XmlRenderer().render([textOrFragment]) : textOrFragment;
|
|
2075
|
+
if (typeof text === "string") {
|
|
2076
|
+
assertReminderText(text);
|
|
2077
|
+
}
|
|
2078
|
+
if (options && "when" in options && options.when) {
|
|
2079
|
+
return {
|
|
2080
|
+
name: "reminder",
|
|
2081
|
+
data: null,
|
|
2082
|
+
metadata: {
|
|
2083
|
+
reminder: {
|
|
2084
|
+
text,
|
|
2085
|
+
when: options.when,
|
|
2086
|
+
asPart: options.asPart ?? false
|
|
2087
|
+
}
|
|
2141
2088
|
}
|
|
2142
|
-
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
return {
|
|
2092
|
+
text,
|
|
2093
|
+
asPart: options?.asPart ?? false
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
function user(content, ...reminders) {
|
|
2097
|
+
const message2 = typeof content === "string" ? {
|
|
2098
|
+
id: generateId2(),
|
|
2099
|
+
role: "user",
|
|
2100
|
+
parts: [{ type: "text", text: content }]
|
|
2101
|
+
} : { ...content, role: "user", parts: [...content.parts] };
|
|
2102
|
+
if (reminders.length > 0) {
|
|
2103
|
+
const plainText = extractPlainText(message2);
|
|
2104
|
+
const added = [];
|
|
2105
|
+
for (const item of reminders) {
|
|
2106
|
+
const meta = applyReminderToMessage(message2, item, {
|
|
2107
|
+
content: plainText
|
|
2108
|
+
});
|
|
2109
|
+
if (meta) added.push(meta);
|
|
2143
2110
|
}
|
|
2144
|
-
|
|
2111
|
+
mergeReminderMetadata(message2, added);
|
|
2145
2112
|
}
|
|
2146
|
-
|
|
2113
|
+
return {
|
|
2114
|
+
id: message2.id,
|
|
2115
|
+
name: "user",
|
|
2116
|
+
type: "message",
|
|
2117
|
+
persist: true,
|
|
2118
|
+
codec: {
|
|
2119
|
+
decode() {
|
|
2120
|
+
return message2;
|
|
2121
|
+
},
|
|
2122
|
+
encode() {
|
|
2123
|
+
return message2;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
// packages/context/src/lib/guardrail.ts
|
|
2130
|
+
function pass(part) {
|
|
2131
|
+
return { type: "pass", part };
|
|
2132
|
+
}
|
|
2133
|
+
function fail(feedback) {
|
|
2134
|
+
return { type: "fail", feedback };
|
|
2135
|
+
}
|
|
2136
|
+
function stop(part) {
|
|
2137
|
+
return { type: "stop", part };
|
|
2138
|
+
}
|
|
2139
|
+
function runGuardrailChain(part, guardrails, context) {
|
|
2140
|
+
let currentPart = part;
|
|
2141
|
+
for (const guardrail2 of guardrails) {
|
|
2142
|
+
const result = guardrail2.handle(currentPart, context);
|
|
2143
|
+
if (result.type === "fail" || result.type === "stop") {
|
|
2144
|
+
return result;
|
|
2145
|
+
}
|
|
2146
|
+
currentPart = result.part;
|
|
2147
|
+
}
|
|
2148
|
+
return pass(currentPart);
|
|
2149
|
+
}
|
|
2147
2150
|
|
|
2148
2151
|
// packages/context/src/lib/render.ts
|
|
2149
2152
|
function render(tag, ...fragments) {
|
|
@@ -2302,7 +2305,6 @@ function visualizeGraph(data) {
|
|
|
2302
2305
|
export {
|
|
2303
2306
|
ContextRenderer,
|
|
2304
2307
|
ContextStore,
|
|
2305
|
-
LAZY_ID,
|
|
2306
2308
|
MarkdownRenderer,
|
|
2307
2309
|
ModelsRegistry,
|
|
2308
2310
|
StreamStore,
|
|
@@ -2345,10 +2347,8 @@ export {
|
|
|
2345
2347
|
isConditionalReminder,
|
|
2346
2348
|
isFragment,
|
|
2347
2349
|
isFragmentObject,
|
|
2348
|
-
isLazyFragment,
|
|
2349
2350
|
isMessageFragment,
|
|
2350
2351
|
isRecord,
|
|
2351
|
-
lastAssistantMessage,
|
|
2352
2352
|
mergeMessageMetadata,
|
|
2353
2353
|
mergeReminderMetadata,
|
|
2354
2354
|
message,
|
|
@@ -2366,6 +2366,7 @@ export {
|
|
|
2366
2366
|
reminder,
|
|
2367
2367
|
render,
|
|
2368
2368
|
resolveReminder,
|
|
2369
|
+
resolveReminderAsync,
|
|
2369
2370
|
resolveReminderText,
|
|
2370
2371
|
role,
|
|
2371
2372
|
runGuardrailChain,
|