@telemai/sdk 0.3.3 → 0.4.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/README.md CHANGED
@@ -213,10 +213,22 @@ your last poll. `poll` returns a `SearchResponse`:
213
213
  ```ts
214
214
  const monitor = await telem.monitors.create("Nvidia files a new 8-K with the SEC", { frequency: "1h", ttl: "7d" })
215
215
  const response = await telem.monitors.poll(monitor.id)
216
+ for await (const change of telem.monitors.iterateChanges(monitor.id)) {
217
+ console.log(change.seq, change.kind, change.subject.name)
218
+ }
216
219
  await telem.monitors.update(monitor.id, { status: "paused" })
217
220
  await telem.monitors.delete(monitor.id)
218
221
  ```
219
222
 
223
+ A monitor has an agent unless you create it with `agent: false`. The agent checks every
224
+ result against the query and keeps the ones that match. `iterateChanges` reads what it
225
+ kept, oldest first, until you are caught up, and then stops. Keep the `seq` of the last
226
+ change you handled and pass it as `cursor` next time: no change comes twice, and none
227
+ is skipped. `changes` returns one page (`nextCursor`, `watermark`) and takes
228
+ `cursor`, `since`, `kinds` and `limit`. `agent` returns the agent itself: its status,
229
+ query, frequency and plan version. `monitor.agentState` shows it on the monitor. Read
230
+ `iterateChanges` with `for await`.
231
+
220
232
  `telem.monitors` also has `get` and `list`. See [Monitors](https://docs.telem.ai/resources/monitors/)
221
233
  for the fields and the errors.
222
234
 
@@ -80,8 +80,10 @@ function defaultMessage(status) {
80
80
  if (status === 404) return "Not found";
81
81
  return `Unexpected status code ${status}`;
82
82
  }
83
+ var BLOCKED_MESSAGE = "The request was blocked by a firewall before it reached Telem; the text may have characters that are not allowed.";
83
84
  function statusError(status, body) {
84
- return new TelemError(detailFromBody(body) ?? defaultMessage(status), {
85
+ const fallback = status === 403 && !isObject(body) ? BLOCKED_MESSAGE : defaultMessage(status);
86
+ return new TelemError(detailFromBody(body) ?? fallback, {
85
87
  status,
86
88
  code: codeFromBody(body),
87
89
  details: body
package/dist/index.cjs CHANGED
@@ -60,7 +60,7 @@ var TimeoutError = class extends TelemError {
60
60
  };
61
61
 
62
62
  // src/version.ts
63
- var VERSION = "0.3.3";
63
+ var VERSION = "0.4.0";
64
64
 
65
65
  // src/config.ts
66
66
  var DEFAULT_BASE_URL = "https://router.telem.ai";
@@ -120,6 +120,7 @@ function resolveConfig(options) {
120
120
  if (typeof send !== "function") {
121
121
  throw invalidOption("no fetch on this runtime: pass one with the `fetch` option");
122
122
  }
123
+ if (typeof opts.apiKey === "string" && !opts.apiKey.trim()) throw invalidOption("apiKey is empty");
123
124
  let apiKey = opts.apiKey || env.TELEM_API_KEY || void 0;
124
125
  let baseUrl = opts.baseUrl || env.TELEM_BASE_URL || void 0;
125
126
  if (apiKey === void 0 || baseUrl === void 0) {
@@ -232,8 +233,10 @@ function defaultMessage(status) {
232
233
  if (status === 404) return "Not found";
233
234
  return `Unexpected status code ${status}`;
234
235
  }
236
+ var BLOCKED_MESSAGE = "The request was blocked by a firewall before it reached Telem; the text may have characters that are not allowed.";
235
237
  function statusError(status, body) {
236
- return new TelemError(detailFromBody(body) ?? defaultMessage(status), {
238
+ const fallback = status === 403 && !isObject(body) ? BLOCKED_MESSAGE : defaultMessage(status);
239
+ return new TelemError(detailFromBody(body) ?? fallback, {
237
240
  status,
238
241
  code: codeFromBody(body),
239
242
  details: body
@@ -698,7 +701,8 @@ function providerRun(run) {
698
701
  related: envelope.related ?? null,
699
702
  verticals: envelope.verticals ?? null,
700
703
  usage: envelope.usage ?? null,
701
- warnings: asArray(envelope.warnings)
704
+ warnings: asArray(envelope.warnings),
705
+ sameStory: isObject(envelope.same_story) ? envelope.same_story : null
702
706
  };
703
707
  }
704
708
  function buildSearchResponse(interaction) {
@@ -722,9 +726,25 @@ async function search(config, query, options) {
722
726
  }
723
727
 
724
728
  // src/methods/monitors.ts
729
+ function agentStateFrom(data) {
730
+ return {
731
+ engine: String(data.engine ?? ""),
732
+ status: String(data.status ?? ""),
733
+ needsAttention: data.needs_attention === true,
734
+ planVersion: typeof data.plan_version === "number" ? data.plan_version : null,
735
+ nextRunAt: typeof data.next_run_at === "string" ? data.next_run_at : null,
736
+ watermark: Number(data.watermark ?? 0),
737
+ // No compile job yet is null, not an object of empty strings.
738
+ compile: isObject(data.compile) ? {
739
+ jobId: String(data.compile.job_id ?? ""),
740
+ status: String(data.compile.status ?? ""),
741
+ error: typeof data.compile.error === "string" ? data.compile.error : null
742
+ } : null
743
+ };
744
+ }
725
745
  function monitorFrom(body) {
726
746
  const data = asObject(body);
727
- return {
747
+ const monitor = {
728
748
  id: String(data.id ?? ""),
729
749
  query: data.query ?? "",
730
750
  frequency: data.frequency ?? "",
@@ -737,12 +757,85 @@ function monitorFrom(body) {
737
757
  webhookSecret: data.webhook_secret ?? null,
738
758
  raw: data
739
759
  };
760
+ if (data.agent_state !== void 0) {
761
+ monitor.agentState = isObject(data.agent_state) ? agentStateFrom(data.agent_state) : null;
762
+ }
763
+ return monitor;
764
+ }
765
+ function agentDocumentFrom(body) {
766
+ const data = asObject(body);
767
+ const document = { raw: data };
768
+ if (typeof data.status === "string") document.status = data.status;
769
+ if (typeof data.query === "string") document.query = data.query;
770
+ if (typeof data.frequency === "string") document.frequency = data.frequency;
771
+ if (typeof data.spec_version === "number") document.specVersion = data.spec_version;
772
+ if (data.budget !== void 0) document.budget = isObject(data.budget) ? data.budget : null;
773
+ if (typeof data.spend_usd === "number") document.spendUsd = data.spend_usd;
774
+ return document;
775
+ }
776
+ function changeRecordFrom(entry) {
777
+ const subject = asObject(entry.subject);
778
+ return {
779
+ seq: Number(entry.seq ?? 0),
780
+ type: String(entry.type ?? ""),
781
+ kind: String(entry.kind ?? ""),
782
+ monitorId: String(entry.monitor_id ?? ""),
783
+ subject: {
784
+ entityId: typeof subject.entity_id === "string" ? subject.entity_id : null,
785
+ name: typeof subject.name === "string" ? subject.name : null
786
+ },
787
+ // The values depend on the kind (an object, a status string, nothing): as sent.
788
+ before: entry.before ?? null,
789
+ after: entry.after ?? null,
790
+ factIds: asArray(entry.fact_ids).map(String),
791
+ at: String(entry.at ?? ""),
792
+ raw: entry
793
+ };
794
+ }
795
+ function changesPageFrom(body) {
796
+ const data = asObject(body);
797
+ return {
798
+ changes: asArray(data.changes).filter(isObject).map(changeRecordFrom),
799
+ nextCursor: Number(data.next_cursor ?? 0),
800
+ watermark: Number(data.watermark ?? 0)
801
+ };
802
+ }
803
+ function listQuery(options) {
804
+ const params = new URLSearchParams();
805
+ if (options.limit !== void 0) params.set("limit", String(options.limit));
806
+ if (options.cursor !== void 0) params.set("cursor", options.cursor);
807
+ const query = params.toString();
808
+ return query ? `?${query}` : "";
809
+ }
810
+ function sinceParam(since) {
811
+ if (typeof since === "string") return since;
812
+ if (Number.isNaN(since.getTime())) throw invalidRequest("since is not a valid date");
813
+ return since.toISOString();
814
+ }
815
+ function changesQuery(options) {
816
+ const params = new URLSearchParams();
817
+ if (options.cursor !== void 0) params.set("cursor", String(options.cursor));
818
+ if (options.since !== void 0) params.set("since", sinceParam(options.since));
819
+ if (options.kinds !== void 0) params.set("kinds", options.kinds.join(","));
820
+ if (options.limit !== void 0) params.set("limit", String(options.limit));
821
+ const query = params.toString();
822
+ return query ? `?${query}` : "";
740
823
  }
741
824
  function createMonitors(config) {
742
825
  const path = (monitorId, suffix = "") => {
743
826
  if (!monitorId || /^\.+$/.test(monitorId)) throw invalidRequest("a monitor id is required");
744
827
  return `/v1/monitors/${encodeURIComponent(monitorId)}${suffix}`;
745
828
  };
829
+ const listPage = async (options = {}) => {
830
+ const route = `/v1/monitors${listQuery(options)}`;
831
+ const data = asObject(await request(config, "GET", route, void 0, options.signal));
832
+ const nextCursor = typeof data.next_cursor === "string" ? data.next_cursor : null;
833
+ return { monitors: asArray(data.monitors).map(monitorFrom), nextCursor };
834
+ };
835
+ const changes = async (monitorId, options = {}) => {
836
+ const route = `${path(monitorId, "/agent/changes")}${changesQuery(options)}`;
837
+ return changesPageFrom(await request(config, "GET", route, void 0, options.signal));
838
+ };
746
839
  return {
747
840
  /** Create a monitor. Telem runs `query` on the schedule. */
748
841
  async create(query, options = {}) {
@@ -756,15 +849,25 @@ function createMonitors(config) {
756
849
  if (options.metadata !== void 0) body.metadata = options.metadata;
757
850
  if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl;
758
851
  if (options.ttl !== void 0) body.ttl = options.ttl;
759
- const data = await request(config, "POST", "/v1/monitors", body, options.signal, "rate_limit");
852
+ if (options.agent !== void 0) body.agent = options.agent;
853
+ const data = await request(config, "POST", "/v1/monitors", body, options.signal, "rate_limit").catch(
854
+ (error) => {
855
+ if (error instanceof TimeoutError) {
856
+ throw new TimeoutError(
857
+ `${error.message}. The monitor may exist: list monitors before you create it again.`,
858
+ error.cause
859
+ );
860
+ }
861
+ throw error;
862
+ }
863
+ );
760
864
  return monitorFrom(data);
761
865
  },
762
- /** List your monitors, newest first (server default 50, maximum 200). */
866
+ /** List your monitors, newest first. `listPage` also gives the next cursor. */
763
867
  async list(options = {}) {
764
- const query = options.limit === void 0 ? "" : `?limit=${options.limit}`;
765
- const body = await request(config, "GET", `/v1/monitors${query}`, void 0, options.signal);
766
- return asArray(asObject(body).monitors).map(monitorFrom);
868
+ return (await listPage(options)).monitors;
767
869
  },
870
+ listPage,
768
871
  /** Get one monitor. */
769
872
  async get(monitorId, options = {}) {
770
873
  return monitorFrom(await request(config, "GET", path(monitorId), void 0, options.signal));
@@ -774,7 +877,7 @@ function createMonitors(config) {
774
877
  const body = {};
775
878
  if (options.status !== void 0) body.status = options.status;
776
879
  if (options.frequency !== void 0) body.frequency = options.frequency;
777
- if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl;
880
+ if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl || null;
778
881
  const route = path(monitorId);
779
882
  return monitorFrom(await request(config, "PATCH", route, body, options.signal));
780
883
  },
@@ -790,6 +893,23 @@ function createMonitors(config) {
790
893
  /** Delete a monitor. A repeat deletes what a failed delete left. */
791
894
  async delete(monitorId, options = {}) {
792
895
  await request(config, "DELETE", path(monitorId), void 0, options.signal);
896
+ },
897
+ /** Read the monitor agent's document. A monitor without an agent answers 404. */
898
+ async agent(monitorId, options = {}) {
899
+ const route = path(monitorId, "/agent");
900
+ return agentDocumentFrom(await request(config, "GET", route, void 0, options.signal));
901
+ },
902
+ /** One page of the agent's changes. Keep `nextCursor` and pass it back as `cursor`. */
903
+ changes,
904
+ /** Every change after `cursor`, page by page, until you are caught up. */
905
+ async *iterateChanges(monitorId, options = {}) {
906
+ let cursor = options.cursor ?? 0;
907
+ for (; ; ) {
908
+ const page = await changes(monitorId, { cursor, signal: options.signal });
909
+ for (const change of page.changes) yield change;
910
+ if (!page.changes.length || page.nextCursor <= cursor || page.nextCursor >= page.watermark) return;
911
+ cursor = page.nextCursor;
912
+ }
793
913
  }
794
914
  };
795
915
  }
@@ -892,7 +1012,8 @@ var Telem = class {
892
1012
  maxRetries;
893
1013
  /** The session read surface: `list` and `results(id)`. */
894
1014
  sessions;
895
- /** Monitors: `create`, `list`, `get`, `update`, `poll`, `delete`. */
1015
+ /** Monitors: `create`, `list`, `listPage`, `get`, `update`, `poll`, `delete`, and the
1016
+ * agent reads `agent`, `changes` and `iterateChanges`. */
896
1017
  monitors;
897
1018
  #config;
898
1019
  /**
package/dist/index.d.cts CHANGED
@@ -157,6 +157,8 @@ type ProviderRun = {
157
157
  verticals: Json | null;
158
158
  usage: Json | unknown[] | null;
159
159
  warnings: Json[];
160
+ /** Monitor polls: results folded as the same story, `{leadUrl: [{url, title}]}`. */
161
+ sameStory: Record<string, Json[]> | null;
160
162
  raw: Json | null;
161
163
  };
162
164
  type SearchResponse = {
@@ -207,7 +209,7 @@ type ProviderInfo = {
207
209
  url: string | null;
208
210
  normalized: boolean;
209
211
  tiers: string[];
210
- /** Whether auto-routing can pick it for a ranked topic; `null` from a router that does not say. */
212
+ /** Whether auto-routing can pick it; `null` from a router that does not say. */
211
213
  autoRouted: boolean | null;
212
214
  };
213
215
  /** One session as `sessions.list` reports it. */
@@ -252,6 +254,10 @@ type MonitorCreateOptions = {
252
254
  webhookUrl?: string;
253
255
  /** Delete the monitor after this long, such as `"12h"` or `"7d"` (at most `"30d"`). Without it, the monitor never expires. */
254
256
  ttl?: string;
257
+ /** Start the monitor agent with the monitor: it checks every result against the query
258
+ * and keeps the ones that match. Telem turns it on when you leave this out; `false`
259
+ * creates the monitor without one. Read what the agent keeps with `monitors.changes`. */
260
+ agent?: boolean;
255
261
  signal?: AbortSignal;
256
262
  };
257
263
  /** Options for `monitors.update`. Send at least one field. */
@@ -259,7 +265,7 @@ type MonitorUpdateOptions = {
259
265
  /** `"paused"` or `"active"`. */
260
266
  status?: string;
261
267
  frequency?: string;
262
- /** A new webhook URL, with a new `webhookSecret` in the response. `null` removes it. */
268
+ /** A new webhook URL, with a new `webhookSecret` in the response. `null` or `""` removes it. */
263
269
  webhookUrl?: string | null;
264
270
  signal?: AbortSignal;
265
271
  };
@@ -276,25 +282,144 @@ type Monitor = {
276
282
  id: string;
277
283
  query: string;
278
284
  frequency: string;
279
- /** `active` or `paused` (you paused it). */
285
+ /** `active`, `paused` (you paused it) or `ended` (past `expiresAt`). */
280
286
  status: string;
281
287
  sessionId: string;
282
288
  createdAt: string;
283
289
  lastPolledAt: string | null;
284
- /** When Telem deletes the monitor; `null`: never. */
290
+ /** When the monitor ends; `null`: never. */
285
291
  expiresAt: string | null;
286
292
  webhookUrl: string | null;
287
293
  /** Signs the webhook deliveries. Only in the response that set `webhookUrl`. */
288
294
  webhookSecret: string | null;
295
+ /** The monitor agent's state. `null`: the monitor has no agent. Absent when the router
296
+ * sends none, as a router from before the agent reads does. */
297
+ agentState?: AgentState | null;
289
298
  raw: Json;
290
299
  };
300
+ /** The latest compile of an agent's plan (`AgentState.compile`). */
301
+ type AgentCompileState = {
302
+ jobId: string;
303
+ /** The compile job's status, such as `done` or `failed`. */
304
+ status: string;
305
+ /** Why the compile failed; `null` when it did not. */
306
+ error: string | null;
307
+ };
308
+ /** The state of a monitor's agent: `monitor.agentState`. */
309
+ type AgentState = {
310
+ /** The agent engine, `"v4"` today. */
311
+ engine: string;
312
+ /** Such as `compiling`, `ready`, `paused` or `failed`. */
313
+ status: string;
314
+ /** `true` when `status` is `failed`. */
315
+ needsAttention: boolean;
316
+ /** The version of the agent's plan; `null` before it has one. */
317
+ planVersion: number | null;
318
+ /** When the agent runs next; `null` when no run is scheduled. */
319
+ nextRunAt: string | null;
320
+ /** The `seq` of the newest change `monitors.changes` can serve now. */
321
+ watermark: number;
322
+ /** The latest compile of the plan; `null` when there has been none. */
323
+ compile: AgentCompileState | null;
324
+ };
325
+ /** The monitor agent's document: `monitors.agent`. A field is there only when the
326
+ * router sent it. The rest of the document (the plan, the counts, the runs) is in `raw`. */
327
+ type AgentDocument = {
328
+ /** Such as `compiling`, `ready`, `paused`, `failed` or `ended`. */
329
+ status?: string;
330
+ query?: string;
331
+ frequency?: string;
332
+ /** The version of the plan; 0 while the agent compiles. */
333
+ specVersion?: number;
334
+ /** The agent's spending limits; `null` when none are set. */
335
+ budget?: Json | null;
336
+ /** What the agent has spent, in US dollars. */
337
+ spendUsd?: number;
338
+ raw: Json;
339
+ };
340
+ /** The item a change is about. `entityId` is `null` for a change to the whole monitor,
341
+ * such as a run or a plan change. */
342
+ type ChangeSubject = {
343
+ entityId: string | null;
344
+ name: string | null;
345
+ };
346
+ /** One change the monitor agent made. */
347
+ type ChangeRecord = {
348
+ /** The change's place in the stream. It grows with every change and is never reused.
349
+ * Pass the last one you handled as `cursor` to read on from there. */
350
+ seq: number;
351
+ /** The change's own type, such as `new_object`. */
352
+ type: string;
353
+ /** What happened: one of the six kinds `entity_added`, `value_changed`,
354
+ * `fact_status_changed`, `alert`, `run` or `plan_changed`. */
355
+ kind: string;
356
+ monitorId: string;
357
+ subject: ChangeSubject;
358
+ /** What it was before, as the router sent it; `null` when there is no before. Its shape
359
+ * depends on `kind`. */
360
+ before: unknown;
361
+ /** What it is now, as the router sent it. */
362
+ after: unknown;
363
+ /** The facts behind the change; empty when the router names none. */
364
+ factIds: string[];
365
+ /** When it happened, ISO 8601. */
366
+ at: string;
367
+ raw: Json;
368
+ };
369
+ /** One page of `monitors.changes`. */
370
+ type ChangesPage = {
371
+ changes: ChangeRecord[];
372
+ /** Keep this and pass it as `cursor` to read the changes after this page. On a full
373
+ * page (`limit` changes) it is the `seq` of the last change. On a shorter page, an
374
+ * empty one included, it is `watermark`: the read got that far, past the changes
375
+ * that `kinds` left out too. */
376
+ nextCursor: number;
377
+ /** The `seq` of the newest change that can be read now. You are caught up when
378
+ * `nextCursor` equals it, or when a page is empty. */
379
+ watermark: number;
380
+ };
381
+ /** Options for `monitors.changes`. */
382
+ type MonitorChangesOptions = {
383
+ /** Read the changes after this `seq`. If you leave it out, the page starts at the
384
+ * first change. Do not send it with `since`. */
385
+ cursor?: number;
386
+ /** Read from this time on: a `Date`, or an ISO 8601 time with an offset such as
387
+ * `"2026-11-03T12:00:00Z"`. Do not send it with `cursor`. */
388
+ since?: string | Date;
389
+ /** Only these kinds of change: `entity_added`, `value_changed`, `fact_status_changed`,
390
+ * `alert`, `run` or `plan_changed`, for example `["alert", "run"]`. Another name is a
391
+ * 400 (`kinds_invalid`). An empty list is no filter. */
392
+ kinds?: string[];
393
+ /** How many changes to return (server default 200, maximum 500). */
394
+ limit?: number;
395
+ signal?: AbortSignal;
396
+ };
397
+ /** Options for `monitors.iterateChanges`. */
398
+ type MonitorIterateChangesOptions = {
399
+ /** Read the changes after this `seq`. If you leave it out, the walk starts at the
400
+ * first change. */
401
+ cursor?: number;
402
+ signal?: AbortSignal;
403
+ };
404
+ /** Options for `monitors.list` and `monitors.listPage`. */
405
+ type MonitorListOptions = {
406
+ /** How many to return (server default 50, maximum 200). */
407
+ limit?: number;
408
+ /** The `nextCursor` of the page before. */
409
+ cursor?: string;
410
+ signal?: AbortSignal;
411
+ };
412
+ /** One page of `monitors.listPage`. */
413
+ type MonitorPage = {
414
+ monitors: Monitor[];
415
+ /** Pass as `cursor` to get the next page; `null` on the last page. */
416
+ nextCursor: string | null;
417
+ };
291
418
  /** The `telem.monitors` namespace. */
292
419
  type MonitorsResource = {
293
420
  create(query: string, options?: MonitorCreateOptions): Promise<Monitor>;
294
- list(options?: {
295
- limit?: number;
296
- signal?: AbortSignal;
297
- }): Promise<Monitor[]>;
421
+ list(options?: MonitorListOptions): Promise<Monitor[]>;
422
+ listPage(options?: MonitorListOptions): Promise<MonitorPage>;
298
423
  get(monitorId: string, options?: {
299
424
  signal?: AbortSignal;
300
425
  }): Promise<Monitor>;
@@ -303,6 +428,14 @@ type MonitorsResource = {
303
428
  delete(monitorId: string, options?: {
304
429
  signal?: AbortSignal;
305
430
  }): Promise<void>;
431
+ /** Read the monitor agent's document. A monitor without an agent answers 404. */
432
+ agent(monitorId: string, options?: {
433
+ signal?: AbortSignal;
434
+ }): Promise<AgentDocument>;
435
+ /** One page of the agent's changes. Keep `nextCursor` and pass it back as `cursor`. */
436
+ changes(monitorId: string, options?: MonitorChangesOptions): Promise<ChangesPage>;
437
+ /** Every change after `cursor`, page by page, until you are caught up. */
438
+ iterateChanges(monitorId: string, options?: MonitorIterateChangesOptions): AsyncGenerator<ChangeRecord, void, undefined>;
306
439
  };
307
440
 
308
441
  /**
@@ -446,7 +579,8 @@ declare class Telem {
446
579
  readonly maxRetries: number;
447
580
  /** The session read surface: `list` and `results(id)`. */
448
581
  readonly sessions: SessionsResource;
449
- /** Monitors: `create`, `list`, `get`, `update`, `poll`, `delete`. */
582
+ /** Monitors: `create`, `list`, `listPage`, `get`, `update`, `poll`, `delete`, and the
583
+ * agent reads `agent`, `changes` and `iterateChanges`. */
450
584
  readonly monitors: MonitorsResource;
451
585
  /**
452
586
  * @param options - An API key string, or an options object. Anything left unset
@@ -479,4 +613,4 @@ declare class Telem {
479
613
  providers(): Promise<ProviderInfo[]>;
480
614
  }
481
615
 
482
- export { type FetchOptions, type FetchResponse, type FetchResult, type Json, type Monitor, type MonitorCreateOptions, type MonitorPollOptions, type MonitorUpdateOptions, type MonitorsResource, type ProviderInfo, type ProviderRun, RESERVED_METADATA, type SearchDefaults, type SearchOptions, type SearchResponse, type SearchResult, type SessionResults, type SessionSummary, type SessionsResource, type SnapshotArgs, Telem, type TelemClientErrorCode, TelemError, type TelemErrorOptions, type TelemOptions, TimeoutError, type TrajectoryArgs, type TrajectoryEnvelope, type TrajectorySnapshot, buildMetadata, buildSnapshot, contentAnchor, Telem as default, eventNodeKey, fingerprint, sessionKey, snapshotNodeKey, toolMarker, verifyWebhook, windowAnchor, withTrajectory };
616
+ export { type AgentCompileState, type AgentDocument, type AgentState, type ChangeRecord, type ChangeSubject, type ChangesPage, type FetchOptions, type FetchResponse, type FetchResult, type Json, type Monitor, type MonitorChangesOptions, type MonitorCreateOptions, type MonitorIterateChangesOptions, type MonitorListOptions, type MonitorPage, type MonitorPollOptions, type MonitorUpdateOptions, type MonitorsResource, type ProviderInfo, type ProviderRun, RESERVED_METADATA, type SearchDefaults, type SearchOptions, type SearchResponse, type SearchResult, type SessionResults, type SessionSummary, type SessionsResource, type SnapshotArgs, Telem, type TelemClientErrorCode, TelemError, type TelemErrorOptions, type TelemOptions, TimeoutError, type TrajectoryArgs, type TrajectoryEnvelope, type TrajectorySnapshot, buildMetadata, buildSnapshot, contentAnchor, Telem as default, eventNodeKey, fingerprint, sessionKey, snapshotNodeKey, toolMarker, verifyWebhook, windowAnchor, withTrajectory };
package/dist/index.d.ts CHANGED
@@ -157,6 +157,8 @@ type ProviderRun = {
157
157
  verticals: Json | null;
158
158
  usage: Json | unknown[] | null;
159
159
  warnings: Json[];
160
+ /** Monitor polls: results folded as the same story, `{leadUrl: [{url, title}]}`. */
161
+ sameStory: Record<string, Json[]> | null;
160
162
  raw: Json | null;
161
163
  };
162
164
  type SearchResponse = {
@@ -207,7 +209,7 @@ type ProviderInfo = {
207
209
  url: string | null;
208
210
  normalized: boolean;
209
211
  tiers: string[];
210
- /** Whether auto-routing can pick it for a ranked topic; `null` from a router that does not say. */
212
+ /** Whether auto-routing can pick it; `null` from a router that does not say. */
211
213
  autoRouted: boolean | null;
212
214
  };
213
215
  /** One session as `sessions.list` reports it. */
@@ -252,6 +254,10 @@ type MonitorCreateOptions = {
252
254
  webhookUrl?: string;
253
255
  /** Delete the monitor after this long, such as `"12h"` or `"7d"` (at most `"30d"`). Without it, the monitor never expires. */
254
256
  ttl?: string;
257
+ /** Start the monitor agent with the monitor: it checks every result against the query
258
+ * and keeps the ones that match. Telem turns it on when you leave this out; `false`
259
+ * creates the monitor without one. Read what the agent keeps with `monitors.changes`. */
260
+ agent?: boolean;
255
261
  signal?: AbortSignal;
256
262
  };
257
263
  /** Options for `monitors.update`. Send at least one field. */
@@ -259,7 +265,7 @@ type MonitorUpdateOptions = {
259
265
  /** `"paused"` or `"active"`. */
260
266
  status?: string;
261
267
  frequency?: string;
262
- /** A new webhook URL, with a new `webhookSecret` in the response. `null` removes it. */
268
+ /** A new webhook URL, with a new `webhookSecret` in the response. `null` or `""` removes it. */
263
269
  webhookUrl?: string | null;
264
270
  signal?: AbortSignal;
265
271
  };
@@ -276,25 +282,144 @@ type Monitor = {
276
282
  id: string;
277
283
  query: string;
278
284
  frequency: string;
279
- /** `active` or `paused` (you paused it). */
285
+ /** `active`, `paused` (you paused it) or `ended` (past `expiresAt`). */
280
286
  status: string;
281
287
  sessionId: string;
282
288
  createdAt: string;
283
289
  lastPolledAt: string | null;
284
- /** When Telem deletes the monitor; `null`: never. */
290
+ /** When the monitor ends; `null`: never. */
285
291
  expiresAt: string | null;
286
292
  webhookUrl: string | null;
287
293
  /** Signs the webhook deliveries. Only in the response that set `webhookUrl`. */
288
294
  webhookSecret: string | null;
295
+ /** The monitor agent's state. `null`: the monitor has no agent. Absent when the router
296
+ * sends none, as a router from before the agent reads does. */
297
+ agentState?: AgentState | null;
289
298
  raw: Json;
290
299
  };
300
+ /** The latest compile of an agent's plan (`AgentState.compile`). */
301
+ type AgentCompileState = {
302
+ jobId: string;
303
+ /** The compile job's status, such as `done` or `failed`. */
304
+ status: string;
305
+ /** Why the compile failed; `null` when it did not. */
306
+ error: string | null;
307
+ };
308
+ /** The state of a monitor's agent: `monitor.agentState`. */
309
+ type AgentState = {
310
+ /** The agent engine, `"v4"` today. */
311
+ engine: string;
312
+ /** Such as `compiling`, `ready`, `paused` or `failed`. */
313
+ status: string;
314
+ /** `true` when `status` is `failed`. */
315
+ needsAttention: boolean;
316
+ /** The version of the agent's plan; `null` before it has one. */
317
+ planVersion: number | null;
318
+ /** When the agent runs next; `null` when no run is scheduled. */
319
+ nextRunAt: string | null;
320
+ /** The `seq` of the newest change `monitors.changes` can serve now. */
321
+ watermark: number;
322
+ /** The latest compile of the plan; `null` when there has been none. */
323
+ compile: AgentCompileState | null;
324
+ };
325
+ /** The monitor agent's document: `monitors.agent`. A field is there only when the
326
+ * router sent it. The rest of the document (the plan, the counts, the runs) is in `raw`. */
327
+ type AgentDocument = {
328
+ /** Such as `compiling`, `ready`, `paused`, `failed` or `ended`. */
329
+ status?: string;
330
+ query?: string;
331
+ frequency?: string;
332
+ /** The version of the plan; 0 while the agent compiles. */
333
+ specVersion?: number;
334
+ /** The agent's spending limits; `null` when none are set. */
335
+ budget?: Json | null;
336
+ /** What the agent has spent, in US dollars. */
337
+ spendUsd?: number;
338
+ raw: Json;
339
+ };
340
+ /** The item a change is about. `entityId` is `null` for a change to the whole monitor,
341
+ * such as a run or a plan change. */
342
+ type ChangeSubject = {
343
+ entityId: string | null;
344
+ name: string | null;
345
+ };
346
+ /** One change the monitor agent made. */
347
+ type ChangeRecord = {
348
+ /** The change's place in the stream. It grows with every change and is never reused.
349
+ * Pass the last one you handled as `cursor` to read on from there. */
350
+ seq: number;
351
+ /** The change's own type, such as `new_object`. */
352
+ type: string;
353
+ /** What happened: one of the six kinds `entity_added`, `value_changed`,
354
+ * `fact_status_changed`, `alert`, `run` or `plan_changed`. */
355
+ kind: string;
356
+ monitorId: string;
357
+ subject: ChangeSubject;
358
+ /** What it was before, as the router sent it; `null` when there is no before. Its shape
359
+ * depends on `kind`. */
360
+ before: unknown;
361
+ /** What it is now, as the router sent it. */
362
+ after: unknown;
363
+ /** The facts behind the change; empty when the router names none. */
364
+ factIds: string[];
365
+ /** When it happened, ISO 8601. */
366
+ at: string;
367
+ raw: Json;
368
+ };
369
+ /** One page of `monitors.changes`. */
370
+ type ChangesPage = {
371
+ changes: ChangeRecord[];
372
+ /** Keep this and pass it as `cursor` to read the changes after this page. On a full
373
+ * page (`limit` changes) it is the `seq` of the last change. On a shorter page, an
374
+ * empty one included, it is `watermark`: the read got that far, past the changes
375
+ * that `kinds` left out too. */
376
+ nextCursor: number;
377
+ /** The `seq` of the newest change that can be read now. You are caught up when
378
+ * `nextCursor` equals it, or when a page is empty. */
379
+ watermark: number;
380
+ };
381
+ /** Options for `monitors.changes`. */
382
+ type MonitorChangesOptions = {
383
+ /** Read the changes after this `seq`. If you leave it out, the page starts at the
384
+ * first change. Do not send it with `since`. */
385
+ cursor?: number;
386
+ /** Read from this time on: a `Date`, or an ISO 8601 time with an offset such as
387
+ * `"2026-11-03T12:00:00Z"`. Do not send it with `cursor`. */
388
+ since?: string | Date;
389
+ /** Only these kinds of change: `entity_added`, `value_changed`, `fact_status_changed`,
390
+ * `alert`, `run` or `plan_changed`, for example `["alert", "run"]`. Another name is a
391
+ * 400 (`kinds_invalid`). An empty list is no filter. */
392
+ kinds?: string[];
393
+ /** How many changes to return (server default 200, maximum 500). */
394
+ limit?: number;
395
+ signal?: AbortSignal;
396
+ };
397
+ /** Options for `monitors.iterateChanges`. */
398
+ type MonitorIterateChangesOptions = {
399
+ /** Read the changes after this `seq`. If you leave it out, the walk starts at the
400
+ * first change. */
401
+ cursor?: number;
402
+ signal?: AbortSignal;
403
+ };
404
+ /** Options for `monitors.list` and `monitors.listPage`. */
405
+ type MonitorListOptions = {
406
+ /** How many to return (server default 50, maximum 200). */
407
+ limit?: number;
408
+ /** The `nextCursor` of the page before. */
409
+ cursor?: string;
410
+ signal?: AbortSignal;
411
+ };
412
+ /** One page of `monitors.listPage`. */
413
+ type MonitorPage = {
414
+ monitors: Monitor[];
415
+ /** Pass as `cursor` to get the next page; `null` on the last page. */
416
+ nextCursor: string | null;
417
+ };
291
418
  /** The `telem.monitors` namespace. */
292
419
  type MonitorsResource = {
293
420
  create(query: string, options?: MonitorCreateOptions): Promise<Monitor>;
294
- list(options?: {
295
- limit?: number;
296
- signal?: AbortSignal;
297
- }): Promise<Monitor[]>;
421
+ list(options?: MonitorListOptions): Promise<Monitor[]>;
422
+ listPage(options?: MonitorListOptions): Promise<MonitorPage>;
298
423
  get(monitorId: string, options?: {
299
424
  signal?: AbortSignal;
300
425
  }): Promise<Monitor>;
@@ -303,6 +428,14 @@ type MonitorsResource = {
303
428
  delete(monitorId: string, options?: {
304
429
  signal?: AbortSignal;
305
430
  }): Promise<void>;
431
+ /** Read the monitor agent's document. A monitor without an agent answers 404. */
432
+ agent(monitorId: string, options?: {
433
+ signal?: AbortSignal;
434
+ }): Promise<AgentDocument>;
435
+ /** One page of the agent's changes. Keep `nextCursor` and pass it back as `cursor`. */
436
+ changes(monitorId: string, options?: MonitorChangesOptions): Promise<ChangesPage>;
437
+ /** Every change after `cursor`, page by page, until you are caught up. */
438
+ iterateChanges(monitorId: string, options?: MonitorIterateChangesOptions): AsyncGenerator<ChangeRecord, void, undefined>;
306
439
  };
307
440
 
308
441
  /**
@@ -446,7 +579,8 @@ declare class Telem {
446
579
  readonly maxRetries: number;
447
580
  /** The session read surface: `list` and `results(id)`. */
448
581
  readonly sessions: SessionsResource;
449
- /** Monitors: `create`, `list`, `get`, `update`, `poll`, `delete`. */
582
+ /** Monitors: `create`, `list`, `listPage`, `get`, `update`, `poll`, `delete`, and the
583
+ * agent reads `agent`, `changes` and `iterateChanges`. */
450
584
  readonly monitors: MonitorsResource;
451
585
  /**
452
586
  * @param options - An API key string, or an options object. Anything left unset
@@ -479,4 +613,4 @@ declare class Telem {
479
613
  providers(): Promise<ProviderInfo[]>;
480
614
  }
481
615
 
482
- export { type FetchOptions, type FetchResponse, type FetchResult, type Json, type Monitor, type MonitorCreateOptions, type MonitorPollOptions, type MonitorUpdateOptions, type MonitorsResource, type ProviderInfo, type ProviderRun, RESERVED_METADATA, type SearchDefaults, type SearchOptions, type SearchResponse, type SearchResult, type SessionResults, type SessionSummary, type SessionsResource, type SnapshotArgs, Telem, type TelemClientErrorCode, TelemError, type TelemErrorOptions, type TelemOptions, TimeoutError, type TrajectoryArgs, type TrajectoryEnvelope, type TrajectorySnapshot, buildMetadata, buildSnapshot, contentAnchor, Telem as default, eventNodeKey, fingerprint, sessionKey, snapshotNodeKey, toolMarker, verifyWebhook, windowAnchor, withTrajectory };
616
+ export { type AgentCompileState, type AgentDocument, type AgentState, type ChangeRecord, type ChangeSubject, type ChangesPage, type FetchOptions, type FetchResponse, type FetchResult, type Json, type Monitor, type MonitorChangesOptions, type MonitorCreateOptions, type MonitorIterateChangesOptions, type MonitorListOptions, type MonitorPage, type MonitorPollOptions, type MonitorUpdateOptions, type MonitorsResource, type ProviderInfo, type ProviderRun, RESERVED_METADATA, type SearchDefaults, type SearchOptions, type SearchResponse, type SearchResult, type SessionResults, type SessionSummary, type SessionsResource, type SnapshotArgs, Telem, type TelemClientErrorCode, TelemError, type TelemErrorOptions, type TelemOptions, TimeoutError, type TrajectoryArgs, type TrajectoryEnvelope, type TrajectorySnapshot, buildMetadata, buildSnapshot, contentAnchor, Telem as default, eventNodeKey, fingerprint, sessionKey, snapshotNodeKey, toolMarker, verifyWebhook, windowAnchor, withTrajectory };
package/dist/index.js CHANGED
@@ -19,10 +19,10 @@ import {
19
19
  windowAnchor,
20
20
  wireMetadata,
21
21
  withTrajectory
22
- } from "./chunk-DKTEG7EY.js";
22
+ } from "./chunk-SQ3ZZA72.js";
23
23
 
24
24
  // src/version.ts
25
- var VERSION = "0.3.3";
25
+ var VERSION = "0.4.0";
26
26
 
27
27
  // src/config.ts
28
28
  var DEFAULT_BASE_URL = "https://router.telem.ai";
@@ -82,6 +82,7 @@ function resolveConfig(options) {
82
82
  if (typeof send !== "function") {
83
83
  throw invalidOption("no fetch on this runtime: pass one with the `fetch` option");
84
84
  }
85
+ if (typeof opts.apiKey === "string" && !opts.apiKey.trim()) throw invalidOption("apiKey is empty");
85
86
  let apiKey = opts.apiKey || env.TELEM_API_KEY || void 0;
86
87
  let baseUrl = opts.baseUrl || env.TELEM_BASE_URL || void 0;
87
88
  if (apiKey === void 0 || baseUrl === void 0) {
@@ -331,7 +332,8 @@ function providerRun(run) {
331
332
  related: envelope.related ?? null,
332
333
  verticals: envelope.verticals ?? null,
333
334
  usage: envelope.usage ?? null,
334
- warnings: asArray(envelope.warnings)
335
+ warnings: asArray(envelope.warnings),
336
+ sameStory: isObject(envelope.same_story) ? envelope.same_story : null
335
337
  };
336
338
  }
337
339
  function buildSearchResponse(interaction) {
@@ -355,9 +357,25 @@ async function search(config, query, options) {
355
357
  }
356
358
 
357
359
  // src/methods/monitors.ts
360
+ function agentStateFrom(data) {
361
+ return {
362
+ engine: String(data.engine ?? ""),
363
+ status: String(data.status ?? ""),
364
+ needsAttention: data.needs_attention === true,
365
+ planVersion: typeof data.plan_version === "number" ? data.plan_version : null,
366
+ nextRunAt: typeof data.next_run_at === "string" ? data.next_run_at : null,
367
+ watermark: Number(data.watermark ?? 0),
368
+ // No compile job yet is null, not an object of empty strings.
369
+ compile: isObject(data.compile) ? {
370
+ jobId: String(data.compile.job_id ?? ""),
371
+ status: String(data.compile.status ?? ""),
372
+ error: typeof data.compile.error === "string" ? data.compile.error : null
373
+ } : null
374
+ };
375
+ }
358
376
  function monitorFrom(body) {
359
377
  const data = asObject(body);
360
- return {
378
+ const monitor = {
361
379
  id: String(data.id ?? ""),
362
380
  query: data.query ?? "",
363
381
  frequency: data.frequency ?? "",
@@ -370,12 +388,85 @@ function monitorFrom(body) {
370
388
  webhookSecret: data.webhook_secret ?? null,
371
389
  raw: data
372
390
  };
391
+ if (data.agent_state !== void 0) {
392
+ monitor.agentState = isObject(data.agent_state) ? agentStateFrom(data.agent_state) : null;
393
+ }
394
+ return monitor;
395
+ }
396
+ function agentDocumentFrom(body) {
397
+ const data = asObject(body);
398
+ const document = { raw: data };
399
+ if (typeof data.status === "string") document.status = data.status;
400
+ if (typeof data.query === "string") document.query = data.query;
401
+ if (typeof data.frequency === "string") document.frequency = data.frequency;
402
+ if (typeof data.spec_version === "number") document.specVersion = data.spec_version;
403
+ if (data.budget !== void 0) document.budget = isObject(data.budget) ? data.budget : null;
404
+ if (typeof data.spend_usd === "number") document.spendUsd = data.spend_usd;
405
+ return document;
406
+ }
407
+ function changeRecordFrom(entry) {
408
+ const subject = asObject(entry.subject);
409
+ return {
410
+ seq: Number(entry.seq ?? 0),
411
+ type: String(entry.type ?? ""),
412
+ kind: String(entry.kind ?? ""),
413
+ monitorId: String(entry.monitor_id ?? ""),
414
+ subject: {
415
+ entityId: typeof subject.entity_id === "string" ? subject.entity_id : null,
416
+ name: typeof subject.name === "string" ? subject.name : null
417
+ },
418
+ // The values depend on the kind (an object, a status string, nothing): as sent.
419
+ before: entry.before ?? null,
420
+ after: entry.after ?? null,
421
+ factIds: asArray(entry.fact_ids).map(String),
422
+ at: String(entry.at ?? ""),
423
+ raw: entry
424
+ };
425
+ }
426
+ function changesPageFrom(body) {
427
+ const data = asObject(body);
428
+ return {
429
+ changes: asArray(data.changes).filter(isObject).map(changeRecordFrom),
430
+ nextCursor: Number(data.next_cursor ?? 0),
431
+ watermark: Number(data.watermark ?? 0)
432
+ };
433
+ }
434
+ function listQuery(options) {
435
+ const params = new URLSearchParams();
436
+ if (options.limit !== void 0) params.set("limit", String(options.limit));
437
+ if (options.cursor !== void 0) params.set("cursor", options.cursor);
438
+ const query = params.toString();
439
+ return query ? `?${query}` : "";
440
+ }
441
+ function sinceParam(since) {
442
+ if (typeof since === "string") return since;
443
+ if (Number.isNaN(since.getTime())) throw invalidRequest("since is not a valid date");
444
+ return since.toISOString();
445
+ }
446
+ function changesQuery(options) {
447
+ const params = new URLSearchParams();
448
+ if (options.cursor !== void 0) params.set("cursor", String(options.cursor));
449
+ if (options.since !== void 0) params.set("since", sinceParam(options.since));
450
+ if (options.kinds !== void 0) params.set("kinds", options.kinds.join(","));
451
+ if (options.limit !== void 0) params.set("limit", String(options.limit));
452
+ const query = params.toString();
453
+ return query ? `?${query}` : "";
373
454
  }
374
455
  function createMonitors(config) {
375
456
  const path = (monitorId, suffix = "") => {
376
457
  if (!monitorId || /^\.+$/.test(monitorId)) throw invalidRequest("a monitor id is required");
377
458
  return `/v1/monitors/${encodeURIComponent(monitorId)}${suffix}`;
378
459
  };
460
+ const listPage = async (options = {}) => {
461
+ const route = `/v1/monitors${listQuery(options)}`;
462
+ const data = asObject(await request(config, "GET", route, void 0, options.signal));
463
+ const nextCursor = typeof data.next_cursor === "string" ? data.next_cursor : null;
464
+ return { monitors: asArray(data.monitors).map(monitorFrom), nextCursor };
465
+ };
466
+ const changes = async (monitorId, options = {}) => {
467
+ const route = `${path(monitorId, "/agent/changes")}${changesQuery(options)}`;
468
+ return changesPageFrom(await request(config, "GET", route, void 0, options.signal));
469
+ };
379
470
  return {
380
471
  /** Create a monitor. Telem runs `query` on the schedule. */
381
472
  async create(query, options = {}) {
@@ -389,15 +480,25 @@ function createMonitors(config) {
389
480
  if (options.metadata !== void 0) body.metadata = options.metadata;
390
481
  if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl;
391
482
  if (options.ttl !== void 0) body.ttl = options.ttl;
392
- const data = await request(config, "POST", "/v1/monitors", body, options.signal, "rate_limit");
483
+ if (options.agent !== void 0) body.agent = options.agent;
484
+ const data = await request(config, "POST", "/v1/monitors", body, options.signal, "rate_limit").catch(
485
+ (error) => {
486
+ if (error instanceof TimeoutError) {
487
+ throw new TimeoutError(
488
+ `${error.message}. The monitor may exist: list monitors before you create it again.`,
489
+ error.cause
490
+ );
491
+ }
492
+ throw error;
493
+ }
494
+ );
393
495
  return monitorFrom(data);
394
496
  },
395
- /** List your monitors, newest first (server default 50, maximum 200). */
497
+ /** List your monitors, newest first. `listPage` also gives the next cursor. */
396
498
  async list(options = {}) {
397
- const query = options.limit === void 0 ? "" : `?limit=${options.limit}`;
398
- const body = await request(config, "GET", `/v1/monitors${query}`, void 0, options.signal);
399
- return asArray(asObject(body).monitors).map(monitorFrom);
499
+ return (await listPage(options)).monitors;
400
500
  },
501
+ listPage,
401
502
  /** Get one monitor. */
402
503
  async get(monitorId, options = {}) {
403
504
  return monitorFrom(await request(config, "GET", path(monitorId), void 0, options.signal));
@@ -407,7 +508,7 @@ function createMonitors(config) {
407
508
  const body = {};
408
509
  if (options.status !== void 0) body.status = options.status;
409
510
  if (options.frequency !== void 0) body.frequency = options.frequency;
410
- if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl;
511
+ if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl || null;
411
512
  const route = path(monitorId);
412
513
  return monitorFrom(await request(config, "PATCH", route, body, options.signal));
413
514
  },
@@ -423,6 +524,23 @@ function createMonitors(config) {
423
524
  /** Delete a monitor. A repeat deletes what a failed delete left. */
424
525
  async delete(monitorId, options = {}) {
425
526
  await request(config, "DELETE", path(monitorId), void 0, options.signal);
527
+ },
528
+ /** Read the monitor agent's document. A monitor without an agent answers 404. */
529
+ async agent(monitorId, options = {}) {
530
+ const route = path(monitorId, "/agent");
531
+ return agentDocumentFrom(await request(config, "GET", route, void 0, options.signal));
532
+ },
533
+ /** One page of the agent's changes. Keep `nextCursor` and pass it back as `cursor`. */
534
+ changes,
535
+ /** Every change after `cursor`, page by page, until you are caught up. */
536
+ async *iterateChanges(monitorId, options = {}) {
537
+ let cursor = options.cursor ?? 0;
538
+ for (; ; ) {
539
+ const page = await changes(monitorId, { cursor, signal: options.signal });
540
+ for (const change of page.changes) yield change;
541
+ if (!page.changes.length || page.nextCursor <= cursor || page.nextCursor >= page.watermark) return;
542
+ cursor = page.nextCursor;
543
+ }
426
544
  }
427
545
  };
428
546
  }
@@ -525,7 +643,8 @@ var Telem = class {
525
643
  maxRetries;
526
644
  /** The session read surface: `list` and `results(id)`. */
527
645
  sessions;
528
- /** Monitors: `create`, `list`, `get`, `update`, `poll`, `delete`. */
646
+ /** Monitors: `create`, `list`, `listPage`, `get`, `update`, `poll`, `delete`, and the
647
+ * agent reads `agent`, `changes` and `iterateChanges`. */
529
648
  monitors;
530
649
  #config;
531
650
  /**
@@ -9,7 +9,7 @@ import {
9
9
  toolMarker,
10
10
  windowAnchor,
11
11
  withTrajectory
12
- } from "../chunk-DKTEG7EY.js";
12
+ } from "../chunk-SQ3ZZA72.js";
13
13
 
14
14
  // src/vercel/index.ts
15
15
  import { jsonSchema } from "ai";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telemai/sdk",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "Telem web search and fetch for JavaScript and TypeScript.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",