@aithos/sdk 0.1.0-alpha.23 → 0.1.0-alpha.24

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.
@@ -192,119 +192,6 @@ export interface InvokeSegmentationResult {
192
192
  readonly walletBalance: number;
193
193
  readonly auditId: string;
194
194
  }
195
- /**
196
- * Models accepted by `invokeUrlFetch`. These are the Anthropic-API-direct
197
- * model aliases — the proxy resolves them to the canonical API model id
198
- * (`claude-haiku-4-5-20251001`, etc.) at dispatch time.
199
- *
200
- * Bedrock's compute_invoke supports the same names but routes through
201
- * Bedrock; url_fetch routes through `api.anthropic.com` directly because
202
- * the `web_fetch` server-side tool isn't exposed via Bedrock.
203
- */
204
- export type UrlFetchModelId = "claude-haiku-4-5" | "claude-sonnet-4-6" | "claude-opus-4-6";
205
- export interface InvokeUrlFetchArgs {
206
- /**
207
- * Mandate ID under which this call should be attributed.
208
- *
209
- * - **Owner sessions**: optional. The owner's own DID is used as a
210
- * sentinel "self" mandate id; the proxy skips all mandate checks
211
- * for owner-signed envelopes.
212
- * - **Delegate sessions**: required. Must reference an imported
213
- * mandate bundle that carries the `compute.url_fetch` scope (NOT
214
- * the same scope as `compute.invoke` — see the protocol spec).
215
- */
216
- readonly mandateId?: string;
217
- /**
218
- * Anthropic model alias. Default `"claude-haiku-4-5"` — fastest and
219
- * cheapest model that supports `web_fetch`. Bump to Sonnet 4.6 for
220
- * deeper reasoning over the fetched content; Opus 4.6 for the
221
- * heaviest analyses (priced accordingly via reconcile). Opus 4.7 is
222
- * provisioned but commercially gated — see the docstring on
223
- * InvokeBedrockArgs.model for the unlock path.
224
- */
225
- readonly model?: UrlFetchModelId;
226
- /**
227
- * User prompt — should normally contain the URL(s) the caller wants
228
- * the model to fetch and analyze. Example:
229
- * "Voici l'URL https://tata.com — résume le service, identifie
230
- * le style du site et la couleur primaire. Renvoie en JSON."
231
- */
232
- readonly prompt: string;
233
- /** Optional system prompt (Anthropic-style separate field). */
234
- readonly system?: string;
235
- /** Cap on output tokens. Default 2048. */
236
- readonly maxTokens?: number;
237
- /** Sampling temperature. Default model-dependent. */
238
- readonly temperature?: number;
239
- /**
240
- * Maximum number of `web_fetch` invocations the model is allowed to
241
- * make in this call. Default 5; range [1, 10].
242
- */
243
- readonly maxFetches?: number;
244
- /**
245
- * Maximum tokens of fetched content Anthropic will inject per fetch.
246
- * Default 100_000; range [1000, 200_000]. Pages larger than this
247
- * are truncated server-side.
248
- */
249
- readonly maxContentTokens?: number;
250
- /**
251
- * When `true` (default), the response carries citation spans tying
252
- * generated text back to fetched documents — useful for displaying
253
- * "selon X, …" footnotes in the UI without post-processing.
254
- */
255
- readonly citations?: boolean;
256
- /**
257
- * Optional domain allowlist — if set, the model can only fetch from
258
- * these domains. Mutually exclusive with `blockedDomains`.
259
- */
260
- readonly allowedDomains?: readonly string[];
261
- /**
262
- * Optional domain blocklist. Mutually exclusive with `allowedDomains`.
263
- */
264
- readonly blockedDomains?: readonly string[];
265
- /** Idempotency key for retries (generated if omitted). */
266
- readonly idempotencyKey?: string;
267
- /** Abort signal to cancel the request. */
268
- readonly signal?: AbortSignal;
269
- }
270
- /**
271
- * Single citation projection — flattened from Anthropic's wire shape so
272
- * consumers can render `{cited_text}` next to `{url}` without parsing
273
- * vendor-specific block types.
274
- */
275
- export interface UrlFetchCitation {
276
- readonly url: string;
277
- readonly citedText: string;
278
- readonly documentTitle?: string;
279
- readonly startCharIndex?: number;
280
- readonly endCharIndex?: number;
281
- }
282
- /** Per-fetch metadata in the order the model performed the fetches. */
283
- export interface UrlFetchMetadata {
284
- readonly url: string;
285
- readonly retrievedAt?: string;
286
- readonly title?: string;
287
- }
288
- export interface InvokeUrlFetchResult {
289
- /** Final assistant text — typically a JSON string when the prompt asked for structure. */
290
- readonly content: string;
291
- /** Citation spans (empty when `citations: false` or no fetches succeeded). */
292
- readonly citations: readonly UrlFetchCitation[];
293
- /** Per-URL fetch metadata. */
294
- readonly urlsFetched: readonly UrlFetchMetadata[];
295
- readonly stopReason: "end_turn" | "max_tokens" | "tool_use" | "stop_sequence" | "pause_turn" | "refusal";
296
- readonly usage: {
297
- readonly inputTokens: number;
298
- readonly outputTokens: number;
299
- readonly webFetchInvocations: number;
300
- };
301
- /** Microcredits charged after reconcile (already net of any refund). */
302
- readonly creditsCharged: number;
303
- /** Wallet balance after the debit + reconcile. */
304
- readonly walletBalance: number;
305
- /** Audit log id for traceability. */
306
- readonly auditId: string;
307
- }
308
195
  export interface ComputeNamespaceDeps {
309
196
  readonly auth: AithosAuth;
310
197
  readonly appDid: string;
@@ -392,41 +279,5 @@ export declare class ComputeNamespace {
392
279
  * Pricing: flat 5 000 mc per call (~$0.005 — Florence-2 is cheap).
393
280
  */
394
281
  invokeSegmentation(args: InvokeSegmentationArgs): Promise<InvokeSegmentationResult>;
395
- /**
396
- * Fetch one or more URLs and have Claude analyze the content. Routes
397
- * through `api.anthropic.com` with the `web_fetch` server-side tool —
398
- * NOT through Bedrock — because Bedrock does not expose Anthropic's
399
- * server-side tools (web_fetch, web_search, etc.). The proxy hides
400
- * this multi-backend detail from the SDK consumer; the wallet,
401
- * envelope, and mandate-scope contracts are unchanged.
402
- *
403
- * Typical use:
404
- * ```ts
405
- * const r = await sdk.compute.invokeUrlFetch({
406
- * prompt: "Voici l'URL https://tata.com — résume le service, " +
407
- * "identifie le style et la couleur primaire. JSON.",
408
- * });
409
- * console.log(r.content);
410
- * for (const c of r.citations) console.log(c.url, "→", c.citedText);
411
- * ```
412
- *
413
- * Mandate scope: requires `compute.url_fetch` (distinct from
414
- * `compute.invoke` — see {@link InvokeUrlFetchArgs.mandateId}).
415
- *
416
- * Pricing: same Claude 4.x rates as Bedrock (Anthropic's direct API
417
- * and Bedrock list prices are identical). Default Haiku 4.5 ≈
418
- * $0.001/1k input + $0.005/1k output. The proxy pre-debits a
419
- * conservative upper bound (`maxFetches × maxContentTokens × input
420
- * rate + maxTokens × output rate`) and reconciles down to the actual
421
- * usage Anthropic reports — so the wallet is always charged the
422
- * exact post-call cost.
423
- *
424
- * @throws {AithosSDKError} on protocol errors. Notable codes:
425
- * `sdk_no_signer`, `sdk_no_delegate_for_mandate`, `network`,
426
- * `http`, `empty`, plus proxy codes `-32042` (mandate scope
427
- * missing), `-32070`/`-32071` (wallet), `-32074` (fetch blocked
428
- * by robots.txt / domain filter), `-32050` (rate limit).
429
- */
430
- invokeUrlFetch(args: InvokeUrlFetchArgs): Promise<InvokeUrlFetchResult>;
431
282
  }
432
283
  //# sourceMappingURL=compute.d.ts.map
@@ -234,82 +234,6 @@ export class ComputeNamespace {
234
234
  signal: args.signal,
235
235
  });
