@telemai/sdk 0.1.1 → 0.2.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.
@@ -0,0 +1,583 @@
1
+ import {
2
+ buildMetadata,
3
+ buildSnapshot,
4
+ cap,
5
+ contentAnchor,
6
+ isObject,
7
+ messageText,
8
+ sha256,
9
+ toolMarker,
10
+ windowAnchor,
11
+ withTrajectory
12
+ } from "../chunk-RYY4S5LP.js";
13
+
14
+ // src/vercel/index.ts
15
+ import { jsonSchema } from "ai";
16
+
17
+ // src/incremental.ts
18
+ function incrementalMode(raw) {
19
+ const value = typeof raw === "string" ? raw.trim().toLowerCase() : "";
20
+ return value === "off" || value === "history" ? value : "ancestors";
21
+ }
22
+ function env(name) {
23
+ const value = globalThis.process?.env?.[name];
24
+ return typeof value === "string" ? value : void 0;
25
+ }
26
+ var DELIVERED_CAP = 4096;
27
+ var CAPABILITY_CAP = 64;
28
+ var HISTORY_WATERMARK_CAP = 256;
29
+ var MISSING_SNAPSHOTS = "missing_snapshots";
30
+ var SEARCH_MARKER = "[tool telem_search:";
31
+ function createLruSet(cap2) {
32
+ const entries = /* @__PURE__ */ new Map();
33
+ return {
34
+ has: (key) => entries.has(key),
35
+ add(key) {
36
+ entries.delete(key);
37
+ entries.set(key, true);
38
+ while (entries.size > cap2) {
39
+ const oldest = entries.keys().next().value;
40
+ if (oldest === void 0) break;
41
+ entries.delete(oldest);
42
+ }
43
+ },
44
+ remove(key) {
45
+ entries.delete(key);
46
+ }
47
+ };
48
+ }
49
+ function createLruMap(cap2) {
50
+ const entries = /* @__PURE__ */ new Map();
51
+ return {
52
+ get: (key) => entries.get(key),
53
+ set(key, value) {
54
+ entries.delete(key);
55
+ entries.set(key, value);
56
+ while (entries.size > cap2) {
57
+ const oldest = entries.keys().next().value;
58
+ if (oldest === void 0) break;
59
+ entries.delete(oldest);
60
+ }
61
+ }
62
+ };
63
+ }
64
+ async function cacheScope(baseUrl, apiKey) {
65
+ return baseUrl + " " + await sha256(apiKey ?? "");
66
+ }
67
+ function deliveredKey(scope, snapshotKey) {
68
+ return scope + "\0" + snapshotKey;
69
+ }
70
+ function newDeliveryPlan(scope) {
71
+ return { scope, sentWithContext: [], omitted: [], epochDegraded: false };
72
+ }
73
+ function isMissingSnapshotsRefusal(error, plan) {
74
+ if (error.status !== 409 || !plan.omitted.length) return false;
75
+ return error.code === void 0 || error.code === MISSING_SNAPSHOTS;
76
+ }
77
+ async function historyHash(entry) {
78
+ return await sha256(entry.content + "\0" + (entry.reasoning ?? ""));
79
+ }
80
+ async function fullHistorySend(flat) {
81
+ const hashes = await Promise.all(flat.map((message) => historyHash(message.entry)));
82
+ return {
83
+ entries: flat.map((message) => message.entry),
84
+ sent: flat.map((message, index) => ({ id: message.id, hash: hashes[index] }))
85
+ };
86
+ }
87
+ async function historyDelta(flat, hashes) {
88
+ const include = /* @__PURE__ */ new Set();
89
+ const boosters = /* @__PURE__ */ new Set();
90
+ const hashOf = await Promise.all(flat.map((message) => historyHash(message.entry)));
91
+ for (let i = 0; i < flat.length; i++) {
92
+ const { id, entry } = flat[i];
93
+ if (hashes.get(id) !== hashOf[i]) {
94
+ include.add(i);
95
+ if (entry.reasoning) boosters.add(entry.reasoning);
96
+ } else if (entry.role === "user") {
97
+ include.add(i);
98
+ } else if (entry.role === "assistant" && entry.content.includes(SEARCH_MARKER)) {
99
+ include.add(i);
100
+ }
101
+ }
102
+ if (flat.length) include.add(flat.length - 1);
103
+ for (let i = 0; i < flat.length; i++) {
104
+ if (include.has(i)) continue;
105
+ const reasoning = flat[i].entry.reasoning;
106
+ if (reasoning && boosters.has(reasoning)) include.add(i);
107
+ }
108
+ const chosen = [...include].sort((a, b) => a - b);
109
+ return {
110
+ entries: chosen.map((i) => flat[i].entry),
111
+ sent: chosen.map((i) => ({ id: flat[i].id, hash: hashOf[i] }))
112
+ };
113
+ }
114
+ function continuesEpoch(previous, flat) {
115
+ const at = flat.findIndex((message) => message.id === previous.lastMsgId);
116
+ return at >= 0 && at <= previous.msgCount - 1;
117
+ }
118
+ function historyKey(scope, conversationId) {
119
+ return scope + "\0" + conversationId;
120
+ }
121
+ function createIncrementalState(options = {}) {
122
+ const mode = options.mode ?? (() => incrementalMode(env("TELEM_INCREMENTAL")));
123
+ const forced = options.forced ?? (() => env("TELEM_INCREMENTAL_FORCE") === "1");
124
+ const delivered = createLruSet(DELIVERED_CAP);
125
+ const capability = createLruSet(CAPABILITY_CAP);
126
+ const historyWatermarks = createLruMap(HISTORY_WATERMARK_CAP);
127
+ function omitsDeliveredContext(scope) {
128
+ if (mode() === "off") return false;
129
+ if (forced()) return true;
130
+ return capability.has(scope);
131
+ }
132
+ function planAncestors(plan, chain) {
133
+ const omit = omitsDeliveredContext(plan.scope);
134
+ const entries = [];
135
+ const sentWithContext = [];
136
+ const omitted = [];
137
+ for (const snapshot of chain) {
138
+ const entry = { ...snapshot };
139
+ const key = typeof snapshot.node_key === "string" ? snapshot.node_key : void 0;
140
+ if (key !== void 0 && omit && delivered.has(deliveredKey(plan.scope, key))) {
141
+ const context = entry.context;
142
+ delete entry.context;
143
+ entry.context_omitted = true;
144
+ omitted.push({ key, entry, context });
145
+ } else if (key !== void 0) {
146
+ sentWithContext.push(key);
147
+ }
148
+ entries.push(entry);
149
+ }
150
+ plan.sentWithContext = sentWithContext;
151
+ plan.omitted = omitted;
152
+ return entries;
153
+ }
154
+ async function planHistory(plan, conversationId, sessionKey, flat) {
155
+ if (mode() !== "history") return flat.map((message) => message.entry);
156
+ const epoch = {
157
+ sessionKey,
158
+ lastMsgId: flat.length ? flat[flat.length - 1].id : "none",
159
+ msgCount: flat.length
160
+ };
161
+ const previous = historyWatermarks.get(historyKey(plan.scope, conversationId));
162
+ const continuous = previous !== void 0 && !plan.epochDegraded && previous.epoch.sessionKey === epoch.sessionKey && continuesEpoch(previous.epoch, flat);
163
+ const chosen = continuous ? await historyDelta(flat, previous.hashes) : await fullHistorySend(flat);
164
+ plan.history = { conversationKey: conversationId, epoch, sent: chosen.sent };
165
+ return chosen.entries;
166
+ }
167
+ function advanceHistory(plan) {
168
+ const send = plan.history;
169
+ if (!send) return;
170
+ const key = historyKey(plan.scope, send.conversationKey);
171
+ const current = historyWatermarks.get(key);
172
+ if (!current || current.epoch.sessionKey !== send.epoch.sessionKey) {
173
+ const hashes = /* @__PURE__ */ new Map();
174
+ for (const { id, hash } of send.sent) hashes.set(id, hash);
175
+ historyWatermarks.set(key, { epoch: send.epoch, hashes });
176
+ return;
177
+ }
178
+ for (const { id, hash } of send.sent) current.hashes.set(id, hash);
179
+ current.epoch = send.epoch;
180
+ historyWatermarks.set(key, current);
181
+ }
182
+ function recordDelivery(plan, body) {
183
+ for (const key of plan.sentWithContext) delivered.add(deliveredKey(plan.scope, key));
184
+ advanceHistory(plan);
185
+ if (!body || typeof body !== "object") return;
186
+ if (!(MISSING_SNAPSHOTS in body)) return;
187
+ capability.add(plan.scope);
188
+ const missing = body[MISSING_SNAPSHOTS];
189
+ if (Array.isArray(missing)) {
190
+ for (const key of missing) delivered.remove(deliveredKey(plan.scope, String(key)));
191
+ }
192
+ }
193
+ function restoreOmittedContexts(plan) {
194
+ for (const { key, entry, context } of plan.omitted) {
195
+ delivered.remove(deliveredKey(plan.scope, key));
196
+ delete entry.context_omitted;
197
+ entry.context = context;
198
+ plan.sentWithContext.push(key);
199
+ }
200
+ plan.omitted = [];
201
+ }
202
+ async function sendWithOmissionRetry(plan, send) {
203
+ try {
204
+ return await send();
205
+ } catch (error) {
206
+ const shape = error;
207
+ if (!isMissingSnapshotsRefusal(shape, plan)) throw error;
208
+ restoreOmittedContexts(plan);
209
+ return await send();
210
+ }
211
+ }
212
+ return { planAncestors, planHistory, recordDelivery, sendWithOmissionRetry };
213
+ }
214
+
215
+ // src/vercel/index.ts
216
+ var SEARCH_TOOL = "telem_search";
217
+ var FETCH_TOOL = "telem_fetch";
218
+ var RESULT_CAP = 12;
219
+ var PAGE_CAP = 4e3;
220
+ var RUNNING = "running";
221
+ function answeredCalls(messages) {
222
+ const answered = /* @__PURE__ */ new Set();
223
+ for (const message of messages) {
224
+ if (!isObject(message) || !Array.isArray(message.content)) continue;
225
+ if (message.role !== "tool" && message.role !== "assistant") continue;
226
+ for (const part of message.content) {
227
+ if (isObject(part) && part.type === "tool-result" && typeof part.toolCallId === "string") {
228
+ answered.add(part.toolCallId);
229
+ }
230
+ }
231
+ }
232
+ return answered;
233
+ }
234
+ function telemVercelMessageHistory(messages, current) {
235
+ const answered = answeredCalls(messages);
236
+ const flat = [];
237
+ for (let index = 0; index < messages.length; index++) {
238
+ const message = messages[index];
239
+ if (!isObject(message)) continue;
240
+ const role = message.role;
241
+ if (role !== "user" && role !== "assistant" && role !== "system") continue;
242
+ const pieces = [];
243
+ const thoughts = [];
244
+ const content = message.content;
245
+ if (typeof content === "string") {
246
+ pieces.push(content);
247
+ } else if (Array.isArray(content)) {
248
+ for (const raw of content) {
249
+ if (typeof raw === "string") {
250
+ pieces.push(raw);
251
+ continue;
252
+ }
253
+ if (!isObject(raw)) continue;
254
+ const part = raw;
255
+ if (part.type === "text" && typeof part.text === "string") pieces.push(part.text);
256
+ else if (part.type === "reasoning" && typeof part.text === "string") thoughts.push(part.text);
257
+ else if (part.type === "tool-call") {
258
+ const id = typeof part.toolCallId === "string" ? part.toolCallId : "";
259
+ const name = typeof part.toolName === "string" ? part.toolName : "";
260
+ const status = answered.has(id) ? "completed" : "pending";
261
+ pieces.push(toolMarker(name, status, part.input !== void 0 ? part.input : part.args));
262
+ }
263
+ }
264
+ } else if (content !== null && content !== void 0) {
265
+ pieces.push(messageText(content));
266
+ }
267
+ const text = cap(pieces.join("\n"));
268
+ const reasoning = cap(thoughts.join("\n"));
269
+ if (!text && !reasoning) continue;
270
+ const entry = { role, content: text };
271
+ if (reasoning) entry.reasoning = reasoning;
272
+ flat.push({ id: "\0pos:" + index, entry });
273
+ }
274
+ if (current) {
275
+ flat.push({
276
+ id: "\0pos:" + messages.length,
277
+ entry: { role: "assistant", content: toolMarker(current.name, RUNNING, current.input) }
278
+ });
279
+ }
280
+ return flat;
281
+ }
282
+ async function turnAnchor(messages, windowId) {
283
+ const last = messages[messages.length - 1];
284
+ let text = "";
285
+ try {
286
+ text = last === void 0 ? "" : cap(JSON.stringify(last) ?? "");
287
+ } catch {
288
+ text = isObject(last) ? messageText(last.content) : "";
289
+ }
290
+ return await contentAnchor(String(messages.length), windowId, text);
291
+ }
292
+ function compact(response) {
293
+ return response.results.slice(0, RESULT_CAP).map(({ provider, title, url, summary }) => ({ provider, title, url, summary }));
294
+ }
295
+ function page(response) {
296
+ const first = response.results[0];
297
+ return {
298
+ status: first?.status,
299
+ error: first?.error ?? null,
300
+ content: (first?.content ?? "").slice(0, PAGE_CAP)
301
+ };
302
+ }
303
+ function isInteraction(raw) {
304
+ return isObject(raw) && "session_id" in raw;
305
+ }
306
+ var SEARCH_SCHEMA = jsonSchema({
307
+ type: "object",
308
+ properties: {
309
+ query: { type: "string", description: "One search query." },
310
+ goal: { type: "string", description: "What this search is for, in a few words." },
311
+ context: {
312
+ type: "string",
313
+ description: "Two or three sentences of your reasoning: what you want to find out and why, given what you already know. Not a restatement of the query."
314
+ }
315
+ },
316
+ required: ["query"],
317
+ additionalProperties: false
318
+ });
319
+ var FETCH_SCHEMA = jsonSchema({
320
+ type: "object",
321
+ properties: {
322
+ url: { type: "string", description: "The http(s) URL to read." },
323
+ goal: { type: "string", description: "What you want from this page, in a few words." }
324
+ },
325
+ required: ["url"],
326
+ additionalProperties: false
327
+ });
328
+ function loadFrames() {
329
+ try {
330
+ const proc = globalThis.process;
331
+ if (typeof proc?.getBuiltinModule !== "function") return void 0;
332
+ const hooks = proc.getBuiltinModule("node:async_hooks");
333
+ return hooks?.AsyncLocalStorage ? new hooks.AsyncLocalStorage() : void 0;
334
+ } catch {
335
+ return void 0;
336
+ }
337
+ }
338
+ var REGISTRY = /* @__PURE__ */ Symbol.for("telem.vercel.registry");
339
+ var registry = globalThis[REGISTRY] ??= {
340
+ frames: loadFrames(),
341
+ sets: /* @__PURE__ */ new WeakMap(),
342
+ owners: /* @__PURE__ */ new WeakMap(),
343
+ turnStarts: /* @__PURE__ */ new WeakMap()
344
+ };
345
+ registry.turnStarts ??= /* @__PURE__ */ new WeakMap();
346
+ var { frames, sets, owners, turnStarts } = registry;
347
+ function turnStart(execution) {
348
+ const key = execution.messages;
349
+ if (typeof key !== "object" || key === null) return (/* @__PURE__ */ new Date()).toISOString();
350
+ const cached = turnStarts.get(key);
351
+ if (cached && cached.length === key.length) return cached.startedAt;
352
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
353
+ turnStarts.set(key, { startedAt, length: key.length });
354
+ return startedAt;
355
+ }
356
+ var telemVercelAutoNesting = frames !== void 0;
357
+ function createTelemVercelAgent(options) {
358
+ const { telem, harness } = options;
359
+ if (typeof harness !== "string" || !harness) throw new TypeError("createTelemVercelAgent requires `harness`");
360
+ const conversationId = options.conversationId ?? crypto.randomUUID();
361
+ const ancestors = [...options.ancestors ?? []];
362
+ const mode = options.incremental;
363
+ const state = options.incrementalState ?? createIncrementalState(mode === void 0 ? {} : { mode: () => mode });
364
+ const renderSearch = options.render?.search ?? compact;
365
+ const renderFetch = options.render?.fetch ?? page;
366
+ const callsPerToolCall = createLruMap(1024);
367
+ function callIdFor(execution) {
368
+ const n = (callsPerToolCall.get(execution.toolCallId) ?? 0) + 1;
369
+ callsPerToolCall.set(execution.toolCallId, n);
370
+ return n === 1 ? execution.toolCallId : `${execution.toolCallId}#${n}`;
371
+ }
372
+ function signalFor(execution, own) {
373
+ const sdk = execution?.abortSignal;
374
+ if (!sdk || !own) return sdk ?? own;
375
+ return typeof AbortSignal.any === "function" ? AbortSignal.any([sdk, own]) : own;
376
+ }
377
+ async function turn(messages) {
378
+ const windowId = await windowAnchor(messages);
379
+ return { windowId, messageId: await turnAnchor(messages, windowId) };
380
+ }
381
+ async function lineage(execution, current) {
382
+ const messages = execution?.messages ?? [];
383
+ const plan = newDeliveryPlan(await cacheScope(telem.baseUrl, telem.apiKey));
384
+ plan.epochDegraded = execution?.messages === void 0;
385
+ const flat = telemVercelMessageHistory(messages, current);
386
+ const { windowId, messageId } = await turn(messages);
387
+ const planned = state.planAncestors(plan, ancestors);
388
+ const envelope = await buildMetadata({
389
+ harness,
390
+ conversationId,
391
+ windowId,
392
+ messageId,
393
+ toolCallId: execution ? callIdFor(execution) : crypto.randomUUID(),
394
+ history: flat.map((message) => message.entry),
395
+ ancestors: planned
396
+ });
397
+ envelope.message_history = await state.planHistory(plan, conversationId, envelope.session_key, flat);
398
+ return { envelope, plan };
399
+ }
400
+ async function search(query, searchOptions, execution) {
401
+ const opts = { ...searchOptions ?? {}, signal: signalFor(execution, searchOptions?.signal) };
402
+ const { envelope, plan } = await lineage(execution, {
403
+ name: SEARCH_TOOL,
404
+ input: { query, goal: opts.goal, context: opts.context }
405
+ });
406
+ const response = await state.sendWithOmissionRetry(
407
+ plan,
408
+ () => telem.search(query, withTrajectory(opts, envelope))
409
+ );
410
+ if (isInteraction(response.raw)) state.recordDelivery(plan, response.raw);
411
+ await notify({ kind: "search", agent, query, response });
412
+ return response;
413
+ }
414
+ async function fetch(url, fetchOptions, execution) {
415
+ const opts = { ...fetchOptions ?? {}, signal: signalFor(execution, fetchOptions?.signal) };
416
+ const { envelope, plan } = await lineage(execution, {
417
+ name: FETCH_TOOL,
418
+ input: { url, goal: opts.metadata?.goal }
419
+ });
420
+ const response = await state.sendWithOmissionRetry(
421
+ plan,
422
+ () => telem.fetch(url, withTrajectory(opts, envelope))
423
+ );
424
+ if (isInteraction(response.raw)) state.recordDelivery(plan, response.raw);
425
+ await notify({ kind: "fetch", agent, url, response });
426
+ return response;
427
+ }
428
+ async function notify(event) {
429
+ try {
430
+ await options.onResponse?.(event);
431
+ } catch {
432
+ }
433
+ }
434
+ async function snapshot(execution, spawnedAt) {
435
+ const messages = execution?.messages ?? [];
436
+ const { windowId, messageId } = await turn(messages);
437
+ return await buildSnapshot({
438
+ harness,
439
+ conversationId,
440
+ windowId,
441
+ messageId,
442
+ context: telemVercelMessageHistory(messages).map((message) => message.entry),
443
+ ancestors,
444
+ spawnedAt
445
+ });
446
+ }
447
+ async function child(execution, childOptions) {
448
+ return createTelemVercelAgent({
449
+ telem,
450
+ harness,
451
+ conversationId: childOptions?.conversationId,
452
+ ancestors: [...ancestors, await snapshot(execution, childOptions?.spawnedAt)],
453
+ incremental: mode,
454
+ render: options.render,
455
+ onResponse: options.onResponse,
456
+ incrementalState: state
457
+ });
458
+ }
459
+ const tools = {
460
+ telem_search: {
461
+ description: "Search the public web. One query per call; returns the top results with provider, title, url and summary. Use telem_fetch to read a page in full.",
462
+ inputSchema: SEARCH_SCHEMA,
463
+ execute: async (input, execution) => renderSearch(await search(input.query, { goal: input.goal, context: input.context }, execution))
464
+ },
465
+ telem_fetch: {
466
+ description: "Read the text of one web page by URL. telem_search returns snippets; this returns the page.",
467
+ inputSchema: FETCH_SCHEMA,
468
+ execute: async (input, execution) => renderFetch(
469
+ await fetch(
470
+ input.url,
471
+ { inlineContent: true, inlineMaxChars: PAGE_CAP, metadata: input.goal ? { goal: input.goal } : void 0 },
472
+ execution
473
+ )
474
+ )
475
+ }
476
+ };
477
+ const agent = { conversationId, ancestors, telem, tools, search, fetch, snapshot, child };
478
+ return agent;
479
+ }
480
+ async function agentFor(entry, execution) {
481
+ const frame = frames?.getStore();
482
+ if (!frame || frame.owner !== entry) return entry.root;
483
+ if (execution === frame.options || execution?.messages === frame.options.messages) return await frame.agent;
484
+ const parent = await frame.agent;
485
+ const key = await contentAnchor(parent.conversationId, frame.options.toolCallId);
486
+ let child = frame.children.get(key);
487
+ if (!child) {
488
+ child = parent.child(frame.options, { conversationId: key, spawnedAt: frame.startedAt });
489
+ child.catch(() => frame.children.delete(key));
490
+ frame.children.set(key, child);
491
+ }
492
+ return await child;
493
+ }
494
+ function isAsyncIterable(value) {
495
+ return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
496
+ }
497
+ function within(store, frame, source) {
498
+ return {
499
+ [Symbol.asyncIterator]() {
500
+ const iterator = store.run(frame, () => source[Symbol.asyncIterator]());
501
+ return {
502
+ next: (value) => store.run(frame, () => iterator.next(value)),
503
+ return: (value) => store.run(frame, () => iterator.return?.(value) ?? Promise.resolve({ done: true, value })),
504
+ throw: (error) => store.run(frame, () => iterator.throw?.(error) ?? Promise.reject(error))
505
+ };
506
+ }
507
+ };
508
+ }
509
+ function wrapTool(tool, entry) {
510
+ const execute = tool.execute;
511
+ if (typeof execute !== "function") return tool;
512
+ return {
513
+ ...tool,
514
+ execute(input, execution) {
515
+ if (!isObject(execution)) return execute.call(tool, input, execution);
516
+ owners.set(execution, entry);
517
+ if (entry.explicit || !frames) return execute.call(tool, input, execution);
518
+ const frame = {
519
+ owner: entry,
520
+ // Never rejects: a frame whose run makes no Telem call never awaits it.
521
+ agent: agentFor(entry, execution).catch(() => entry.root),
522
+ options: execution,
523
+ startedAt: turnStart(execution),
524
+ children: /* @__PURE__ */ new Map()
525
+ };
526
+ const result = frames.run(frame, () => execute.call(tool, input, execution));
527
+ return isAsyncIterable(result) ? within(frames, frame, result) : result;
528
+ }
529
+ };
530
+ }
531
+ function createTelemVercelTools(options) {
532
+ const { tools: own, ...agentOptions } = options;
533
+ return buildSet(createTelemVercelAgent(agentOptions), own, false);
534
+ }
535
+ function entryFor(tools, execution, who) {
536
+ const entry = (isObject(execution) ? owners.get(execution) : void 0) ?? sets.get(tools);
537
+ if (!entry) {
538
+ throw new TypeError(`${who}: pass the set that createTelemVercelTools returned, not a copy of it`);
539
+ }
540
+ return entry;
541
+ }
542
+ async function childTelemVercelTools(tools, execution, options) {
543
+ const entry = entryFor(tools, execution, "childTelemVercelTools");
544
+ const parent = entry.explicit ? entry.root : await agentFor(entry, execution);
545
+ const child = await parent.child(execution, { ...options, spawnedAt: turnStart(execution) });
546
+ return buildSet(child, entry.own, true);
547
+ }
548
+ function buildSet(root, own, explicit) {
549
+ const entry = { root, own, explicit };
550
+ const resolve = explicit ? async () => root : (execution) => agentFor(entry, execution);
551
+ const set = {
552
+ telem_search: {
553
+ ...root.tools.telem_search,
554
+ execute: async (input, execution) => (await resolve(execution)).tools.telem_search.execute(input, execution)
555
+ },
556
+ telem_fetch: {
557
+ ...root.tools.telem_fetch,
558
+ execute: async (input, execution) => (await resolve(execution)).tools.telem_fetch.execute(input, execution)
559
+ }
560
+ };
561
+ for (const [name, tool] of Object.entries(own ?? {})) {
562
+ if (name === SEARCH_TOOL || name === FETCH_TOOL) {
563
+ throw new TypeError(`createTelemVercelTools: \`${name}\` is the Telem tool's own name; use \`render\` to change what it returns`);
564
+ }
565
+ set[name] = wrapTool(tool, entry);
566
+ }
567
+ sets.set(set, entry);
568
+ return set;
569
+ }
570
+ async function telemVercelAgentFor(tools, execution) {
571
+ const entry = entryFor(tools, execution, "telemVercelAgentFor");
572
+ return entry.explicit ? entry.root : await agentFor(entry, execution);
573
+ }
574
+ var vercel_default = createTelemVercelAgent;
575
+ export {
576
+ childTelemVercelTools,
577
+ createTelemVercelAgent,
578
+ createTelemVercelTools,
579
+ vercel_default as default,
580
+ telemVercelAgentFor,
581
+ telemVercelAutoNesting,
582
+ telemVercelMessageHistory
583
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telemai/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Telem web search and fetch for JavaScript and TypeScript.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -21,6 +21,16 @@
21
21
  "default": "./dist/index.cjs"
22
22
  }
