@telemai/sdk 0.3.1 → 0.3.3

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
@@ -167,6 +167,13 @@ const page = await telem.fetch("https://example.com/article", {
167
167
  const { status, content } = page.results[0]
168
168
  ```
169
169
 
170
+ `providers` pins the fetch providers, in order; `tier` picks the fetch tier; and
171
+ `noCache: true` reads the page live instead of from the shared cache. If you leave
172
+ one out, the client uses its environment variable: `TELEM_FETCH_PROVIDERS` (comma
173
+ separated), `TELEM_FETCH_TIER` (lowercased) or `TELEM_FETCH_NO_CACHE` (`1` turns it
174
+ on). The client reads them when you create it. An option you pass wins, so
175
+ `noCache: false` turns off `TELEM_FETCH_NO_CACHE=1` for that call.
176
+
170
177
  A URL that failed still returns a result. Check `result.status` and `result.error`.
171
178
  Do not expect a shorter list. The options are on the
172
179
  [fetch parameters](https://docs.telem.ai/resources/fetch-parameters/) page.
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.1";
63
+ var VERSION = "0.3.3";
64
64
 
65
65
  // src/config.ts
66
66
  var DEFAULT_BASE_URL = "https://router.telem.ai";
@@ -158,6 +158,14 @@ function resolveConfig(options) {
158
158
  autoRouting: opts.autoRouting ?? (trimBlank(env.TELEM_AUTO_ROUTING ?? "") || void 0),
159
159
  maxRoutingProviders: opts.maxRoutingProviders ?? intEnv(env.TELEM_MAX_ROUTING_PROVIDERS),
160
160
  topic: opts.topic ?? (trimBlank(env.TELEM_TOPIC ?? "") || void 0)
161
+ },
162
+ // Fetch defaults: env var only, parsed as the shared option table parses it (CSV,
163
+ // a trimmed name, a "1"-only flag); the tier is lowercased, as the agent plugins
164
+ // send it. No constructor option, and no config file, as above.
165
+ fetchDefaults: {
166
+ providers: csvEnv(env.TELEM_FETCH_PROVIDERS),
167
+ tier: trimBlank(env.TELEM_FETCH_TIER ?? "").toLowerCase() || void 0,
168
+ noCache: env.TELEM_FETCH_NO_CACHE === "1" || void 0
161
169
  }
162
170
  };
163
171
  }
@@ -492,7 +500,7 @@ function wireMetadata(options, kind) {
492
500
  }
493
501
 
494
502
  // src/methods/fetch.ts
495
- function fetchBody(url, options) {
503
+ function fetchBody(url, options, defaults) {
496
504
  const urls = stringList(
497
505
  typeof url === "string" ? [url] : url,
498
506
  "fetch() requires at least one URL",
@@ -500,11 +508,16 @@ function fetchBody(url, options) {
500
508
  );
501
509
  const { metadata, sessionId } = wireMetadata(options, "fetch");
502
510
  const body = { urls, metadata };
511
+ const providers2 = options.providers ?? defaults.providers;
512
+ const tier = options.tier ?? defaults.tier;
513
+ const noCache = options.noCache ?? defaults.noCache;
503
514
  const block = {};
504
- if (options.providers !== void 0) block.providers = options.providers;
515
+ if (providers2 !== void 0) block.providers = providers2;
505
516
  if (options.inlineContent !== void 0) block.inline_content = options.inlineContent;
506
517
  if (options.inlineMaxChars !== void 0) block.inline_max_chars = options.inlineMaxChars;
507
518
  if (options.contentFormat !== void 0) block.content_format = options.contentFormat;
519
+ if (tier !== void 0) block.tier = tier;
520
+ if (noCache !== void 0) block.no_cache = noCache;
508
521
  if (Object.keys(block).length) body.options = block;
509
522
  if (sessionId !== void 0) body.session_id = sessionId;
510
523
  return body;
@@ -545,12 +558,17 @@ function buildFetchResponse(interaction) {
545
558
  };
546
559
  }
547
560
  async function fetchUrls(config, url, options) {
548
- const body = fetchBody(url, options);
561
+ const body = fetchBody(url, options, config.fetchDefaults);
549
562
  return buildFetchResponse(await request(config, "POST", "/v1/fetch", body, options.signal));
550
563
  }
551
564
 
552
565
  // src/methods/search.ts
553
566
  var MIN_SCHEMA_VERSION = 2;
567
+ function providersRefusal(include, includeFromCall, excludeFromCall) {
568
+ const where = (half, env, fromCall) => fromCall ? `the ${half} search() option` : `the client's ${half} or ${env}`;
569
+ const names = include.join(", ");
570
+ return `providersExclude removes every provider in providersInclude (${names}), so no provider is left and no search was sent. Remove ${names} from providersInclude (set by ${where("providersInclude", "TELEM_PROVIDERS_INCLUDE", includeFromCall)}) or from providersExclude (set by ${where("providersExclude", "TELEM_PROVIDERS_EXCLUDE", excludeFromCall)}).`;
571
+ }
554
572
  function searchBlock(defaults, options) {
555
573
  const fromCallTier = options.tier !== void 0;
556
574
  const fromCallFields = options.fields !== void 0;
@@ -564,7 +582,13 @@ function searchBlock(defaults, options) {
564
582
  let exclude = options.providersExclude ?? defaults.providersExclude;
565
583
  if (include !== void 0 && exclude !== void 0) {
566
584
  const excluded = new Set(exclude);
567
- include = include.filter((name) => !excluded.has(name));
585
+ const kept = include.filter((name) => !excluded.has(name));
586
+ if (include.length && !kept.length) {
587
+ throw invalidRequest(
588
+ providersRefusal(include, options.providersInclude !== void 0, options.providersExclude !== void 0)
589
+ );
590
+ }
591
+ include = kept;
568
592
  exclude = void 0;
569
593
  }
570
594
  const includeFullContent = options.includeFullContent ?? defaults.includeFullContent;
@@ -588,6 +612,7 @@ function searchBlock(defaults, options) {
588
612
  if (topic !== void 0) block.topic = topic;
589
613
  if (options.publishedAfter !== void 0) block.published_after = isoDate(options.publishedAfter);
590
614
  if (options.publishedBefore !== void 0) block.published_before = isoDate(options.publishedBefore);
615
+ if (options.includeDomains !== void 0) block.include_domains = options.includeDomains;
591
616
  return block;
592
617
  }
593
618
  function isoDate(value) {
@@ -720,8 +745,14 @@ function createMonitors(config) {
720
745
  };
721
746
  return {
722
747
  /** Create a monitor. Telem runs `query` on the schedule. */
723
- async create(query, options) {
724
- const body = { query, options: { frequency: options.frequency } };
748
+ async create(query, options = {}) {
749
+ const monitorOptions = {};
750
+ if (options.frequency !== void 0) monitorOptions.frequency = options.frequency;
751
+ if (options.includeDomains !== void 0) {
752
+ monitorOptions.include_domains = options.includeDomains;
753
+ }
754
+ if (options.search !== void 0) monitorOptions.search = searchBlock({}, options.search);
755
+ const body = { query, options: monitorOptions };
725
756
  if (options.metadata !== void 0) body.metadata = options.metadata;
726
757
  if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl;
727
758
  if (options.ttl !== void 0) body.ttl = options.ttl;
@@ -747,7 +778,7 @@ function createMonitors(config) {
747
778
  const route = path(monitorId);
748
779
  return monitorFrom(await request(config, "PATCH", route, body, options.signal));
749
780
  },
750
- /** Get the results that are new since the last poll, one entry per provider. */
781
+ /** Get the results that are new since the last poll. */
751
782
  async poll(monitorId, options = {}) {
752
783
  const body = {};
753
784
  if (options.session !== void 0) body.session_id = options.session;
@@ -791,7 +822,8 @@ async function providers(config) {
791
822
  method: entry.method ?? null,
792
823
  url: entry.url ?? null,
793
824
  normalized: entry.normalized ?? false,
794
- tiers: asArray(entry.tiers)
825
+ tiers: asArray(entry.tiers),
826
+ autoRouted: entry.auto_routed ?? null
795
827
  }));
796
828
  }
797
829
 
package/dist/index.d.cts CHANGED
@@ -72,6 +72,9 @@ type SearchOptions = {
72
72
  * includes that whole day. A `Date` is an exact instant; pass a "YYYY-MM-DD"
73
73
  * string to include the whole day. */
74
74
  publishedBefore?: string | Date;
75
+ /** Only results from these domains: at most 20 hostnames such as `"linkedin.com"`.
76
+ * A subdomain such as `"uk.linkedin.com"` matches its domain. Per-call only. */
77
+ includeDomains?: string[];
75
78
  /** Opt this request into the server's rerank stage. It is the only path where
76
79
  * `context`, the reasoning on the last assistant entry of the lineage history
77
80
  * (that entry only), and `goal` change result ORDER (in that precedence) —
@@ -93,10 +96,17 @@ type SearchOptions = {
93
96
  * `numResults`/`includeRaw`/`rerank`/`providerOverrides` are per-call intent only. */
94
97
  type SearchDefaults = Pick<SearchOptions, "tier" | "fields" | "providersInclude" | "providersExclude" | "includeFullContent" | "autoRouting" | "maxRoutingProviders" | "topic">;
95
98
  type FetchOptions = {
99
+ /** Fetch provider chain, in order. Defaults to `TELEM_FETCH_PROVIDERS`. */
96
100
  providers?: string[];
97
101
  inlineContent?: boolean;
98
102
  inlineMaxChars?: number;
99
103
  contentFormat?: string;
104
+ /** Fetch tier: `minimalist`, `default`, `extended` or `max`. Sent as given; the
105
+ * server rejects an unknown one. Defaults to `TELEM_FETCH_TIER`, lowercased. */
106
+ tier?: string;
107
+ /** `true` reads every page live and skips the shared fetch cache. Defaults to
108
+ * `TELEM_FETCH_NO_CACHE` (on with exactly `"1"`); `false` overrides it. */
109
+ noCache?: boolean;
100
110
  session?: string;
101
111
  /** Abort this call: the request stops, no retry follows, and the call rejects
102
112
  * with the signal's reason. Merged with the per-attempt timeout. */
@@ -197,6 +207,8 @@ type ProviderInfo = {
197
207
  url: string | null;
198
208
  normalized: boolean;
199
209
  tiers: string[];
210
+ /** Whether auto-routing can pick it for a ranked topic; `null` from a router that does not say. */
211
+ autoRouted: boolean | null;
200
212
  };
201
213
  /** One session as `sessions.list` reports it. */
202
214
  type SessionSummary = {
@@ -222,10 +234,18 @@ type SessionsResource = {
222
234
  list(): Promise<SessionSummary[]>;
223
235
  results(sessionId: string): Promise<SessionResults>;
224
236
  };
237
+ /** The search options a monitor can run on its schedule (`MonitorCreateOptions.search`). */
238
+ type MonitorSearchOptions = Pick<SearchOptions, "tier" | "numResults">;
225
239
  /** Options for `monitors.create`. */
226
240
  type MonitorCreateOptions = {
227
- /** `"1h"`, `"6h"`, `"1d"` or `"7d"`. */
228
- frequency: string;
241
+ /** `"1h"`, `"6h"`, `"12h"`, `"1d"` or `"7d"`. If you leave it out, the monitor runs once a day. */
242
+ frequency?: string;
243
+ /** Also run a web search for the query on the schedule, with these options. `{}`
244
+ * uses the defaults. Client search defaults do not apply. */
245
+ search?: MonitorSearchOptions;
246
+ /** Only results from these sites and their subdomains, such as `["sec.gov"]`,
247
+ * from every source of the monitor. */
248
+ includeDomains?: string[];
229
249
  /** Request metadata (query lineage keys), sent as given. */
230
250
  metadata?: Json;
231
251
  /** An `https` URL that receives the new results. */
@@ -270,7 +290,7 @@ type Monitor = {
270
290
  };
271
291
  /** The `telem.monitors` namespace. */
272
292
  type MonitorsResource = {
273
- create(query: string, options: MonitorCreateOptions): Promise<Monitor>;
293
+ create(query: string, options?: MonitorCreateOptions): Promise<Monitor>;
274
294
  list(options?: {
275
295
  limit?: number;
276
296
  signal?: AbortSignal;
package/dist/index.d.ts CHANGED
@@ -72,6 +72,9 @@ type SearchOptions = {
72
72
  * includes that whole day. A `Date` is an exact instant; pass a "YYYY-MM-DD"
73
73
  * string to include the whole day. */
74
74
  publishedBefore?: string | Date;
75
+ /** Only results from these domains: at most 20 hostnames such as `"linkedin.com"`.
76
+ * A subdomain such as `"uk.linkedin.com"` matches its domain. Per-call only. */
77
+ includeDomains?: string[];
75
78
  /** Opt this request into the server's rerank stage. It is the only path where
76
79
  * `context`, the reasoning on the last assistant entry of the lineage history
77
80
  * (that entry only), and `goal` change result ORDER (in that precedence) —
@@ -93,10 +96,17 @@ type SearchOptions = {
93
96
  * `numResults`/`includeRaw`/`rerank`/`providerOverrides` are per-call intent only. */
94
97
  type SearchDefaults = Pick<SearchOptions, "tier" | "fields" | "providersInclude" | "providersExclude" | "includeFullContent" | "autoRouting" | "maxRoutingProviders" | "topic">;
95
98
  type FetchOptions = {
99
+ /** Fetch provider chain, in order. Defaults to `TELEM_FETCH_PROVIDERS`. */
96
100
  providers?: string[];
97
101
  inlineContent?: boolean;
98
102
  inlineMaxChars?: number;
99
103
  contentFormat?: string;
104
+ /** Fetch tier: `minimalist`, `default`, `extended` or `max`. Sent as given; the
105
+ * server rejects an unknown one. Defaults to `TELEM_FETCH_TIER`, lowercased. */
106
+ tier?: string;
107
+ /** `true` reads every page live and skips the shared fetch cache. Defaults to
108
+ * `TELEM_FETCH_NO_CACHE` (on with exactly `"1"`); `false` overrides it. */
109
+ noCache?: boolean;
100
110
  session?: string;
101
111
  /** Abort this call: the request stops, no retry follows, and the call rejects
102
112
  * with the signal's reason. Merged with the per-attempt timeout. */
@@ -197,6 +207,8 @@ type ProviderInfo = {
197
207
  url: string | null;
198
208
  normalized: boolean;
199
209
  tiers: string[];
210
+ /** Whether auto-routing can pick it for a ranked topic; `null` from a router that does not say. */
211
+ autoRouted: boolean | null;
200
212
  };
201
213
  /** One session as `sessions.list` reports it. */
202
214
  type SessionSummary = {
@@ -222,10 +234,18 @@ type SessionsResource = {
222
234
  list(): Promise<SessionSummary[]>;
223
235
  results(sessionId: string): Promise<SessionResults>;
224
236
  };
237
+ /** The search options a monitor can run on its schedule (`MonitorCreateOptions.search`). */
238
+ type MonitorSearchOptions = Pick<SearchOptions, "tier" | "numResults">;
225
239
  /** Options for `monitors.create`. */
226
240
  type MonitorCreateOptions = {
227
- /** `"1h"`, `"6h"`, `"1d"` or `"7d"`. */
228
- frequency: string;
241
+ /** `"1h"`, `"6h"`, `"12h"`, `"1d"` or `"7d"`. If you leave it out, the monitor runs once a day. */
242
+ frequency?: string;
243
+ /** Also run a web search for the query on the schedule, with these options. `{}`
244
+ * uses the defaults. Client search defaults do not apply. */
245
+ search?: MonitorSearchOptions;
246
+ /** Only results from these sites and their subdomains, such as `["sec.gov"]`,
247
+ * from every source of the monitor. */
248
+ includeDomains?: string[];
229
249
  /** Request metadata (query lineage keys), sent as given. */
230
250
  metadata?: Json;
231
251
  /** An `https` URL that receives the new results. */
@@ -270,7 +290,7 @@ type Monitor = {
270
290
  };
271
291
  /** The `telem.monitors` namespace. */
272
292
  type MonitorsResource = {
273
- create(query: string, options: MonitorCreateOptions): Promise<Monitor>;
293
+ create(query: string, options?: MonitorCreateOptions): Promise<Monitor>;
274
294
  list(options?: {
275
295
  limit?: number;
276
296
  signal?: AbortSignal;
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-DKTEG7EY.js";
23
23
 
24
24
  // src/version.ts
25
- var VERSION = "0.3.1";
25
+ var VERSION = "0.3.3";
26
26
 
27
27
  // src/config.ts
28
28
  var DEFAULT_BASE_URL = "https://router.telem.ai";
@@ -120,12 +120,20 @@ function resolveConfig(options) {
120
120
  autoRouting: opts.autoRouting ?? (trimBlank(env.TELEM_AUTO_ROUTING ?? "") || void 0),
121
121
  maxRoutingProviders: opts.maxRoutingProviders ?? intEnv(env.TELEM_MAX_ROUTING_PROVIDERS),
122
122
  topic: opts.topic ?? (trimBlank(env.TELEM_TOPIC ?? "") || void 0)
123
+ },
124
+ // Fetch defaults: env var only, parsed as the shared option table parses it (CSV,
125
+ // a trimmed name, a "1"-only flag); the tier is lowercased, as the agent plugins
126
+ // send it. No constructor option, and no config file, as above.
127
+ fetchDefaults: {
128
+ providers: csvEnv(env.TELEM_FETCH_PROVIDERS),
129
+ tier: trimBlank(env.TELEM_FETCH_TIER ?? "").toLowerCase() || void 0,
130
+ noCache: env.TELEM_FETCH_NO_CACHE === "1" || void 0
123
131
  }
124
132
  };
125
133
  }
126
134
 
127
135
  // src/methods/fetch.ts
128
- function fetchBody(url, options) {
136
+ function fetchBody(url, options, defaults) {
129
137
  const urls = stringList(
130
138
  typeof url === "string" ? [url] : url,
131
139
  "fetch() requires at least one URL",
@@ -133,11 +141,16 @@ function fetchBody(url, options) {
133
141
  );
134
142
  const { metadata, sessionId } = wireMetadata(options, "fetch");
135
143
  const body = { urls, metadata };
144
+ const providers2 = options.providers ?? defaults.providers;
145
+ const tier = options.tier ?? defaults.tier;
146
+ const noCache = options.noCache ?? defaults.noCache;
136
147
  const block = {};
137
- if (options.providers !== void 0) block.providers = options.providers;
148
+ if (providers2 !== void 0) block.providers = providers2;
138
149
  if (options.inlineContent !== void 0) block.inline_content = options.inlineContent;
139
150
  if (options.inlineMaxChars !== void 0) block.inline_max_chars = options.inlineMaxChars;
140
151
  if (options.contentFormat !== void 0) block.content_format = options.contentFormat;
152
+ if (tier !== void 0) block.tier = tier;
153
+ if (noCache !== void 0) block.no_cache = noCache;
141
154
  if (Object.keys(block).length) body.options = block;
142
155
  if (sessionId !== void 0) body.session_id = sessionId;
143
156
  return body;
@@ -178,12 +191,17 @@ function buildFetchResponse(interaction) {
178
191
  };
179
192
  }
180
193
  async function fetchUrls(config, url, options) {
181
- const body = fetchBody(url, options);
194
+ const body = fetchBody(url, options, config.fetchDefaults);
182
195
  return buildFetchResponse(await request(config, "POST", "/v1/fetch", body, options.signal));
183
196
  }
184
197
 
185
198
  // src/methods/search.ts
186
199
  var MIN_SCHEMA_VERSION = 2;
200
+ function providersRefusal(include, includeFromCall, excludeFromCall) {
201
+ const where = (half, env, fromCall) => fromCall ? `the ${half} search() option` : `the client's ${half} or ${env}`;
202
+ const names = include.join(", ");
203
+ return `providersExclude removes every provider in providersInclude (${names}), so no provider is left and no search was sent. Remove ${names} from providersInclude (set by ${where("providersInclude", "TELEM_PROVIDERS_INCLUDE", includeFromCall)}) or from providersExclude (set by ${where("providersExclude", "TELEM_PROVIDERS_EXCLUDE", excludeFromCall)}).`;
204
+ }
187
205
  function searchBlock(defaults, options) {
188
206
  const fromCallTier = options.tier !== void 0;
189
207
  const fromCallFields = options.fields !== void 0;
@@ -197,7 +215,13 @@ function searchBlock(defaults, options) {
197
215
  let exclude = options.providersExclude ?? defaults.providersExclude;
198
216
  if (include !== void 0 && exclude !== void 0) {
199
217
  const excluded = new Set(exclude);
200
- include = include.filter((name) => !excluded.has(name));
218
+ const kept = include.filter((name) => !excluded.has(name));
219
+ if (include.length && !kept.length) {
220
+ throw invalidRequest(
221
+ providersRefusal(include, options.providersInclude !== void 0, options.providersExclude !== void 0)
222
+ );
223
+ }
224
+ include = kept;
201
225
  exclude = void 0;
202
226
  }
203
227
  const includeFullContent = options.includeFullContent ?? defaults.includeFullContent;
@@ -221,6 +245,7 @@ function searchBlock(defaults, options) {
221
245
  if (topic !== void 0) block.topic = topic;
222
246
  if (options.publishedAfter !== void 0) block.published_after = isoDate(options.publishedAfter);
223
247
  if (options.publishedBefore !== void 0) block.published_before = isoDate(options.publishedBefore);
248
+ if (options.includeDomains !== void 0) block.include_domains = options.includeDomains;
224
249
  return block;
225
250
  }
226
251
  function isoDate(value) {
@@ -353,8 +378,14 @@ function createMonitors(config) {
353
378
  };
354
379
  return {
355
380
  /** Create a monitor. Telem runs `query` on the schedule. */
356
- async create(query, options) {
357
- const body = { query, options: { frequency: options.frequency } };
381
+ async create(query, options = {}) {
382
+ const monitorOptions = {};
383
+ if (options.frequency !== void 0) monitorOptions.frequency = options.frequency;
384
+ if (options.includeDomains !== void 0) {
385
+ monitorOptions.include_domains = options.includeDomains;
386
+ }
387
+ if (options.search !== void 0) monitorOptions.search = searchBlock({}, options.search);
388
+ const body = { query, options: monitorOptions };
358
389
  if (options.metadata !== void 0) body.metadata = options.metadata;
359
390
  if (options.webhookUrl !== void 0) body.webhook_url = options.webhookUrl;
360
391
  if (options.ttl !== void 0) body.ttl = options.ttl;
@@ -380,7 +411,7 @@ function createMonitors(config) {
380
411
  const route = path(monitorId);
381
412
  return monitorFrom(await request(config, "PATCH", route, body, options.signal));
382
413
  },
383
- /** Get the results that are new since the last poll, one entry per provider. */
414
+ /** Get the results that are new since the last poll. */
384
415
  async poll(monitorId, options = {}) {
385
416
  const body = {};
386
417
  if (options.session !== void 0) body.session_id = options.session;
@@ -424,7 +455,8 @@ async function providers(config) {
424
455
  method: entry.method ?? null,
425
456
  url: entry.url ?? null,
426
457
  normalized: entry.normalized ?? false,
427
- tiers: asArray(entry.tiers)
458
+ tiers: asArray(entry.tiers),
459
+ autoRouted: entry.auto_routed ?? null
428
460
  }));
429
461
  }
430
462
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telemai/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Telem web search and fetch for JavaScript and TypeScript.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",