@triplef/agent 0.1.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/intent.schema-BbIiFHUW.d.ts +100 -0
- package/dist/prompts/index.d.ts +286 -0
- package/dist/prompts/index.mjs +3206 -0
- package/dist/schemas/index.d.ts +895 -0
- package/dist/schemas/index.mjs +1052 -0
- package/dist/tools/index.d.ts +699 -0
- package/dist/tools/index.mjs +1637 -0
- package/package.json +98 -0
|
@@ -0,0 +1,1052 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { merge, omit } from '@triplef/helpers/object-io';
|
|
3
|
+
|
|
4
|
+
// src/schemas/constants/blocked-image-hosts.ts
|
|
5
|
+
var BLOCKED_IMAGE_HOSTS = /* @__PURE__ */ new Set([
|
|
6
|
+
// Google thumbnail proxies (low-res, frequently 404 when hot-linked)
|
|
7
|
+
"encrypted-tbn0.gstatic.com",
|
|
8
|
+
"encrypted-tbn1.gstatic.com",
|
|
9
|
+
"encrypted-tbn2.gstatic.com",
|
|
10
|
+
"encrypted-tbn3.gstatic.com",
|
|
11
|
+
"t0.gstatic.com",
|
|
12
|
+
"t1.gstatic.com",
|
|
13
|
+
"t2.gstatic.com",
|
|
14
|
+
"t3.gstatic.com",
|
|
15
|
+
"t4.gstatic.com",
|
|
16
|
+
"t5.gstatic.com",
|
|
17
|
+
"t6.gstatic.com",
|
|
18
|
+
"t7.gstatic.com",
|
|
19
|
+
"t8.gstatic.com",
|
|
20
|
+
"t9.gstatic.com",
|
|
21
|
+
"t10.gstatic.com",
|
|
22
|
+
"news.gstatic.com",
|
|
23
|
+
"books.gstatic.com",
|
|
24
|
+
"maps.gstatic.com",
|
|
25
|
+
// Google user-content thumbnails
|
|
26
|
+
"lh1.googleusercontent.com",
|
|
27
|
+
"lh2.googleusercontent.com",
|
|
28
|
+
"lh3.googleusercontent.com",
|
|
29
|
+
"lh4.googleusercontent.com",
|
|
30
|
+
"lh5.googleusercontent.com",
|
|
31
|
+
"lh6.googleusercontent.com"
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
// src/schemas/constants/url-trust.constants.ts
|
|
35
|
+
var BLOCKED_URL_HOSTS = /* @__PURE__ */ new Set([
|
|
36
|
+
// Google thumbnail / static asset proxies
|
|
37
|
+
"encrypted-tbn0.gstatic.com",
|
|
38
|
+
"encrypted-tbn1.gstatic.com",
|
|
39
|
+
"encrypted-tbn2.gstatic.com",
|
|
40
|
+
"encrypted-tbn3.gstatic.com",
|
|
41
|
+
"t0.gstatic.com",
|
|
42
|
+
"t1.gstatic.com",
|
|
43
|
+
"t2.gstatic.com",
|
|
44
|
+
"t3.gstatic.com",
|
|
45
|
+
"t4.gstatic.com",
|
|
46
|
+
"t5.gstatic.com",
|
|
47
|
+
"t6.gstatic.com",
|
|
48
|
+
"t7.gstatic.com",
|
|
49
|
+
"t8.gstatic.com",
|
|
50
|
+
"t9.gstatic.com",
|
|
51
|
+
"t10.gstatic.com",
|
|
52
|
+
"news.gstatic.com",
|
|
53
|
+
"books.gstatic.com",
|
|
54
|
+
"maps.gstatic.com",
|
|
55
|
+
"lh1.googleusercontent.com",
|
|
56
|
+
"lh2.googleusercontent.com",
|
|
57
|
+
"lh3.googleusercontent.com",
|
|
58
|
+
"lh4.googleusercontent.com",
|
|
59
|
+
"lh5.googleusercontent.com",
|
|
60
|
+
"lh6.googleusercontent.com"
|
|
61
|
+
]);
|
|
62
|
+
var NON_PAGE_EXTENSIONS = /\.(js|css|json|xml|svg|png|jpg|jpeg|gif|webp|ico|mp4|webm|ogg|mov|mkv|avi|flv|m3u8|mpd|pdf|zip|tar|gz|rar|exe|dmg|pkg|deb|rpm|woff|woff2|ttf|otf|eot)(\?.*)?$/i;
|
|
63
|
+
|
|
64
|
+
// src/schemas/helpers/tools/categorize-tools.helper.ts
|
|
65
|
+
function categorizeTools(toolNames) {
|
|
66
|
+
const cats = {
|
|
67
|
+
imageSearch: [],
|
|
68
|
+
newsSearch: [],
|
|
69
|
+
videoSearch: [],
|
|
70
|
+
pageFetch: [],
|
|
71
|
+
browser: [],
|
|
72
|
+
imageVariants: [],
|
|
73
|
+
specialized: []
|
|
74
|
+
};
|
|
75
|
+
for (const t of toolNames) {
|
|
76
|
+
if (t.startsWith("browser_")) cats.browser.push(t);
|
|
77
|
+
else if (t.endsWith("ImageSearch")) cats.imageSearch.push(t);
|
|
78
|
+
else if (t.endsWith("NewsSearch")) cats.newsSearch.push(t);
|
|
79
|
+
else if (t.endsWith("VideoSearch")) cats.videoSearch.push(t);
|
|
80
|
+
else if (t.includes("Fetch") || t.includes("fetch") || t.includes("Scrape")) cats.pageFetch.push(t);
|
|
81
|
+
else if (t.startsWith("request")) cats.imageVariants.push(t);
|
|
82
|
+
else cats.specialized.push(t);
|
|
83
|
+
}
|
|
84
|
+
return cats;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/schemas/helpers/tools/tool-registry.constants.ts
|
|
88
|
+
var VARIANT_NAMES = ["grayscale", "denoised", "sharpened", "clahe"];
|
|
89
|
+
var TOOL_DESCRIPTIONS = {
|
|
90
|
+
brightDataWebSearch: "Search the web using Bright Data SERP API (Google). Returns organic results with titles, snippets, and links. Supports an optional recency window (day/week/month/year) for fresh results.",
|
|
91
|
+
brightDataImageSearch: "Search for images using Bright Data SERP API (Google Images). Returns image URLs, source pages, and dimensions. Enforces a minimum of 1280\xD7720 (720p).",
|
|
92
|
+
brightDataNewsSearch: "Search latest news using Bright Data SERP API. Returns headlines, sources, dates, and snippets. Supports an optional recency window (day/week/month/year).",
|
|
93
|
+
brightDataPlacesSearch: "Search places and businesses using Bright Data SERP API (Google Maps). Returns addresses, phone numbers, ratings, review counts, and coordinates. Query with a business name or business type plus location.",
|
|
94
|
+
brightDataShoppingSearch: "Search for products using Bright Data SERP API (Google Shopping). Returns prices, sellers, images, and ratings. Query with the bare product name and model number.",
|
|
95
|
+
brightDataVideoSearch: "Search for videos using Bright Data SERP API. Returns titles, links, channel names, duration, and publish dates. Supports an optional recency window (day/week/month/year). Only return URLs from supported embeddable providers: YouTube, Vimeo, Dailymotion, Loom, Wistia, or direct video files. Reject Instagram, Facebook, TikTok, Twitch, X/Twitter, and other unreliable platforms.",
|
|
96
|
+
brightDataWebpageScrape: "Fetch and render a full webpage using Bright Data Web Unlocker API. Returns clean Markdown text. Use for pages behind anti-bot protection that plain fetch cannot reach.",
|
|
97
|
+
serperWebSearch: "Search the web using Serper.dev (Google). Returns organic results with titles, snippets, and links. Supports an optional recency window (day/week/month/year) for fresh results.",
|
|
98
|
+
serperImageSearch: "Search for images using Serper.dev (Google Images). Prefers 2560\xD71440 (1440p) images and enforces a minimum of 1280\xD7720 (720p) via the Google Images tbs size filter and a client-side dimension filter. Supports an optional recency window (day/week/month/year).",
|
|
99
|
+
serperNewsSearch: "Search latest news using Serper.dev. Returns headlines, sources, dates, and snippets. Supports an optional recency window (day/week/month/year).",
|
|
100
|
+
serperPlacesSearch: "Search places and businesses using Serper.dev (Google Maps). Returns addresses, phone numbers, ratings, review counts, and coordinates. Query with a business name or business type plus location.",
|
|
101
|
+
serperShoppingSearch: "Search for products using Serper.dev (Google Shopping). Returns prices, sellers, delivery info, images, and per-offer ratings. Query with the bare product name and model number.",
|
|
102
|
+
serperBusinessReviewsSearch: "Fetch Google Maps reviews for a specific business or place using Serper.dev. Returns reviewer snippets with author names, star ratings, and dates. Use for seller/business reputation, not editorial product reviews.",
|
|
103
|
+
serperVideoSearch: "Search for videos using Serper.dev. Returns titles, links, channel names, duration, and publish dates. Supports an optional recency window (day/week/month/year). Only return URLs from supported embeddable providers: YouTube, Vimeo, Dailymotion, Loom, Wistia, or direct video files. Reject Instagram, Facebook, TikTok, Twitch, X/Twitter, and other unreliable platforms.",
|
|
104
|
+
serperWebpageScrape: "Fetch and render a full webpage using Serper.dev scrape API. Returns clean rendered text with its title.",
|
|
105
|
+
youtubeVideoSearch: "Search YouTube using the official YouTube Data API. Returns titles, links, channel names, durations, view counts, upload dates, and direct thumbnails. All results are embeddable YouTube videos.",
|
|
106
|
+
eodhdSearch: 'Resolve a company, ETF, or index name to an EODHD ticker code (e.g. "Nvidia" \u2192 NVDA.US). Use before fetching quotes, history, technicals, or news for a named entity.',
|
|
107
|
+
eodhdQuote: "Fetch the current (delayed) quote for one or more EODHD tickers \u2014 last price, change, change %, open/high/low, volume, previous close.",
|
|
108
|
+
eodhdHistory: "Fetch end-of-day OHLCV price history for an EODHD ticker. Returns a compact summary plus the full time series as chartData for the client chart. Use for the time-value chart and buy/sell pressure (volume).",
|
|
109
|
+
eodhdTechnical: "Fetch a technical indicator series (RSI, MACD, ADX, SMA, EMA, BBANDS, ATR, \u2026) for an EODHD ticker. Use to gauge buy/sell pressure and momentum.",
|
|
110
|
+
eodhdIntraday: "Fetch intraday OHLCV bars for an EODHD ticker and return a per-day, per-price-band volume profile as chartData for the client heatmap. Use to render a volume heatmap across fixed price bands.",
|
|
111
|
+
eodhdNews: "Fetch recent financial news for an EODHD ticker \u2014 headlines, links, sources, publish dates. Use to ground a stock-market answer in what is happening around a company.",
|
|
112
|
+
eodhdFundamentals: "Fetch company fundamentals for an EODHD ticker \u2014 general info, valuation, and key financial highlights (sector, market cap, P/E, revenue, margins).",
|
|
113
|
+
webFetch: "Fetch the full content of a specific URL. Use only when search snippets are insufficient.",
|
|
114
|
+
browser_navigate: "Control a real browser: navigate to a URL. Use for interactive browsing \u2014 JS-heavy pages, content behind clicks, tabs, scrolling, or forms \u2014 that static search/fetch cannot reach. Follow up with browser_snapshot to read the page before acting on it.",
|
|
115
|
+
browser_navigate_back: "Go back to the previous page in the browser history.",
|
|
116
|
+
browser_snapshot: "Read the current browser page as an accessibility snapshot (structured text with element refs). The primary way to see page content and obtain the refs that browser_click/browser_type need.",
|
|
117
|
+
browser_click: "Click an element in the browser, referenced by a ref from browser_snapshot.",
|
|
118
|
+
browser_type: "Type text into an editable browser element, referenced by a ref from browser_snapshot, optionally submitting with Enter.",
|
|
119
|
+
browser_fill_form: "Fill multiple form fields in the browser in one call.",
|
|
120
|
+
browser_select_option: "Select an option in a dropdown in the browser.",
|
|
121
|
+
browser_press_key: "Press a keyboard key in the browser (Enter, Tab, arrows).",
|
|
122
|
+
browser_wait_for: "Wait for text to appear or disappear, or for a time period, in the browser.",
|
|
123
|
+
browser_take_screenshot: "Take a screenshot of the current browser page or a specific element.",
|
|
124
|
+
browser_tabs: "List, create, close, or switch browser tabs.",
|
|
125
|
+
browser_console_messages: "Get console messages from the browser. Use to diagnose JavaScript errors on a page (e.g. when testing a web app).",
|
|
126
|
+
browser_network_requests: "List network requests the browser made since page load. Use to diagnose failed or slow requests (e.g. when testing a web app).",
|
|
127
|
+
browser_verify_element_visible: "Assert that an element is visible on the current browser page.",
|
|
128
|
+
browser_verify_text_visible: "Assert that text is visible on the current browser page.",
|
|
129
|
+
requestGrayscale: "Request a grayscale version of the images. Use when color noise or color information is irrelevant, for example when reading text or analyzing shapes.",
|
|
130
|
+
requestDenoised: "Request a denoised (blurred) version of the images. Use when the original has noise, grain, or artifacts that hide details.",
|
|
131
|
+
requestSharpened: "Request a sharpened version of the images. Use when edges or fine details are blurry.",
|
|
132
|
+
requestClahe: "Request a CLAHE (contrast-enhanced) version of the images. Use when details are hidden in shadows or highlights.",
|
|
133
|
+
memoryRemember: 'Store into YOUR long-term memory of this user: notable facts about subjects they care about (favorites, interests, projects, followed stocks, people, past topics), preferences and durable details they state, and anything they explicitly ask you to remember. Storing gathered knowledge and noticed preferences is expected \u2014 do not wait for an explicit "remember" instruction.',
|
|
134
|
+
memoryRecall: "Retrieve from YOUR long-term memory of this user \u2014 things they told you in past conversations or asked you to remember. These are trusted user statements, not public facts; attribute them to the user and prefer them over web results for anything personal. Check this tool whenever a request touches a subject this user has cared about before.",
|
|
135
|
+
memoryDelete: "Delete from YOUR long-term memory of this user: one exact fact record quoted verbatim from a memoryRecall result, or \u2014 only when the user asks \u2014 your whole learned cognition profile of them. Never delete on a guess: recall first, delete the verbatim statement. Needs memoryRecall alongside it."
|
|
136
|
+
};
|
|
137
|
+
var BROWSER_TOOL_NAMES = [
|
|
138
|
+
"browser_navigate",
|
|
139
|
+
"browser_navigate_back",
|
|
140
|
+
"browser_snapshot",
|
|
141
|
+
"browser_click",
|
|
142
|
+
"browser_type",
|
|
143
|
+
"browser_fill_form",
|
|
144
|
+
"browser_select_option",
|
|
145
|
+
"browser_press_key",
|
|
146
|
+
"browser_wait_for",
|
|
147
|
+
"browser_take_screenshot",
|
|
148
|
+
"browser_tabs",
|
|
149
|
+
"browser_console_messages",
|
|
150
|
+
"browser_network_requests",
|
|
151
|
+
"browser_verify_element_visible",
|
|
152
|
+
"browser_verify_text_visible"
|
|
153
|
+
];
|
|
154
|
+
var MEMORY_TOOL_NAMES = ["memoryRemember", "memoryRecall", "memoryDelete"];
|
|
155
|
+
var TOOL_NAMES = [
|
|
156
|
+
"webFetch",
|
|
157
|
+
"brightDataWebSearch",
|
|
158
|
+
"brightDataImageSearch",
|
|
159
|
+
"brightDataNewsSearch",
|
|
160
|
+
"brightDataPlacesSearch",
|
|
161
|
+
"brightDataShoppingSearch",
|
|
162
|
+
"brightDataVideoSearch",
|
|
163
|
+
"brightDataWebpageScrape",
|
|
164
|
+
"serperWebSearch",
|
|
165
|
+
"serperImageSearch",
|
|
166
|
+
"serperNewsSearch",
|
|
167
|
+
"serperPlacesSearch",
|
|
168
|
+
"serperShoppingSearch",
|
|
169
|
+
"serperBusinessReviewsSearch",
|
|
170
|
+
"serperVideoSearch",
|
|
171
|
+
"serperWebpageScrape",
|
|
172
|
+
"youtubeVideoSearch",
|
|
173
|
+
"eodhdSearch",
|
|
174
|
+
"eodhdQuote",
|
|
175
|
+
"eodhdHistory",
|
|
176
|
+
"eodhdTechnical",
|
|
177
|
+
"eodhdIntraday",
|
|
178
|
+
"eodhdNews",
|
|
179
|
+
"eodhdFundamentals",
|
|
180
|
+
"requestGrayscale",
|
|
181
|
+
"requestDenoised",
|
|
182
|
+
"requestSharpened",
|
|
183
|
+
"requestClahe",
|
|
184
|
+
"memoryRemember",
|
|
185
|
+
"memoryRecall",
|
|
186
|
+
"memoryDelete",
|
|
187
|
+
...BROWSER_TOOL_NAMES
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
// src/schemas/helpers/url-trust/has-blocked-image-host.helper.ts
|
|
191
|
+
function hasBlockedImageHost(url) {
|
|
192
|
+
if (!url || url.startsWith("/") || url.startsWith("data:image/")) return false;
|
|
193
|
+
let parsed;
|
|
194
|
+
try {
|
|
195
|
+
parsed = new URL(url);
|
|
196
|
+
} catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
|
|
200
|
+
return BLOCKED_IMAGE_HOSTS.has(parsed.hostname.toLowerCase());
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/schemas/helpers/url-trust/is-private-or-localhost.helper.ts
|
|
204
|
+
function isPrivateOrLocalhost(hostname) {
|
|
205
|
+
const lower = hostname.toLowerCase();
|
|
206
|
+
if (lower === "localhost" || lower.endsWith(".localhost")) return true;
|
|
207
|
+
if (lower === "127.0.0.1" || lower === "0.0.0.0") return true;
|
|
208
|
+
if (lower.startsWith("10.")) return true;
|
|
209
|
+
if (/^172\.(1[6-9]|2\d|3[0-1])\./.test(lower)) return true;
|
|
210
|
+
if (lower.startsWith("192.168.")) return true;
|
|
211
|
+
if (lower.startsWith("169.254.")) return true;
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/schemas/helpers/url-trust/is-trusted-image-url.helper.ts
|
|
216
|
+
var TRUSTED_IMAGE_HOSTS = /* @__PURE__ */ new Set([
|
|
217
|
+
"i.imgur.com",
|
|
218
|
+
"i.redd.it",
|
|
219
|
+
"preview.redd.it",
|
|
220
|
+
"upload.wikimedia.org",
|
|
221
|
+
"commons.wikimedia.org",
|
|
222
|
+
"images.unsplash.com",
|
|
223
|
+
"images.pexels.com",
|
|
224
|
+
"cdn.pixabay.com",
|
|
225
|
+
"live.staticflickr.com",
|
|
226
|
+
"farm1.staticflickr.com",
|
|
227
|
+
"farm2.staticflickr.com",
|
|
228
|
+
"farm3.staticflickr.com",
|
|
229
|
+
"farm4.staticflickr.com",
|
|
230
|
+
"farm5.staticflickr.com",
|
|
231
|
+
"farm6.staticflickr.com",
|
|
232
|
+
"farm7.staticflickr.com",
|
|
233
|
+
"farm8.staticflickr.com",
|
|
234
|
+
"farm9.staticflickr.com",
|
|
235
|
+
"i.pinimg.com",
|
|
236
|
+
"media.istockphoto.com",
|
|
237
|
+
"assets.istockphoto.com",
|
|
238
|
+
"media.gettyimages.com",
|
|
239
|
+
"embed.gettyimages.com",
|
|
240
|
+
// Social image CDNs (images are generally embeddable, unlike videos)
|
|
241
|
+
"pbs.twimg.com",
|
|
242
|
+
"cdninstagram.com",
|
|
243
|
+
"scontent.cdninstagram.com",
|
|
244
|
+
"scontent-iad3-1.cdninstagram.com",
|
|
245
|
+
"graph.facebook.com",
|
|
246
|
+
"scontent-iad3-1.xx.fbcdn.net",
|
|
247
|
+
"scontent.xx.fbcdn.net",
|
|
248
|
+
"static.xx.fbcdn.net",
|
|
249
|
+
// Cloud/CDNs
|
|
250
|
+
"res.cloudinary.com",
|
|
251
|
+
"images.ctfassets.net",
|
|
252
|
+
"cdn.shopify.com",
|
|
253
|
+
"imgix.net",
|
|
254
|
+
"wpmedia.roomsketcher.com",
|
|
255
|
+
// Bing image CDN
|
|
256
|
+
"tse1.mm.bing.net",
|
|
257
|
+
"tse2.mm.bing.net",
|
|
258
|
+
"tse3.mm.bing.net",
|
|
259
|
+
"tse4.mm.bing.net"
|
|
260
|
+
]);
|
|
261
|
+
var DIRECT_IMAGE_EXTENSION = /\.(jpg|jpeg|png|gif|webp|bmp|tiff|tif|avif|svg|ico)(\?.*)?$/i;
|
|
262
|
+
function isTrustedImageUrl(url) {
|
|
263
|
+
if (!url) return false;
|
|
264
|
+
if (url.startsWith("/") || url.startsWith("data:image/")) return true;
|
|
265
|
+
let parsed;
|
|
266
|
+
try {
|
|
267
|
+
parsed = new URL(url);
|
|
268
|
+
} catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
|
|
272
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
273
|
+
if (BLOCKED_IMAGE_HOSTS.has(hostname)) return false;
|
|
274
|
+
if (TRUSTED_IMAGE_HOSTS.has(hostname)) return true;
|
|
275
|
+
if (DIRECT_IMAGE_EXTENSION.test(parsed.pathname)) return true;
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// src/schemas/helpers/url-trust/is-trusted-url.helper.ts
|
|
280
|
+
function isYouTubeNonVideoPath(hostname, pathname) {
|
|
281
|
+
const lowerHost = hostname.toLowerCase();
|
|
282
|
+
if (lowerHost !== "youtube.com" && lowerHost !== "www.youtube.com" && lowerHost !== "m.youtube.com") {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
const lowerPath = pathname.toLowerCase();
|
|
286
|
+
if (lowerPath.startsWith("/s/") || lowerPath.startsWith("/static/") || lowerPath.startsWith("/js/") || lowerPath.startsWith("/css/") || lowerPath.startsWith("/fonts/") || lowerPath.startsWith("/yts/") || lowerPath.startsWith("/iframe_api") || lowerPath.startsWith("/sw.js") || lowerPath.startsWith("/embed_config") || lowerPath.startsWith("/get_video_info") || lowerPath.startsWith("/api/")) {
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
function isTrustedUrl(url, options = {}) {
|
|
292
|
+
if (!url) return false;
|
|
293
|
+
let parsed;
|
|
294
|
+
try {
|
|
295
|
+
parsed = new URL(url);
|
|
296
|
+
} catch {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
303
|
+
const pathname = parsed.pathname;
|
|
304
|
+
if (BLOCKED_URL_HOSTS.has(hostname)) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
if (isYouTubeNonVideoPath(hostname, pathname)) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
if (NON_PAGE_EXTENSIONS.test(pathname)) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
if (!options.allowPrivate && isPrivateOrLocalhost(hostname)) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
function safeUrl(message = "must be a safe URL") {
|
|
319
|
+
const text = typeof message === "string" ? message : message.message;
|
|
320
|
+
return z.string().url({ message: "must be a valid URL" }).refine((value) => isTrustedUrl(value, { allowPrivate: false }), {
|
|
321
|
+
message: text
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
var LOCAL_STORAGE_URL_PATTERN = /^\/api\/v1\/storage\/[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+\/[A-Za-z0-9]+$/;
|
|
325
|
+
function isAbsoluteHttpUrl(value) {
|
|
326
|
+
try {
|
|
327
|
+
const protocol = new URL(value).protocol;
|
|
328
|
+
return protocol === "http:" || protocol === "https:";
|
|
329
|
+
} catch {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function safeVideoUrl(message = "must be a safe video URL") {
|
|
334
|
+
const text = typeof message === "string" ? message : message.message;
|
|
335
|
+
return z.string().refine(isAbsoluteHttpUrl, { message: text });
|
|
336
|
+
}
|
|
337
|
+
function safeVideoUrlOrEmpty(message = "must be a safe video URL") {
|
|
338
|
+
return safeVideoUrl(message).optional().or(z.literal(""));
|
|
339
|
+
}
|
|
340
|
+
function safeMediaUrl(message = "must be a safe media URL") {
|
|
341
|
+
const text = typeof message === "string" ? message : message.message;
|
|
342
|
+
return z.string().refine((value) => LOCAL_STORAGE_URL_PATTERN.test(value) || isAbsoluteHttpUrl(value), { message: text });
|
|
343
|
+
}
|
|
344
|
+
function safeMediaUrlOrEmpty(message = "must be a safe media URL") {
|
|
345
|
+
return safeMediaUrl(message).optional().or(z.literal(""));
|
|
346
|
+
}
|
|
347
|
+
function deriveSchemaKeys(schema) {
|
|
348
|
+
const jsonSchema = z.toJSONSchema(schema);
|
|
349
|
+
const properties = jsonSchema.properties ?? {};
|
|
350
|
+
const required = new Set(jsonSchema.required ?? []);
|
|
351
|
+
const requiredKeys = [];
|
|
352
|
+
const optionalKeys = [];
|
|
353
|
+
for (const key of Object.keys(properties)) {
|
|
354
|
+
if (required.has(key)) requiredKeys.push(key);
|
|
355
|
+
else optionalKeys.push(key);
|
|
356
|
+
}
|
|
357
|
+
return { required: requiredKeys, optional: optionalKeys };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/schemas/helpers/zod/format-zod-issues.helper.ts
|
|
361
|
+
function formatZodIssues(issues) {
|
|
362
|
+
return issues.map((issue) => {
|
|
363
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
364
|
+
return `${path}: ${issue.message}`;
|
|
365
|
+
}).join("; ");
|
|
366
|
+
}
|
|
367
|
+
var INDENT = " ";
|
|
368
|
+
function formatZodShape(schema, options = {}) {
|
|
369
|
+
const jsonSchema = z.toJSONSchema(schema);
|
|
370
|
+
return renderNode(jsonSchema, 0, options);
|
|
371
|
+
}
|
|
372
|
+
function renderNode(node, depth, options) {
|
|
373
|
+
if (node.type === "object" && node.properties) return renderObject(node, depth, options);
|
|
374
|
+
if (node.type === "object" && node.additionalProperties) {
|
|
375
|
+
return `{ [key]: ${renderNode(node.additionalProperties, depth, options)} }`;
|
|
376
|
+
}
|
|
377
|
+
if (node.type === "array" && node.items) return `[${renderNode(node.items, depth, options)}]`;
|
|
378
|
+
const anyOfBranches = node.anyOf?.filter((branch) => branch.type !== "null");
|
|
379
|
+
if (anyOfBranches?.length) return anyOfBranches.map((branch) => renderNode(branch, depth, options)).join(" | ");
|
|
380
|
+
if (node.enum) return node.enum.map((value) => JSON.stringify(value)).join(" | ");
|
|
381
|
+
if (node.type === "integer" || node.type === "number") return "number";
|
|
382
|
+
if (node.type === "boolean") return "boolean";
|
|
383
|
+
if (node.type === "string") return "string";
|
|
384
|
+
if (node.type === "null") return "null";
|
|
385
|
+
return "unknown";
|
|
386
|
+
}
|
|
387
|
+
function renderObject(node, depth, options) {
|
|
388
|
+
const properties = node.properties ?? {};
|
|
389
|
+
const required = new Set(node.required ?? []);
|
|
390
|
+
const entries = Object.entries(properties);
|
|
391
|
+
if (entries.length === 0) return "{}";
|
|
392
|
+
const pad = INDENT.repeat(depth);
|
|
393
|
+
const innerPad = INDENT.repeat(depth + 1);
|
|
394
|
+
const lines = entries.map(([key, value]) => {
|
|
395
|
+
const optional = required.has(key) ? "" : "?";
|
|
396
|
+
const hint = options.overrides?.[key] ?? renderNode(value, depth + 1, options);
|
|
397
|
+
return `${innerPad}${JSON.stringify(key)}${optional}: ${hint}`;
|
|
398
|
+
});
|
|
399
|
+
return `{
|
|
400
|
+
${lines.join(",\n")}
|
|
401
|
+
${pad}}`;
|
|
402
|
+
}
|
|
403
|
+
var DEFAULT_VARIANT_ID = "default";
|
|
404
|
+
var TEMPLATES = [
|
|
405
|
+
"article",
|
|
406
|
+
"news",
|
|
407
|
+
"describe",
|
|
408
|
+
"compare",
|
|
409
|
+
"ocr",
|
|
410
|
+
"summary",
|
|
411
|
+
"evaluation",
|
|
412
|
+
"product",
|
|
413
|
+
"shoplist",
|
|
414
|
+
"imagelist",
|
|
415
|
+
"videolist",
|
|
416
|
+
"stockmarketitem",
|
|
417
|
+
"stockmarketlist",
|
|
418
|
+
"merge",
|
|
419
|
+
"text"
|
|
420
|
+
];
|
|
421
|
+
var ImagePlanSchema = z.object({
|
|
422
|
+
resize: z.boolean().default(true).describe(
|
|
423
|
+
"Whether to resize the original images before sending them to the response model. Default true when images are present."
|
|
424
|
+
),
|
|
425
|
+
variants: z.array(z.enum(VARIANT_NAMES)).default([]).describe(
|
|
426
|
+
"Optional preprocessing variants to generate for the images (grayscale, denoised, sharpened, clahe). Only use when they would materially improve analysis."
|
|
427
|
+
)
|
|
428
|
+
});
|
|
429
|
+
var IntentSchema = z.object({
|
|
430
|
+
template: z.enum(TEMPLATES).describe(
|
|
431
|
+
'Template name: "article" (in-depth research/report \u2014 extensive long-form composed from available snippets), "news" (current events \u2014 a compact brief composed from available snippets), "describe" (single/multi image description), "compare" (compare uploaded images only \u2014 information comparisons use "evaluation"), "ocr" (extract text from images), "summary" (recap prior conversation or topic without new images), "evaluation" (critique/assess something from the conversation), "product" (product details with shop offers and prices), "shoplist" (compact product/shop list for follow-up shopping questions about an already-introduced product), "imagelist" (a pure collection of images about a topic, no article), "videolist" (a pure list/playlist of videos about a topic, no article), "stockmarketitem" (a single stock/ETF/index with price chart, technicals, news, and a recommendation), "stockmarketlist" (a selection of stocks/indices with a market overview), "text" (free chat).'
|
|
432
|
+
),
|
|
433
|
+
prompt: z.string().default(DEFAULT_VARIANT_ID).describe(
|
|
434
|
+
'Selected prompt variant for the template. Use "default" unless the user explicitly asks for a specific style.'
|
|
435
|
+
),
|
|
436
|
+
tools: z.array(z.enum(TOOL_NAMES)).describe("List of tool names the model decided to invoke."),
|
|
437
|
+
getDate: z.boolean().default(true).describe(
|
|
438
|
+
'Whether search queries should be anchored on the current date so results bias toward recent information. Default true. Set to false ONLY for timeless general-knowledge, historical, or conceptual requests where recency does not matter (e.g. "how does photosynthesis work", "history of the Roman Empire", "explain quantum entanglement", creative writing).'
|
|
439
|
+
),
|
|
440
|
+
imageCount: z.preprocess((val) => val === null ? 0 : val, z.number().int().min(0).max(50).default(0)).describe(
|
|
441
|
+
"Number of images to retrieve when an imageSearch tool is selected. Only set when the user explicitly requests a specific number; otherwise omit or set to 0 and the system will default to 6."
|
|
442
|
+
),
|
|
443
|
+
videoCount: z.preprocess((val) => val === null ? 0 : val, z.number().int().min(0).max(50).default(0)).describe(
|
|
444
|
+
"Number of videos to retrieve when a videoSearch tool is selected. Only set when the user explicitly requests a specific number; otherwise omit or set to 0 and the system will default to 6."
|
|
445
|
+
),
|
|
446
|
+
reasoning: z.string().describe("Short explanation of why this template, prompt, and these tools were chosen."),
|
|
447
|
+
contextSummary: z.string().default("").describe(
|
|
448
|
+
"Query-focused extraction of the prior conversation context that the latest user message references or depends on: established topics/entities, key facts from prior answers the follow-up builds on, user constraints, and \u2014 for imagelist/videolist follow-ups \u2014 the previously shown image/video URLs verbatim. Empty if there is no relevant prior context."
|
|
449
|
+
),
|
|
450
|
+
needsClarification: z.boolean().default(false).describe("When true, the request is too ambiguous to classify \u2014 set this instead of picking template/tools."),
|
|
451
|
+
clarificationQuestion: z.string().nullable().optional().describe(
|
|
452
|
+
"Concise, human-friendly question to ask the user when needsClarification is true. Ask what the user might have meant and offer the most likely interpretations as options. Do not hardcode wording; adapt tone and language to the user."
|
|
453
|
+
),
|
|
454
|
+
language: z.string().nullable().optional().describe(
|
|
455
|
+
"Two-letter ISO language code of the latest user message (e.g. 'en', 'de', 'ja', 'es'). Detect from the user's text."
|
|
456
|
+
),
|
|
457
|
+
plan: z.object({
|
|
458
|
+
images: ImagePlanSchema.optional().describe("Image processing plan. Only present when images are attached.")
|
|
459
|
+
}).default({}).describe("Execution plan for the response step.")
|
|
460
|
+
});
|
|
461
|
+
var ConsolidationVerdictSchema = z.object({
|
|
462
|
+
verdict: z.enum(["keep", "redundant", "merge"]).describe(
|
|
463
|
+
"keep = the new fact adds information not covered by the candidates; redundant = fully covered already (same claim, no new detail, same polarity); merge = it refines/corrects/completes a candidate and mergedText carries the fuller statement."
|
|
464
|
+
),
|
|
465
|
+
mergedText: z.string().optional().describe("Required with verdict=merge: one fuller self-contained statement (full restatement, never a diff).")
|
|
466
|
+
});
|
|
467
|
+
var ExtractionSchema = z.object({
|
|
468
|
+
/**
|
|
469
|
+
* Durable, self-contained facts worth remembering in a later, unrelated
|
|
470
|
+
* conversation (preferences, decisions, contact details, project facts).
|
|
471
|
+
* Empty when nothing in the text is worth remembering.
|
|
472
|
+
*/
|
|
473
|
+
facts: z.array(z.string()),
|
|
474
|
+
/**
|
|
475
|
+
* 2–6 stable, reusable lowercase topic labels describing the text; the open
|
|
476
|
+
* vocabulary that powers topic-filtered recall.
|
|
477
|
+
*/
|
|
478
|
+
tags: z.array(z.string())
|
|
479
|
+
});
|
|
480
|
+
var nullishText = z.string().nullish();
|
|
481
|
+
var nullishTopics = z.array(z.string()).nullish();
|
|
482
|
+
var memoryCognitionProfileSchema = z.object({
|
|
483
|
+
/** The user's name or preferred handle, when known. */
|
|
484
|
+
name: nullishText,
|
|
485
|
+
/** Primary conversation language (BCP-47-ish, e.g. "en", "de"). */
|
|
486
|
+
language: nullishText,
|
|
487
|
+
/** Coarse location the user works from (IANA name or city), when known. */
|
|
488
|
+
timezone: nullishText,
|
|
489
|
+
/** Demonstrated skills and domains (e.g. ["TypeScript", "NestJS"]). */
|
|
490
|
+
expertise: nullishTopics,
|
|
491
|
+
/** Active goals and aspirations — the most durable cognition there is. */
|
|
492
|
+
goals: nullishTopics,
|
|
493
|
+
/** How the user wants to be answered. */
|
|
494
|
+
communication: z.object({
|
|
495
|
+
style: nullishText,
|
|
496
|
+
detailLevel: nullishText,
|
|
497
|
+
formality: nullishText
|
|
498
|
+
}).nullish(),
|
|
499
|
+
/** Tooling / environment / format preferences (free-form key-value). */
|
|
500
|
+
preferences: z.record(z.string(), z.string()).nullish(),
|
|
501
|
+
likes: nullishTopics,
|
|
502
|
+
dislikes: nullishTopics,
|
|
503
|
+
/** Topics the user keeps returning to. */
|
|
504
|
+
interests: nullishTopics,
|
|
505
|
+
/** The AI's own identity as the user has shaped it (name, role, voice). */
|
|
506
|
+
persona: z.object({
|
|
507
|
+
/** The name the user gave the AI. */
|
|
508
|
+
name: nullishText,
|
|
509
|
+
/** The role the user assigned the AI (e.g. "coding assistant"). */
|
|
510
|
+
role: nullishText,
|
|
511
|
+
/** Short character description the user gave the AI. */
|
|
512
|
+
personality: nullishText,
|
|
513
|
+
/** How the AI introduces itself, when the user set one. */
|
|
514
|
+
greeting: nullishText,
|
|
515
|
+
/** How the AI should speak. */
|
|
516
|
+
voice: z.object({
|
|
517
|
+
tone: nullishText,
|
|
518
|
+
formality: nullishText
|
|
519
|
+
}).nullish()
|
|
520
|
+
}).nullish(),
|
|
521
|
+
/**
|
|
522
|
+
* Learned corrections — behavioral rules the user taught the AI after it
|
|
523
|
+
* got something wrong. Keyed by a short slug (a stable handle for
|
|
524
|
+
* update/remove); the value is the imperative directive ("always …" /
|
|
525
|
+
* "never …"), optionally with a brief why. Deep-merged like preferences.
|
|
526
|
+
*/
|
|
527
|
+
corrections: z.record(z.string(), z.string()).nullish()
|
|
528
|
+
});
|
|
529
|
+
function normalizeCognitionProfile(profile) {
|
|
530
|
+
if (!profile) return void 0;
|
|
531
|
+
const cleaned = {};
|
|
532
|
+
for (const [key, value] of Object.entries(profile)) {
|
|
533
|
+
const kept = cleanProfileValue(value);
|
|
534
|
+
if (kept !== void 0) cleaned[key] = kept;
|
|
535
|
+
}
|
|
536
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
537
|
+
}
|
|
538
|
+
function cleanProfileValue(value) {
|
|
539
|
+
if (value === null || value === void 0) return void 0;
|
|
540
|
+
if (typeof value === "string") return value.trim() || void 0;
|
|
541
|
+
if (Array.isArray(value)) {
|
|
542
|
+
const items = value.map((entry) => typeof entry === "string" ? entry.trim() : entry).filter(Boolean);
|
|
543
|
+
return items.length > 0 ? items : void 0;
|
|
544
|
+
}
|
|
545
|
+
if (typeof value !== "object") return void 0;
|
|
546
|
+
const inner = Object.fromEntries(
|
|
547
|
+
Object.entries(value).map(([k, v]) => [k, cleanProfileValue(v)]).filter(([, v]) => v !== void 0)
|
|
548
|
+
);
|
|
549
|
+
return Object.keys(inner).length > 0 ? inner : void 0;
|
|
550
|
+
}
|
|
551
|
+
function mergeCognitionProfiles(current, patch) {
|
|
552
|
+
const patchRecord = patch;
|
|
553
|
+
const removals = Object.keys(patchRecord).filter(
|
|
554
|
+
(key) => patchRecord[key] === null || patchRecord[key] === void 0
|
|
555
|
+
);
|
|
556
|
+
const base = current ?? {};
|
|
557
|
+
const merged = merge(
|
|
558
|
+
omit(base, removals),
|
|
559
|
+
omit(patch, removals),
|
|
560
|
+
true
|
|
561
|
+
);
|
|
562
|
+
const profile = normalizeCognitionProfile(merged) ?? {};
|
|
563
|
+
const before = normalizeCognitionProfile(base) ?? {};
|
|
564
|
+
const changed = JSON.stringify(profile) !== JSON.stringify(before);
|
|
565
|
+
return { profile: changed ? profile : void 0, removals };
|
|
566
|
+
}
|
|
567
|
+
function isAllFieldsNullWipe(current, patch) {
|
|
568
|
+
if (!current) return false;
|
|
569
|
+
const currentKeys = Object.keys(current);
|
|
570
|
+
if (currentKeys.length === 0) return false;
|
|
571
|
+
const patchRecord = patch;
|
|
572
|
+
const presentKeys = Object.keys(patchRecord);
|
|
573
|
+
if (presentKeys.length === 0) return false;
|
|
574
|
+
const nullKeys = presentKeys.filter((key) => patchRecord[key] === null || patchRecord[key] === void 0);
|
|
575
|
+
return nullKeys.length === presentKeys.length && currentKeys.every((key) => nullKeys.includes(key));
|
|
576
|
+
}
|
|
577
|
+
function parseStoredProfile(text) {
|
|
578
|
+
if (!text?.trim()) return {};
|
|
579
|
+
try {
|
|
580
|
+
const parsed = JSON.parse(text);
|
|
581
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
582
|
+
} catch {
|
|
583
|
+
return {};
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
var memoryProfileInsightSchema = z.object({
|
|
587
|
+
text: z.string(),
|
|
588
|
+
path: z.string().optional()
|
|
589
|
+
});
|
|
590
|
+
function normalizePathSegment(segment) {
|
|
591
|
+
return segment.trim().toLowerCase().replace(/\s+/g, "-");
|
|
592
|
+
}
|
|
593
|
+
function normalizeInsightPath(path) {
|
|
594
|
+
const trimmed = path?.trim();
|
|
595
|
+
if (!trimmed) return void 0;
|
|
596
|
+
const dot = trimmed.indexOf(".");
|
|
597
|
+
if (dot <= 0) return void 0;
|
|
598
|
+
const field = normalizePathSegment(trimmed.slice(0, dot));
|
|
599
|
+
const keyword = normalizePathSegment(trimmed.slice(dot + 1));
|
|
600
|
+
if (!field || !keyword) return void 0;
|
|
601
|
+
return `${field}.${keyword}`;
|
|
602
|
+
}
|
|
603
|
+
var memoryProfileResponseSchema = z.preprocess(
|
|
604
|
+
(value) => {
|
|
605
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return value;
|
|
606
|
+
const record = value;
|
|
607
|
+
if (record.insights == null) record.insights = [];
|
|
608
|
+
else if (Array.isArray(record.insights)) {
|
|
609
|
+
record.insights = record.insights.map((item) => typeof item === "string" ? { text: item } : item);
|
|
610
|
+
}
|
|
611
|
+
return record;
|
|
612
|
+
},
|
|
613
|
+
z.object({
|
|
614
|
+
profile: memoryCognitionProfileSchema.nullish(),
|
|
615
|
+
insights: z.array(memoryProfileInsightSchema).max(8),
|
|
616
|
+
/**
|
|
617
|
+
* One sentence recording what THIS turn was about — the short-term
|
|
618
|
+
* conversation memory (episode), recalled later by recency-blended probe.
|
|
619
|
+
* Omitted (or null) when the turn had no substance.
|
|
620
|
+
*/
|
|
621
|
+
episode: z.string().nullish()
|
|
622
|
+
})
|
|
623
|
+
);
|
|
624
|
+
var INSIGHT_TAGS = ["cognition", "insight"];
|
|
625
|
+
var EPISODE_TAGS = ["cognition", "episode"];
|
|
626
|
+
var COGNITION_LIMIT_DEFAULT = 5e3;
|
|
627
|
+
var COGNITION_LIMIT_MIN = 500;
|
|
628
|
+
var COGNITION_LIMIT_MAX = 32e3;
|
|
629
|
+
var INSIGHT_TEXT_LIMIT = 500;
|
|
630
|
+
var EPISODE_TEXT_LIMIT = 500;
|
|
631
|
+
var INSIGHTS_MAX_PER_TURN = 8;
|
|
632
|
+
var COGNITION_PURGE_BATCH = 500;
|
|
633
|
+
function clampCognitionLimit(value) {
|
|
634
|
+
if (!Number.isFinite(value)) return COGNITION_LIMIT_DEFAULT;
|
|
635
|
+
return Math.min(COGNITION_LIMIT_MAX, Math.max(COGNITION_LIMIT_MIN, Math.trunc(value)));
|
|
636
|
+
}
|
|
637
|
+
var EPISODE_RECENCY_WEIGHT_DEFAULT = 0.3;
|
|
638
|
+
var EPISODE_RECENCY_SCALE_SECONDS_DEFAULT = 7 * 24 * 60 * 60;
|
|
639
|
+
var EPISODE_RECENCY_MIDPOINT_DEFAULT = 0.5;
|
|
640
|
+
var EPISODE_PROBE_LIMIT_DEFAULT = 3;
|
|
641
|
+
var EPISODE_SCORE_THRESHOLD_DEFAULT = 0.1;
|
|
642
|
+
var EPISODE_RECENCY_WEIGHT_MIN = 0;
|
|
643
|
+
var EPISODE_RECENCY_WEIGHT_MAX = 1;
|
|
644
|
+
var EPISODE_RECENCY_SCALE_SECONDS_MIN = 60;
|
|
645
|
+
var EPISODE_RECENCY_SCALE_SECONDS_MAX = 31536e3;
|
|
646
|
+
var EPISODE_RECENCY_MIDPOINT_MIN = 0.01;
|
|
647
|
+
var EPISODE_RECENCY_MIDPOINT_MAX = 0.99;
|
|
648
|
+
var EPISODE_PROBE_LIMIT_MIN = 1;
|
|
649
|
+
var EPISODE_PROBE_LIMIT_MAX = 10;
|
|
650
|
+
var EPISODE_SCORE_THRESHOLD_MIN = 0;
|
|
651
|
+
var EPISODE_SCORE_THRESHOLD_MAX = 1;
|
|
652
|
+
function clampEpisodeRecencyWeight(value) {
|
|
653
|
+
if (!Number.isFinite(value)) return EPISODE_RECENCY_WEIGHT_DEFAULT;
|
|
654
|
+
return Math.min(EPISODE_RECENCY_WEIGHT_MAX, Math.max(EPISODE_RECENCY_WEIGHT_MIN, value));
|
|
655
|
+
}
|
|
656
|
+
function clampEpisodeRecencyScaleSeconds(value) {
|
|
657
|
+
if (!Number.isFinite(value)) return EPISODE_RECENCY_SCALE_SECONDS_DEFAULT;
|
|
658
|
+
return Math.min(EPISODE_RECENCY_SCALE_SECONDS_MAX, Math.max(EPISODE_RECENCY_SCALE_SECONDS_MIN, Math.trunc(value)));
|
|
659
|
+
}
|
|
660
|
+
function clampEpisodeRecencyMidpoint(value) {
|
|
661
|
+
if (!Number.isFinite(value)) return EPISODE_RECENCY_MIDPOINT_DEFAULT;
|
|
662
|
+
return Math.min(EPISODE_RECENCY_MIDPOINT_MAX, Math.max(EPISODE_RECENCY_MIDPOINT_MIN, value));
|
|
663
|
+
}
|
|
664
|
+
function clampEpisodeProbeLimit(value) {
|
|
665
|
+
if (!Number.isFinite(value)) return EPISODE_PROBE_LIMIT_DEFAULT;
|
|
666
|
+
return Math.min(EPISODE_PROBE_LIMIT_MAX, Math.max(EPISODE_PROBE_LIMIT_MIN, Math.trunc(value)));
|
|
667
|
+
}
|
|
668
|
+
function clampEpisodeScoreThreshold(value) {
|
|
669
|
+
if (!Number.isFinite(value)) return EPISODE_SCORE_THRESHOLD_DEFAULT;
|
|
670
|
+
return Math.min(EPISODE_SCORE_THRESHOLD_MAX, Math.max(EPISODE_SCORE_THRESHOLD_MIN, value));
|
|
671
|
+
}
|
|
672
|
+
var cardSchema = z.object(
|
|
673
|
+
{
|
|
674
|
+
url: safeUrl({ message: "cards entries must have a valid url" }),
|
|
675
|
+
title: z.string().optional(),
|
|
676
|
+
description: z.string().optional(),
|
|
677
|
+
linkLabel: z.string().optional()
|
|
678
|
+
},
|
|
679
|
+
{ message: "cards entries must be objects with url" }
|
|
680
|
+
);
|
|
681
|
+
var referenceLineSchema = z.object(
|
|
682
|
+
{
|
|
683
|
+
value: z.number(),
|
|
684
|
+
label: z.string().optional(),
|
|
685
|
+
/** A theme token name, e.g. "accent-primary" or "status-error". */
|
|
686
|
+
color: z.string().optional()
|
|
687
|
+
},
|
|
688
|
+
{ message: "referenceLines entries must be objects with a numeric value" }
|
|
689
|
+
);
|
|
690
|
+
var markerSchema = z.object(
|
|
691
|
+
{
|
|
692
|
+
time: z.string().min(1, { message: "markers entries must have a time" }),
|
|
693
|
+
position: z.enum(["aboveBar", "belowBar"]),
|
|
694
|
+
/** A theme token name, e.g. "harmony-3" or "status-error". */
|
|
695
|
+
color: z.string().optional(),
|
|
696
|
+
shape: z.enum(["circle", "arrowUp", "arrowDown", "square"]),
|
|
697
|
+
text: z.string().optional()
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
message: "markers entries must be objects with time, position, and shape"
|
|
701
|
+
}
|
|
702
|
+
);
|
|
703
|
+
var discardedReferenceSchema = z.discriminatedUnion("type", [
|
|
704
|
+
z.object({
|
|
705
|
+
type: z.literal("image"),
|
|
706
|
+
imageUrl: z.string().min(1),
|
|
707
|
+
title: z.string(),
|
|
708
|
+
reason: z.string().min(1, { message: "reason must not be empty" })
|
|
709
|
+
}),
|
|
710
|
+
z.object({
|
|
711
|
+
type: z.literal("link"),
|
|
712
|
+
url: z.string().min(1),
|
|
713
|
+
title: z.string(),
|
|
714
|
+
reason: z.string().min(1, { message: "reason must not be empty" })
|
|
715
|
+
})
|
|
716
|
+
]);
|
|
717
|
+
var internationalCoverageSchema = z.array(
|
|
718
|
+
z.object(
|
|
719
|
+
{
|
|
720
|
+
title: z.string().optional(),
|
|
721
|
+
url: safeUrl({
|
|
722
|
+
message: "internationalCoverage entries must have a valid url"
|
|
723
|
+
}),
|
|
724
|
+
sourceName: z.string().optional(),
|
|
725
|
+
language: z.string().optional(),
|
|
726
|
+
summary: z.string().optional()
|
|
727
|
+
},
|
|
728
|
+
{ message: "internationalCoverage entries must be objects" }
|
|
729
|
+
)
|
|
730
|
+
);
|
|
731
|
+
var referenceGalleryItemSchema = z.object(
|
|
732
|
+
{
|
|
733
|
+
imageUrl: z.string(),
|
|
734
|
+
imageAlt: z.string().optional(),
|
|
735
|
+
title: z.string().optional(),
|
|
736
|
+
caption: z.string().optional()
|
|
737
|
+
},
|
|
738
|
+
{ message: "galleryItems entries must be objects with imageUrl" }
|
|
739
|
+
);
|
|
740
|
+
var sourceSchema = z.object(
|
|
741
|
+
{
|
|
742
|
+
url: safeUrl({ message: "sources entries must have a valid url" }),
|
|
743
|
+
title: z.string().optional(),
|
|
744
|
+
sourceName: z.string().optional(),
|
|
745
|
+
date: z.string().optional(),
|
|
746
|
+
snippet: z.string().optional()
|
|
747
|
+
},
|
|
748
|
+
{ message: "sources entries must be objects with url" }
|
|
749
|
+
);
|
|
750
|
+
function createTextItemSchema(fieldName) {
|
|
751
|
+
return z.object(
|
|
752
|
+
{
|
|
753
|
+
text: z.string().min(1, {
|
|
754
|
+
message: `${fieldName} entries must have a non-empty text field`
|
|
755
|
+
})
|
|
756
|
+
},
|
|
757
|
+
{ message: `${fieldName} entries must be objects with text` }
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
var videoGalleryItemSchema = z.object(
|
|
761
|
+
{
|
|
762
|
+
videoUrl: safeVideoUrl({
|
|
763
|
+
message: "videoGalleryItems.videoUrl must be a valid URL"
|
|
764
|
+
}),
|
|
765
|
+
title: z.string().min(1, {
|
|
766
|
+
message: "videoGalleryItems.title must not be empty"
|
|
767
|
+
}),
|
|
768
|
+
caption: z.string().min(1, {
|
|
769
|
+
message: "videoGalleryItems.caption must not be empty"
|
|
770
|
+
}),
|
|
771
|
+
duration: z.string().optional(),
|
|
772
|
+
channel: z.string().optional(),
|
|
773
|
+
date: z.string().optional(),
|
|
774
|
+
views: z.number().int().min(0).optional(),
|
|
775
|
+
thumbnailUrl: safeMediaUrlOrEmpty({
|
|
776
|
+
message: "videoGalleryItems.thumbnailUrl must be a valid URL"
|
|
777
|
+
}),
|
|
778
|
+
description: z.string().optional()
|
|
779
|
+
},
|
|
780
|
+
{ message: "videoGalleryItems entries must be objects with videoUrl" }
|
|
781
|
+
);
|
|
782
|
+
function heroVideoHasTitle(data) {
|
|
783
|
+
return !data.heroVideoUrl?.trim() || Boolean(data.heroVideoTitle?.trim());
|
|
784
|
+
}
|
|
785
|
+
var HERO_VIDEO_TITLE_ISSUE = {
|
|
786
|
+
message: "heroVideoTitle must not be empty when heroVideoUrl is set",
|
|
787
|
+
path: ["heroVideoTitle"]
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
// src/schemas/response/compare-json.schema.ts
|
|
791
|
+
var keyFindingSchema = createTextItemSchema("keyFindings");
|
|
792
|
+
var compareSchema = z.object({
|
|
793
|
+
category: z.string(),
|
|
794
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
795
|
+
subtitle: z.string(),
|
|
796
|
+
sectionContent: z.string(),
|
|
797
|
+
galleryTitle: z.string().optional(),
|
|
798
|
+
galleryItems: z.array(referenceGalleryItemSchema).optional(),
|
|
799
|
+
videoGalleryTitle: z.string().optional(),
|
|
800
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional(),
|
|
801
|
+
keyFindings: z.array(keyFindingSchema).optional(),
|
|
802
|
+
sources: z.array(sourceSchema).optional(),
|
|
803
|
+
discardedReferences: z.array(discardedReferenceSchema).optional(),
|
|
804
|
+
note: z.string().optional(),
|
|
805
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
806
|
+
});
|
|
807
|
+
var keyFindingSchema2 = createTextItemSchema("keyFindings");
|
|
808
|
+
var describeSchema = z.object({
|
|
809
|
+
category: z.string(),
|
|
810
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
811
|
+
subtitle: z.string(),
|
|
812
|
+
sectionContent: z.string(),
|
|
813
|
+
galleryTitle: z.string().optional(),
|
|
814
|
+
galleryItems: z.array(referenceGalleryItemSchema).optional(),
|
|
815
|
+
videoGalleryTitle: z.string().optional(),
|
|
816
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional(),
|
|
817
|
+
keyFindings: z.array(keyFindingSchema2).optional(),
|
|
818
|
+
sources: z.array(sourceSchema).optional(),
|
|
819
|
+
discardedReferences: z.array(discardedReferenceSchema).optional(),
|
|
820
|
+
note: z.string().optional(),
|
|
821
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
822
|
+
});
|
|
823
|
+
var galleryItemSchema = z.object(
|
|
824
|
+
{
|
|
825
|
+
imageUrl: safeMediaUrl({
|
|
826
|
+
message: "galleryItems.imageUrl must be a valid URL"
|
|
827
|
+
}),
|
|
828
|
+
imageAlt: z.string().min(1, {
|
|
829
|
+
message: "galleryItems.imageAlt must not be empty"
|
|
830
|
+
}),
|
|
831
|
+
title: z.string().min(1, {
|
|
832
|
+
message: "galleryItems.title must not be empty"
|
|
833
|
+
}),
|
|
834
|
+
caption: z.string().optional()
|
|
835
|
+
},
|
|
836
|
+
{ message: "galleryItems entries must be objects with imageUrl" }
|
|
837
|
+
);
|
|
838
|
+
var imagelistGalleryItemSchema = galleryItemSchema.extend({
|
|
839
|
+
width: z.number().int().positive().optional(),
|
|
840
|
+
height: z.number().int().positive().optional(),
|
|
841
|
+
source: z.string().optional()
|
|
842
|
+
});
|
|
843
|
+
var imagelistSchema = z.object({
|
|
844
|
+
category: z.string(),
|
|
845
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
846
|
+
subtitle: z.string(),
|
|
847
|
+
galleryItems: z.array(imagelistGalleryItemSchema),
|
|
848
|
+
sources: z.array(sourceSchema).optional(),
|
|
849
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
850
|
+
});
|
|
851
|
+
var keyFindingSchema3 = createTextItemSchema("keyFindings");
|
|
852
|
+
var ocrSchema = z.object({
|
|
853
|
+
category: z.string(),
|
|
854
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
855
|
+
subtitle: z.string(),
|
|
856
|
+
sectionContent: z.string(),
|
|
857
|
+
keyFindings: z.array(keyFindingSchema3).optional(),
|
|
858
|
+
// Reference material, only when the model researched visible clues online
|
|
859
|
+
galleryTitle: z.string().optional(),
|
|
860
|
+
galleryItems: z.array(referenceGalleryItemSchema).optional(),
|
|
861
|
+
videoGalleryTitle: z.string().optional(),
|
|
862
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional(),
|
|
863
|
+
sources: z.array(sourceSchema).optional(),
|
|
864
|
+
discardedReferences: z.array(discardedReferenceSchema).optional(),
|
|
865
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
866
|
+
});
|
|
867
|
+
var shopOfferSchema = z.object(
|
|
868
|
+
{
|
|
869
|
+
title: z.string().optional(),
|
|
870
|
+
price: z.string().optional(),
|
|
871
|
+
source: z.string().optional(),
|
|
872
|
+
link: safeUrl({ message: "shopOffers entries must have a valid link" }),
|
|
873
|
+
imageUrl: z.string().url().optional().or(z.literal("")),
|
|
874
|
+
delivery: z.string().optional(),
|
|
875
|
+
rating: z.number().optional(),
|
|
876
|
+
ratingCount: z.number().optional()
|
|
877
|
+
},
|
|
878
|
+
{ message: "shopOffers entries must be objects with a link" }
|
|
879
|
+
);
|
|
880
|
+
var statHighlightSchema = z.object(
|
|
881
|
+
{
|
|
882
|
+
label: z.string().min(1, { message: "statHighlights entries must have a label" }),
|
|
883
|
+
value: z.string().min(1, { message: "statHighlights entries must have a value" })
|
|
884
|
+
},
|
|
885
|
+
{ message: "statHighlights entries must be objects with label and value" }
|
|
886
|
+
);
|
|
887
|
+
var productSchema = z.object({
|
|
888
|
+
category: z.string(),
|
|
889
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
890
|
+
subtitle: z.string(),
|
|
891
|
+
shortDescription: z.string(),
|
|
892
|
+
// Purchase-decision fields
|
|
893
|
+
aggregateRating: z.number().min(0).max(5).optional(),
|
|
894
|
+
aggregateRatingCount: z.number().int().min(0).optional(),
|
|
895
|
+
aggregateRatingLabel: z.string().optional(),
|
|
896
|
+
statHighlights: z.array(statHighlightSchema).optional(),
|
|
897
|
+
keyPoints: z.array(createTextItemSchema("keyPoints")).optional(),
|
|
898
|
+
pros: z.array(createTextItemSchema("pros")).optional(),
|
|
899
|
+
cons: z.array(createTextItemSchema("cons")).optional(),
|
|
900
|
+
shopOffers: z.array(shopOfferSchema).optional(),
|
|
901
|
+
// Media — the product banner is image-only, there is no hero video
|
|
902
|
+
heroImageUrl: safeMediaUrlOrEmpty(),
|
|
903
|
+
heroImageAlt: z.string().optional(),
|
|
904
|
+
heroCaption: z.string().optional(),
|
|
905
|
+
galleryTitle: z.string().optional(),
|
|
906
|
+
galleryItems: z.array(galleryItemSchema).optional(),
|
|
907
|
+
videoGalleryTitle: z.string().optional(),
|
|
908
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional(),
|
|
909
|
+
// Attribution
|
|
910
|
+
sources: z.array(sourceSchema).optional(),
|
|
911
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
912
|
+
});
|
|
913
|
+
var relatedStorySchema = z.object(
|
|
914
|
+
{
|
|
915
|
+
title: z.string().min(1, { message: "relatedStories entries must have a title" }),
|
|
916
|
+
url: safeUrl({ message: "relatedStories entries must have a valid url" }),
|
|
917
|
+
sourceName: z.string().optional(),
|
|
918
|
+
imageUrl: safeMediaUrl({
|
|
919
|
+
message: "relatedStories entries must have a valid imageUrl"
|
|
920
|
+
}),
|
|
921
|
+
date: z.string().optional()
|
|
922
|
+
},
|
|
923
|
+
{ message: "relatedStories entries must have title, url, and imageUrl" }
|
|
924
|
+
);
|
|
925
|
+
var shopOfferSchema2 = z.object(
|
|
926
|
+
{
|
|
927
|
+
title: z.string().optional(),
|
|
928
|
+
price: z.string().optional(),
|
|
929
|
+
source: z.string().optional(),
|
|
930
|
+
link: safeUrl({ message: "shopOffers entries must have a valid link" }),
|
|
931
|
+
imageUrl: safeMediaUrlOrEmpty("shopOffers.imageUrl must be a valid URL"),
|
|
932
|
+
delivery: z.string().optional(),
|
|
933
|
+
rating: z.number().optional(),
|
|
934
|
+
ratingCount: z.number().optional()
|
|
935
|
+
},
|
|
936
|
+
{ message: "shopOffers entries must be objects with a link" }
|
|
937
|
+
);
|
|
938
|
+
var shoplistSchema = z.object({
|
|
939
|
+
category: z.string(),
|
|
940
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
941
|
+
subtitle: z.string(),
|
|
942
|
+
shortDescription: z.string().optional(),
|
|
943
|
+
shopOffers: z.array(shopOfferSchema2).optional(),
|
|
944
|
+
sources: z.array(sourceSchema).optional(),
|
|
945
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
946
|
+
});
|
|
947
|
+
var newsItemSchema = z.object(
|
|
948
|
+
{
|
|
949
|
+
title: z.string().min(1, {
|
|
950
|
+
message: "news entries must have a non-empty title"
|
|
951
|
+
}),
|
|
952
|
+
url: safeUrl({ message: "news entries must have a valid url" }),
|
|
953
|
+
source: z.string().optional(),
|
|
954
|
+
date: z.string().optional(),
|
|
955
|
+
snippet: z.string().optional()
|
|
956
|
+
},
|
|
957
|
+
{ message: "news entries must be objects with title and url" }
|
|
958
|
+
);
|
|
959
|
+
var fundamentalsSchema = z.object({
|
|
960
|
+
name: z.string().optional(),
|
|
961
|
+
sector: z.string().optional(),
|
|
962
|
+
industry: z.string().optional(),
|
|
963
|
+
marketCap: z.union([z.number(), z.string()]).optional(),
|
|
964
|
+
peRatio: z.union([z.number(), z.string()]).optional(),
|
|
965
|
+
revenue: z.union([z.number(), z.string()]).optional(),
|
|
966
|
+
profitMargin: z.union([z.number(), z.string()]).optional()
|
|
967
|
+
});
|
|
968
|
+
var stockmarketItemSchema = z.object({
|
|
969
|
+
category: z.string(),
|
|
970
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
971
|
+
subtitle: z.string(),
|
|
972
|
+
shortDescription: z.string(),
|
|
973
|
+
// Quote
|
|
974
|
+
currentPrice: z.number().optional(),
|
|
975
|
+
change: z.number().optional(),
|
|
976
|
+
changeP: z.number().optional(),
|
|
977
|
+
// Recommendation
|
|
978
|
+
recommendation: z.string().optional(),
|
|
979
|
+
recommendationReasoning: z.string().optional(),
|
|
980
|
+
// Stats / context
|
|
981
|
+
keyPoints: z.array(createTextItemSchema("keyPoints")).optional(),
|
|
982
|
+
fundamentals: fundamentalsSchema.optional(),
|
|
983
|
+
// News + attribution
|
|
984
|
+
news: z.array(newsItemSchema).optional(),
|
|
985
|
+
sources: z.array(sourceSchema).optional(),
|
|
986
|
+
internationalCoverage: internationalCoverageSchema.optional(),
|
|
987
|
+
// Chart overlays
|
|
988
|
+
referenceLines: z.array(referenceLineSchema).optional(),
|
|
989
|
+
markers: z.array(markerSchema).optional(),
|
|
990
|
+
// Videos
|
|
991
|
+
videoGalleryTitle: z.string().optional(),
|
|
992
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional()
|
|
993
|
+
});
|
|
994
|
+
var listItemSchema = z.object(
|
|
995
|
+
{
|
|
996
|
+
name: z.string().min(1, {
|
|
997
|
+
message: "items entries must have a non-empty name"
|
|
998
|
+
}),
|
|
999
|
+
ticker: z.string().min(1, {
|
|
1000
|
+
message: "items entries must have a non-empty ticker"
|
|
1001
|
+
}),
|
|
1002
|
+
price: z.number().optional(),
|
|
1003
|
+
change: z.number().optional(),
|
|
1004
|
+
changeP: z.number().optional()
|
|
1005
|
+
},
|
|
1006
|
+
{ message: "items entries must be objects with name and ticker" }
|
|
1007
|
+
);
|
|
1008
|
+
var stockmarketListSchema = z.object({
|
|
1009
|
+
category: z.string(),
|
|
1010
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
1011
|
+
subtitle: z.string(),
|
|
1012
|
+
summary: z.string(),
|
|
1013
|
+
items: z.array(listItemSchema).optional(),
|
|
1014
|
+
sources: z.array(sourceSchema).optional(),
|
|
1015
|
+
internationalCoverage: internationalCoverageSchema.optional(),
|
|
1016
|
+
// Chart overlays
|
|
1017
|
+
referenceLines: z.array(referenceLineSchema).optional(),
|
|
1018
|
+
markers: z.array(markerSchema).optional(),
|
|
1019
|
+
// Videos
|
|
1020
|
+
videoGalleryTitle: z.string().optional(),
|
|
1021
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional()
|
|
1022
|
+
});
|
|
1023
|
+
var keyFindingSchema4 = createTextItemSchema("keyFindings");
|
|
1024
|
+
var summarySchema = z.object({
|
|
1025
|
+
category: z.string(),
|
|
1026
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
1027
|
+
subtitle: z.string(),
|
|
1028
|
+
summary: z.string(),
|
|
1029
|
+
keyFindings: z.array(keyFindingSchema4).optional(),
|
|
1030
|
+
sources: z.array(sourceSchema).optional(),
|
|
1031
|
+
// Media from online research
|
|
1032
|
+
heroImageUrl: safeMediaUrlOrEmpty(),
|
|
1033
|
+
heroImageAlt: z.string().optional(),
|
|
1034
|
+
heroCaption: z.string().optional(),
|
|
1035
|
+
heroVideoUrl: safeVideoUrlOrEmpty(),
|
|
1036
|
+
heroVideoTitle: z.string().optional(),
|
|
1037
|
+
heroVideoCaption: z.string().optional(),
|
|
1038
|
+
galleryTitle: z.string().optional(),
|
|
1039
|
+
galleryItems: z.array(galleryItemSchema).optional(),
|
|
1040
|
+
videoGalleryTitle: z.string().optional(),
|
|
1041
|
+
videoGalleryItems: z.array(videoGalleryItemSchema).optional(),
|
|
1042
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
1043
|
+
}).refine(heroVideoHasTitle, HERO_VIDEO_TITLE_ISSUE);
|
|
1044
|
+
var videolistSchema = z.object({
|
|
1045
|
+
category: z.string(),
|
|
1046
|
+
title: z.string().min(1, { message: "title must not be empty" }),
|
|
1047
|
+
subtitle: z.string(),
|
|
1048
|
+
videoGalleryItems: z.array(videoGalleryItemSchema),
|
|
1049
|
+
internationalCoverage: internationalCoverageSchema.optional()
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
export { BLOCKED_IMAGE_HOSTS, BLOCKED_URL_HOSTS, BROWSER_TOOL_NAMES, COGNITION_LIMIT_DEFAULT, COGNITION_LIMIT_MAX, COGNITION_LIMIT_MIN, COGNITION_PURGE_BATCH, ConsolidationVerdictSchema, DEFAULT_VARIANT_ID, EPISODE_PROBE_LIMIT_DEFAULT, EPISODE_PROBE_LIMIT_MAX, EPISODE_PROBE_LIMIT_MIN, EPISODE_RECENCY_MIDPOINT_DEFAULT, EPISODE_RECENCY_MIDPOINT_MAX, EPISODE_RECENCY_MIDPOINT_MIN, EPISODE_RECENCY_SCALE_SECONDS_DEFAULT, EPISODE_RECENCY_SCALE_SECONDS_MAX, EPISODE_RECENCY_SCALE_SECONDS_MIN, EPISODE_RECENCY_WEIGHT_DEFAULT, EPISODE_RECENCY_WEIGHT_MAX, EPISODE_RECENCY_WEIGHT_MIN, EPISODE_SCORE_THRESHOLD_DEFAULT, EPISODE_SCORE_THRESHOLD_MAX, EPISODE_SCORE_THRESHOLD_MIN, EPISODE_TAGS, EPISODE_TEXT_LIMIT, ExtractionSchema, HERO_VIDEO_TITLE_ISSUE, INSIGHTS_MAX_PER_TURN, INSIGHT_TAGS, INSIGHT_TEXT_LIMIT, IntentSchema, MEMORY_TOOL_NAMES, NON_PAGE_EXTENSIONS, TOOL_DESCRIPTIONS, TOOL_NAMES, VARIANT_NAMES, cardSchema, categorizeTools, clampCognitionLimit, clampEpisodeProbeLimit, clampEpisodeRecencyMidpoint, clampEpisodeRecencyScaleSeconds, clampEpisodeRecencyWeight, clampEpisodeScoreThreshold, compareSchema, createTextItemSchema, deriveSchemaKeys, describeSchema, discardedReferenceSchema, formatZodIssues, formatZodShape, galleryItemSchema, hasBlockedImageHost, heroVideoHasTitle, imagelistSchema, internationalCoverageSchema, isAllFieldsNullWipe, isPrivateOrLocalhost, isTrustedImageUrl, isTrustedUrl, markerSchema, memoryProfileResponseSchema, mergeCognitionProfiles, normalizeInsightPath, ocrSchema, parseStoredProfile, productSchema, referenceGalleryItemSchema, referenceLineSchema, relatedStorySchema, safeMediaUrl, safeMediaUrlOrEmpty, safeUrl, safeVideoUrl, safeVideoUrlOrEmpty, shoplistSchema, sourceSchema, stockmarketItemSchema, stockmarketListSchema, summarySchema, videoGalleryItemSchema, videolistSchema };
|