@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 +12 -0
- package/dist/{chunk-DKTEG7EY.js → chunk-SQ3ZZA72.js} +3 -1
- package/dist/index.cjs +132 -11
- package/dist/index.d.cts +144 -10
- package/dist/index.d.ts +144 -10
- package/dist/index.js +130 -11
- package/dist/vercel/index.js +1 -1
- package/package.json +1 -1
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
866
|
+
/** List your monitors, newest first. `listPage` also gives the next cursor. */
|
|
763
867
|
async list(options = {}) {
|
|
764
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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-
|
|
22
|
+
} from "./chunk-SQ3ZZA72.js";
|
|
23
23
|
|
|
24
24
|
// src/version.ts
|
|
25
|
-
var VERSION = "0.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
497
|
+
/** List your monitors, newest first. `listPage` also gives the next cursor. */
|
|
396
498
|
async list(options = {}) {
|
|
397
|
-
|
|
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
|
/**
|
package/dist/vercel/index.js
CHANGED