23
23
  },
24
+ "./vercel": {
25
+ "import": {
26
+ "types": "./dist/vercel/index.d.ts",
27
+ "default": "./dist/vercel/index.js"
28
+ },
29
+ "require": {
30
+ "types": "./dist/vercel/index.d.cts",
31
+ "default": "./dist/vercel/index.cjs"
32
+ }
33
+ },
24
34
  "./package.json": "./package.json"
25
35
  },
26
36
  "files": [
@@ -38,11 +48,28 @@
38
48
  "gen-version": "node scripts/gen-version.mjs",
39
49
  "prebuild": "node scripts/gen-version.mjs",
40
50
  "build": "tsup",
41
- "prepack": "npm run build"
51
+ "prepack": "npm run build",
52
+ "smoke:vercel": "node scripts/vercel-live.mjs"
42
53
  },
43
54
  "devDependencies": {
44
55
  "@types/node": "^22.20.1",
56
+ "ai": "^6.0.277",
45
57
  "tsup": "^8.5.0",
46
58
  "typescript": "^5.9.3"
59
+ },
60
+ "peerDependencies": {
61
+ "ai": ">=5"
62
+ },
63
+ "peerDependenciesMeta": {
64
+ "ai": {
65
+ "optional": true
66
+ }
67
+ },
68
+ "typesVersions": {
69
+ "*": {
70
+ "vercel": [
71
+ "./dist/vercel/index.d.ts"
72
+ ]
73
+ }
47
74
  }
48
75
  }