236
236
  }
237
- /**
238
- * Fetch one or more URLs and have Claude analyze the content. Routes
239
- * through `api.anthropic.com` with the `web_fetch` server-side tool —
240
- * NOT through Bedrock — because Bedrock does not expose Anthropic's
241
- * server-side tools (web_fetch, web_search, etc.). The proxy hides
242
- * this multi-backend detail from the SDK consumer; the wallet,
243
- * envelope, and mandate-scope contracts are unchanged.
244
- *
245
- * Typical use:
246
- * ```ts
247
- * const r = await sdk.compute.invokeUrlFetch({
248
- * prompt: "Voici l'URL https://tata.com — résume le service, " +
249
- * "identifie le style et la couleur primaire. JSON.",
250
- * });
251
- * console.log(r.content);
252
- * for (const c of r.citations) console.log(c.url, "→", c.citedText);
253
- * ```
254
- *
255
- * Mandate scope: requires `compute.url_fetch` (distinct from
256
- * `compute.invoke` — see {@link InvokeUrlFetchArgs.mandateId}).
257
- *
258
- * Pricing: same Claude 4.x rates as Bedrock (Anthropic's direct API
259
- * and Bedrock list prices are identical). Default Haiku 4.5 ≈
260
- * $0.001/1k input + $0.005/1k output. The proxy pre-debits a
261
- * conservative upper bound (`maxFetches × maxContentTokens × input
262
- * rate + maxTokens × output rate`) and reconciles down to the actual
263
- * usage Anthropic reports — so the wallet is always charged the
264
- * exact post-call cost.
265
- *
266
- * @throws {AithosSDKError} on protocol errors. Notable codes:
267
- * `sdk_no_signer`, `sdk_no_delegate_for_mandate`, `network`,
268
- * `http`, `empty`, plus proxy codes `-32042` (mandate scope
269
- * missing), `-32070`/`-32071` (wallet), `-32074` (fetch blocked
270
- * by robots.txt / domain filter), `-32050` (rate limit).
271
- */
272
- async invokeUrlFetch(args) {
273
- const { endpoints, fetch: fetchImpl } = this.#deps;
274
- const choice = this.#resolveSigner(args.mandateId);
275
- const url = computeInvokeUrl(endpoints);
276
- const idempotencyKey = args.idempotencyKey ?? generateIdempotencyKey();
277
- const model = args.model ?? "claude-haiku-4-5";
278
- const params = {
279
- app_did: this.#deps.appDid,
280
- mandate_id: this.#resolveMandateIdForWire(args.mandateId, choice),
281
- model,
282
- prompt: args.prompt,
283
- idempotency_key: idempotencyKey,
284
- };
285
- if (args.system !== undefined)
286
- params.system = args.system;
287
- if (args.maxTokens !== undefined)
288
- params.max_tokens = args.maxTokens;
289
- if (args.temperature !== undefined)
290
- params.temperature = args.temperature;
291
- if (args.maxFetches !== undefined)
292
- params.max_fetches = args.maxFetches;
293
- if (args.maxContentTokens !== undefined) {
294
- params.max_content_tokens = args.maxContentTokens;
295
- }
296
- if (args.citations !== undefined)
297
- params.citations = args.citations;
298
- if (args.allowedDomains !== undefined && args.allowedDomains.length > 0) {
299
- params.allowed_domains = args.allowedDomains;
300
- }
301
- if (args.blockedDomains !== undefined && args.blockedDomains.length > 0) {
302
- params.blocked_domains = args.blockedDomains;
303
- }
304
- return await this.#signAndPost({
305
- url,
306
- method: "aithos.compute_invoke_url_fetch",
307
- params,
308
- choice,
309
- fetchImpl,
310
- signal: args.signal,
311
- });
312
- }
313
237
  /**
314
238
  * Resolve the active signer (owner takes precedence over delegate).
315
239
  *
@@ -5,7 +5,7 @@ export { AithosSDKError } from "./types.js";
5
5
  export { AithosRpcError } from "@aithos/protocol-client";
6
6
  export type { AithosSdkEndpoints } from "./endpoints.js";
7
7
  export { DEFAULT_SDK_ENDPOINTS } from "./endpoints.js";
8
- export type { ComputeMessage, ImageAspectRatio, ImageModelId, InvokeBedrockArgs, InvokeBedrockResult, InvokeBedrockVisionArgs, InvokeBedrockVisionResult, InvokeImageArgs, InvokeImageImage, InvokeImageResult, InvokeSegmentationArgs, InvokeSegmentationResult, InvokeUrlFetchArgs, InvokeUrlFetchResult, SegmentPolygon, StopReason, UrlFetchCitation, UrlFetchMetadata, UrlFetchModelId, } from "./compute.js";
8
+ export type { ComputeMessage, ImageAspectRatio, ImageModelId, InvokeBedrockArgs, InvokeBedrockResult, InvokeBedrockVisionArgs, InvokeBedrockVisionResult, InvokeImageArgs, InvokeImageImage, InvokeImageResult, InvokeSegmentationArgs, InvokeSegmentationResult, SegmentPolygon, StopReason, } from "./compute.js";
9
9
  export { ComputeNamespace } from "./compute.js";
10
10
  export type { CreditPackId, CreateTopupSessionArgs, CreateTopupSessionResult, GetBalanceArgs, GetBalanceResult, } from "./wallet.js";
11
11
  export { WalletNamespace } from "./wallet.js";
@@ -187,166 +187,8 @@ describe("compute.invokeBedrock — abort", () => {
187
187
  assert.equal(receivedSignal, ac.signal);
188
188
  });
189
189
  });
190
- /* -------------------------------------------------------------------------- */
191
- /* invokeUrlFetch */
192
- /* -------------------------------------------------------------------------- */
193
- const URL_FETCH_HAPPY_RESULT = {
194
- content: "Tata.com propose un service Y avec une couleur primaire bleu (#1E40AF).",
195
- citations: [
196
- {
197
- url: "https://tata.com",
198
- citedText: "Notre service révolutionne...",
199
- documentTitle: "Tata — Home",
200
- startCharIndex: 0,
201
- endCharIndex: 28,
202
- },
203
- ],
204
- urlsFetched: [
205
- {
206
- url: "https://tata.com",
207
- retrievedAt: "2026-05-12T10:00:00Z",
208
- title: "Tata — Home",
209
- },
210
- ],
211
- stopReason: "end_turn",
212
- usage: { inputTokens: 28_500, outputTokens: 420, webFetchInvocations: 1 },
213
- creditsCharged: 35,
214
- walletBalance: 99_965,
215
- auditId: "audit-url-1",
216
- };
217
- describe("compute.invokeUrlFetch — happy path", () => {
218
- it("posts to ${compute}/v1/invoke with method=aithos.compute_invoke_url_fetch", async () => {
219
- let capturedUrl;
220
- let capturedInit;
221
- const fakeFetch = async (input, init) => {
222
- capturedUrl = typeof input === "string" ? input : input.toString();
223
- capturedInit = init;
224
- return new Response(JSON.stringify({ result: URL_FETCH_HAPPY_RESULT }), {
225
- status: 200,
226
- headers: { "content-type": "application/json" },
227
- });
228
- };
229
- const sdk = await makeSdk(fakeFetch);
230
- const out = await sdk.compute.invokeUrlFetch({
231
- mandateId: "mandate:abc",
232
- prompt: "Voici l'URL https://tata.com — résume.",
233
- });
234
- assert.deepEqual(out, URL_FETCH_HAPPY_RESULT);
235
- assert.equal(capturedUrl, "https://compute.example.test/v1/invoke");
236
- const body = JSON.parse(capturedInit?.body);
237
- assert.equal(body.jsonrpc, "2.0");
238
- assert.equal(body.method, "aithos.compute_invoke_url_fetch");
239
- assert.equal(body.params.app_did, APP_DID);
240
- assert.equal(body.params.mandate_id, "mandate:abc");
241
- // Default model is Haiku 4.5 (cheapest model that supports web_fetch).
242
- assert.equal(body.params.model, "claude-haiku-4-5");
243
- assert.equal(body.params.prompt, "Voici l'URL https://tata.com — résume.");
244
- // Auto-generated idempotency key.
245
- assert.match(body.params.idempotency_key, /^[0-9a-f]{32}$/);
246
- // Envelope is present on the wire.
247
- assert.ok(body.params._envelope, "request must carry a signed envelope");
248
- // Optional params NOT forwarded when not provided.
249
- assert.equal(body.params.system, undefined);
250
- assert.equal(body.params.max_fetches, undefined);
251
- assert.equal(body.params.max_content_tokens, undefined);
252
- assert.equal(body.params.citations, undefined);
253
- assert.equal(body.params.allowed_domains, undefined);
254
- assert.equal(body.params.blocked_domains, undefined);
255
- });
256
- it("forwards all optional knobs: system / maxTokens / maxFetches / maxContentTokens / citations / allowedDomains / idempotencyKey / model", async () => {
257
- let capturedBody;
258
- const fakeFetch = async (_input, init) => {
259
- capturedBody = JSON.parse(init?.body).params;
260
- return new Response(JSON.stringify({ result: URL_FETCH_HAPPY_RESULT }), {
261
- status: 200,
262
- headers: { "content-type": "application/json" },
263
- });
264
- };
265
- const sdk = await makeSdk(fakeFetch);
266
- await sdk.compute.invokeUrlFetch({
267
- mandateId: "mandate:abc",
268
- model: "claude-sonnet-4-6",
269
- prompt: "Analyse https://tata.com",
270
- system: "You are a brand analyst.",
271
- maxTokens: 1024,
272
- temperature: 0.1,
273
- maxFetches: 3,
274
- maxContentTokens: 50_000,
275
- citations: false,
276
- allowedDomains: ["tata.com", "*.tata.com"],
277
- idempotencyKey: "idem-url-1",
278
- });
279
- assert.equal(capturedBody?.model, "claude-sonnet-4-6");
280
- assert.equal(capturedBody?.system, "You are a brand analyst.");
281
- assert.equal(capturedBody?.max_tokens, 1024);
282
- assert.equal(capturedBody?.temperature, 0.1);
283
- assert.equal(capturedBody?.max_fetches, 3);
284
- assert.equal(capturedBody?.max_content_tokens, 50_000);
285
- assert.equal(capturedBody?.citations, false);
286
- assert.deepEqual(capturedBody?.allowed_domains, ["tata.com", "*.tata.com"]);
287
- assert.equal(capturedBody?.idempotency_key, "idem-url-1");
288
- // Empty / undefined arrays must NOT bleed through as `[]` on the wire.
289
- assert.equal(capturedBody?.blocked_domains, undefined);
290
- });
291
- it("omits empty allowedDomains / blockedDomains arrays from the wire payload", async () => {
292
- let capturedBody;
293
- const fakeFetch = async (_input, init) => {
294
- capturedBody = JSON.parse(init?.body).params;
295
- return new Response(JSON.stringify({ result: URL_FETCH_HAPPY_RESULT }), {
296
- status: 200,
297
- headers: { "content-type": "application/json" },
298
- });
299
- };
300
- const sdk = await makeSdk(fakeFetch);
301
- await sdk.compute.invokeUrlFetch({
302
- mandateId: "mandate:abc",
303
- prompt: "Analyse https://tata.com",
304
- allowedDomains: [],
305
- blockedDomains: [],
306
- });
307
- assert.equal(capturedBody?.allowed_domains, undefined);
308
- assert.equal(capturedBody?.blocked_domains, undefined);
309
- });
310
- });
311
- describe("compute.invokeUrlFetch — errors", () => {
312
- it("wraps a JSON-RPC error from the proxy as AithosSDKError with the proxy code", async () => {
313
- const fakeFetch = async () => new Response(JSON.stringify({
314
- error: {
315
- code: -32074,
316
- message: "web_fetch failed: robots.txt disallows /api/* — fetch refused",
317
- data: { detail: "robots_blocked" },
318
- },
319
- }), { status: 200, headers: { "content-type": "application/json" } });
320
- const sdk = await makeSdk(fakeFetch);
321
- await assert.rejects(sdk.compute.invokeUrlFetch({
322
- mandateId: "mandate:abc",
323
- prompt: "Analyse https://tata.com/api/secret",
324
- }), (err) => {
325
- assert.ok(err instanceof AithosSDKError);
326
- assert.equal(err.code, "-32074");
327
- assert.match(err.message, /robots\.txt/);
328
- return true;
329
- });
330
- });
331
- });
332
- describe("compute.invokeUrlFetch — abort", () => {
333
- it("propagates an AbortSignal to fetch", async () => {
334
- let receivedSignal;
335
- const fakeFetch = async (_input, init) => {
336
- receivedSignal = init?.signal;
337
- return new Response(JSON.stringify({ result: URL_FETCH_HAPPY_RESULT }), {
338
- status: 200,
339
- headers: { "content-type": "application/json" },
340
- });
341
- };
342
- const sdk = await makeSdk(fakeFetch);
343
- const ac = new AbortController();
344
- await sdk.compute.invokeUrlFetch({
345
- mandateId: "mandate:abc",
346
- prompt: "Analyse https://tata.com",
347
- signal: ac.signal,
348
- });
349
- assert.equal(receivedSignal, ac.signal);
350
- });
351
- });
190
+ // `compute.invokeUrlFetch` was removed in alpha.24 (BREAKING). The
191
+ // Anthropic API-direct + web_fetch tool path is replaced by the
192
+ // `sdk.web.extract` namespace which routes through the deterministic
193
+ // web-extractor Lambda. No tests here anymore.
352
194
  //# sourceMappingURL=compute.test.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aithos/sdk",
3
- "version": "0.1.0-alpha.23",
3
+ "version": "0.1.0-alpha.24",
4
4
  "description": "Aithos SDK \u2014 high-level TypeScript developer kit for building agentic apps on the Aithos protocol. Wraps @aithos/protocol-client and exposes the Aithos compute proxy and wallet (Stripe top-up) endpoints.",
5
5
  "keywords": [
6
6
  "aithos",