@enterstellar-ai/cloud 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1359 @@
1
+ import { EnterstellarError, EnterstellarErrorCode, ComponentContract, SemanticSearchResult, ForgeSignal, AgentTrace } from '@enterstellar-ai/types';
2
+
3
+ /**
4
+ * @module @enterstellar-ai/cloud/errors
5
+ * @description Cloud SDK error class and deterministic factory functions.
6
+ *
7
+ * `CloudError` extends `EnterstellarError` (from `@enterstellar-ai/types`) with Cloud-specific
8
+ * metadata: the server's error code (`cloudCode`), an optional upgrade URL
9
+ * for quota-exceeded scenarios, a retry-after duration, and the server's
10
+ * request ID for correlation.
11
+ *
12
+ * **Error code taxonomy:**
13
+ *
14
+ * | Namespace | Origin | Examples |
15
+ * |:----------------|:-----------------|:-----------------------------------|
16
+ * | `ENS-5xxx` | SDK-originated | `ENS-5001` (config), `ENS-5004` |
17
+ * | `ENS-C{NNNN}` | Server-originated| `ENS-C4290` (quota exceeded) |
18
+ *
19
+ * SDK-originated errors use `EnterstellarErrorCode` values directly (`ENS-5001`–
20
+ * `ENS-5005`). Server-originated errors store the cloud code in the
21
+ * `cloudCode` field and use `ENS-5003` as the base `EnterstellarError.code`
22
+ * (since `ENS-C{NNNN}` is not in the `EnterstellarErrorCode` union).
23
+ *
24
+ * Six factory functions provide deterministic, documented construction
25
+ * for every known error scenario — consumers never call `new CloudError()`
26
+ * directly.
27
+ *
28
+ * @see Design Choice SD3 — throw `CloudError` on 429 with `upgradeUrl`.
29
+ * @see Design Choice AG10 — `ENS-C{NNNN}` server error code format.
30
+ * @see Bible §9.4 — Cloud error response shape.
31
+ */
32
+
33
+ /**
34
+ * The structured error body returned by Enterstellar Cloud API endpoints.
35
+ *
36
+ * Parsed from the JSON response on non-2xx status codes. The `code` field
37
+ * uses the `ENS-C{NNNN}` format (AG10). Optional fields `retryAfterMs`
38
+ * and `upgradeUrl` are present only on `ENS-C4290` (quota exceeded).
39
+ *
40
+ * @example
41
+ * ```json
42
+ * {
43
+ * "code": "ENS-C4290",
44
+ * "message": "IPU quota exceeded",
45
+ * "retryAfterMs": 3600000,
46
+ * "upgradeUrl": "https://cloud.enterstellar.dev/billing/upgrade"
47
+ * }
48
+ * ```
49
+ *
50
+ * @see Bible §9.4 — Error response shape.
51
+ * @see Design Choice AG10 — `ENS-C{NNNN}` code format.
52
+ */
53
+ type CloudErrorBody = {
54
+ readonly code: string;
55
+ readonly message: string;
56
+ readonly retryAfterMs?: number | undefined;
57
+ readonly upgradeUrl?: string | undefined;
58
+ };
59
+ /**
60
+ * Cloud SDK error — extends `EnterstellarError` with Cloud-specific metadata.
61
+ *
62
+ * All `@enterstellar-ai/cloud` SDK errors are instances of both `CloudError` and
63
+ * `EnterstellarError`. Consumer catch blocks can narrow on either:
64
+ *
65
+ * ```ts
66
+ * try {
67
+ * await client.forge({ intent: 'patient vitals' });
68
+ * } catch (error) {
69
+ * if (error instanceof CloudError && error.upgradeUrl) {
70
+ * showUpgradePrompt(error.upgradeUrl);
71
+ * }
72
+ * }
73
+ * ```
74
+ *
75
+ * **Do not construct directly** — use the factory functions below.
76
+ *
77
+ * @see Design Choice SD3 — throw on 429 with `upgradeUrl` + `retryAfterMs`.
78
+ */
79
+ declare class CloudError extends EnterstellarError {
80
+ /**
81
+ * The Cloud-specific error code.
82
+ *
83
+ * For SDK-originated errors, this mirrors `EnterstellarError.code` (e.g., `'ENS-5001'`).
84
+ * For server-originated errors, this is the `ENS-C{NNNN}` code from the
85
+ * response body (e.g., `'ENS-C4290'`).
86
+ */
87
+ readonly cloudCode: string;
88
+ /**
89
+ * URL for the billing upgrade page.
90
+ * Present only on `ENS-C4290` (IPU quota exceeded) errors.
91
+ *
92
+ * @see Design Choice SD3 — app decides how to surface the upgrade prompt.
93
+ */
94
+ readonly upgradeUrl: string | undefined;
95
+ /**
96
+ * Milliseconds until the quota resets or rate limit expires.
97
+ * Present only on `ENS-C4290` errors.
98
+ *
99
+ * Use this to schedule a retry or display a countdown to the user.
100
+ */
101
+ readonly retryAfterMs: number | undefined;
102
+ /**
103
+ * The `X-Request-Id` header value from the server response.
104
+ * A bare ULID (AG16) for support ticket correlation.
105
+ * `undefined` if the error occurred before a server response was received
106
+ * (e.g., network failure, config validation).
107
+ */
108
+ readonly requestId: string | undefined;
109
+ /**
110
+ * @internal Use factory functions instead of constructing directly.
111
+ *
112
+ * @param code - The `EnterstellarErrorCode` for the base `EnterstellarError` class.
113
+ * @param cloudCode - The Cloud-specific error code (`ENS-5xxx` or `ENS-C{NNNN}`).
114
+ * @param message - Human-readable error description.
115
+ * @param recoverable - Whether the caller can meaningfully retry.
116
+ * @param options - Optional Cloud-specific metadata.
117
+ */
118
+ constructor(code: EnterstellarErrorCode, cloudCode: string, message: string, recoverable: boolean, options?: {
119
+ readonly upgradeUrl?: string | undefined;
120
+ readonly retryAfterMs?: number | undefined;
121
+ readonly requestId?: string | undefined;
122
+ readonly cause?: unknown;
123
+ });
124
+ /**
125
+ * Serializes the error to a plain object for logging, telemetry, or DevTools.
126
+ *
127
+ * Extends `EnterstellarError.toJSON()` with Cloud-specific fields.
128
+ *
129
+ * @returns A plain object representation including all Cloud metadata.
130
+ */
131
+ toJSON(): {
132
+ name: string;
133
+ code: EnterstellarErrorCode;
134
+ cloudCode: string;
135
+ module: 'cloud';
136
+ message: string;
137
+ recoverable: boolean;
138
+ timestamp: string;
139
+ upgradeUrl: string | undefined;
140
+ retryAfterMs: number | undefined;
141
+ requestId: string | undefined;
142
+ stack: string | undefined;
143
+ };
144
+ }
145
+
146
+ /**
147
+ * @module @enterstellar-ai/cloud/types
148
+ * @description Public and internal type definitions for the `@enterstellar-ai/cloud` SDK.
149
+ *
150
+ * This file defines the complete API surface of `@enterstellar-ai/cloud`:
151
+ *
152
+ * **Public types** (re-exported from barrel):
153
+ * - {@link CloudConfig} — client configuration (SD1, SD8, TA2, D111).
154
+ * - {@link EnterstellarCloudClient} — 13 methods + `forge.stream()` (SD2, SD6, §9.2).
155
+ * - {@link CloudResult} — universal return wrapper `{ data, ipu }` (SD7).
156
+ * - {@link CloudIPU} — IPU consumption metadata from response headers (§9.3).
157
+ * - {@link ForgeFragment} — SSE streaming fragment types (SD6, CF6).
158
+ * - {@link RouterPrediction} — intent routing prediction (IR2).
159
+ * - {@link AnalyticsQuery} / {@link AnalyticsResult} — trace/business analytics (TA5).
160
+ * - Pagination types: {@link TracePage}, {@link LedgerPage}.
161
+ * - {@link CertifyResult} — certification lifecycle (GI5, CR10).
162
+ *
163
+ * **Internal types** (not re-exported):
164
+ * - {@link CloudRequestConfig} — per-request transport configuration.
165
+ * - {@link CloudResponse} — parsed HTTP response from the transport layer.
166
+ *
167
+ * **Design philosophy:**
168
+ * - Types for data shapes (no methods).
169
+ * - Interfaces for objects with methods (`EnterstellarCloudClient`).
170
+ * - All fields `readonly` — immutable data structures.
171
+ * - Optional fields explicitly typed `T | undefined` (`exactOptionalPropertyTypes`).
172
+ * - Phase 1: types defined locally. Phase 2: migrated to `@enterstellar-cloud/types` (SD10).
173
+ *
174
+ * @see Bible §9.1–§9.4 — API surface, response headers, error shape.
175
+ * @see Design Choices SD1–SD10 — SDK locked decisions.
176
+ * @see Design Choice CL1 — hybrid IPU metering.
177
+ */
178
+
179
+ /**
180
+ * The Enterstellar product surface that originated the current SDK session.
181
+ *
182
+ * Set once on {@link CloudConfig.sessionType} and applied to all requests
183
+ * as a body field. The server stores this on `forge_signals`, `traces`,
184
+ * and `ipu_ledger` rows (D111). Used for stratified Router models at
185
+ * Phase 3 — different product surfaces generate different intent patterns.
186
+ *
187
+ * @see Design Choice D111 — `session_type TEXT DEFAULT 'app'`.
188
+ */
189
+ type SessionType = 'app' | 'browser' | 'os' | 'connect' | 'agent' | 'other';
190
+ /**
191
+ * Configuration for {@link createEnterstellarCloudClient}.
192
+ *
193
+ * **Minimal usage:**
194
+ * ```ts
195
+ * const client = createEnterstellarCloudClient({ apiKey: 'ak_my_project_key' });
196
+ * ```
197
+ *
198
+ * **Anonymous mode (SD1):**
199
+ * ```ts
200
+ * const client = createEnterstellarCloudClient({ apiKey: 'pk_anon_abc123' });
201
+ * // → Only submitSignal() is available. All other methods throw ENS-5004.
202
+ * ```
203
+ *
204
+ * **Changes from v0.0.x:**
205
+ * - `tier` removed — the server determines the tier from the API key.
206
+ * - `endpoint` renamed to `baseUrl` (SD8).
207
+ * - `traceConsent` added (TA2 dual-consent gate).
208
+ * - `sessionType` added (D111 product surface tag).
209
+ *
210
+ * @see Design Choice SD1 — auto-detect `pk_anon_` prefix → anonymous mode.
211
+ * @see Design Choice SD8 — default `baseUrl` = `https://api.enterstellar.dev`.
212
+ * @see Design Choice TA2 — dual-consent: client flag + server flag.
213
+ * @see Design Choice D111 — `session_type` on all request payloads.
214
+ */
215
+ type CloudConfig = {
216
+ /**
217
+ * API key for authenticating with Enterstellar Cloud.
218
+ *
219
+ * Two formats are supported:
220
+ * - `ak_<project_key>` — full mode, all methods available.
221
+ * - `pk_anon_<install_id>` — anonymous mode, only `submitSignal()` (SD1).
222
+ *
223
+ * The SDK auto-detects the key type by prefix. No separate mode parameter.
224
+ *
225
+ * @see Design Choice SD1 — auto-detect anonymous mode.
226
+ * @see Design Choice AG1 — key format: `ak_<uuid>`, `pk_anon_<uuid>`.
227
+ */
228
+ readonly apiKey: string;
229
+ /**
230
+ * Base URL of the Enterstellar Cloud API.
231
+ *
232
+ * Path segments (`/v1/forge`, `/v1/usage`, etc.) are appended automatically.
233
+ * Override for staging, self-hosted, or local development environments.
234
+ *
235
+ * @default 'https://api.enterstellar.dev'
236
+ *
237
+ * @see Design Choice SD8 — default with override.
238
+ */
239
+ readonly baseUrl?: string | undefined;
240
+ /**
241
+ * Global HTTP request timeout in milliseconds.
242
+ *
243
+ * When set, overrides ALL per-operation timeout defaults. When omitted,
244
+ * each operation uses its own default:
245
+ * - `forge` / `forge.stream()`: 30,000ms (P99 = 10s, 3× safety margin)
246
+ * - `certify`: 90,000ms (CR5: max 60s runtime + overhead)
247
+ * - `analytics` / `businessAnalytics`: 30,000ms (OLAP queries)
248
+ * - All other operations: 10,000ms
249
+ *
250
+ * Applied per-request via `AbortController`.
251
+ *
252
+ * @see Audit Finding F21 — per-operation timeout defaults.
253
+ */
254
+ readonly timeoutMs?: number | undefined;
255
+ /**
256
+ * Client-side trace consent flag (TA2 dual-consent gate).
257
+ *
258
+ * When `false` (default), `submitTrace()` returns immediately without
259
+ * making a network call — `{ data: { accepted: false }, ipu: null }`.
260
+ *
261
+ * Both this flag AND the per-trace `consent.anonymizedAggregation` field
262
+ * AND the server-side `projects.trace_consent` column must be `true`
263
+ * for a trace to reach the Cloud. Defense-in-depth.
264
+ *
265
+ * @default false
266
+ *
267
+ * @see Design Choice TA2 — dual-consent: client flag + server flag.
268
+ * @see Audit Finding F13 — mandatory client consent flag.
269
+ */
270
+ readonly traceConsent?: boolean | undefined;
271
+ /**
272
+ * The Enterstellar product surface originating this SDK session (D111).
273
+ *
274
+ * Applied to all request payloads. The server stores this value on
275
+ * `forge_signals.session_type`, `traces.session_type`, and
276
+ * `ipu_ledger.session_type` columns for stratified analytics.
277
+ *
278
+ * @default 'app'
279
+ *
280
+ * @see Design Choice D111 — `session_type TEXT DEFAULT 'app'`.
281
+ * @see Audit Finding F15 — session type on all submissions.
282
+ */
283
+ readonly sessionType?: SessionType | undefined;
284
+ };
285
+ /**
286
+ * IPU (Intent Processing Unit) consumption metadata from a single API call.
287
+ *
288
+ * Parsed from the `X-IPU-Used`, `X-IPU-Remaining`, and `X-IPU-Cost`
289
+ * response headers (§9.3). Part of every {@link CloudResult} wrapper.
290
+ *
291
+ * @see Design Choice SD7 — every method returns `{ data, ipu }`.
292
+ * @see Bible §9.3 — response header format.
293
+ */
294
+ type CloudIPU = {
295
+ /** Total IPUs consumed in the current billing period (`X-IPU-Used`). */
296
+ readonly used: number;
297
+ /** IPUs remaining in the current billing period (`X-IPU-Remaining`). */
298
+ readonly remaining: number;
299
+ /** IPUs charged for THIS specific request (`X-IPU-Cost`). */
300
+ readonly cost: number;
301
+ };
302
+ /**
303
+ * Universal return wrapper for all `EnterstellarCloudClient` methods.
304
+ *
305
+ * Every SDK method returns `{ data: T, ipu: CloudIPU | null }`.
306
+ * The `ipu` field is `null` for `pk_anon` requests — anonymous users
307
+ * have no IPU concept (AG8: all `X-IPU-*` headers omitted).
308
+ *
309
+ * **Changes from v0.0.x:**
310
+ * Replaces the bespoke `CloudForgeResult`, `CloudSearchResult`, and
311
+ * `CloudTraceResult` types. The `degraded` field is removed — operational
312
+ * errors now throw `CloudError` (SD3).
313
+ *
314
+ * @typeParam T - The payload type specific to the endpoint.
315
+ *
316
+ * @see Design Choice SD7 — universal return wrapper.
317
+ * @see Design Choice AG8 — `X-IPU-*` headers omitted for `pk_anon`.
318
+ *
319
+ * @example
320
+ * ```ts
321
+ * const { data: contract, ipu } = await client.forge({ intent: 'card' });
322
+ *
323
+ * if (ipu !== null) {
324
+ * console.log(`Remaining IPU: ${ipu.remaining}`);
325
+ * }
326
+ * ```
327
+ */
328
+ type CloudResult<T> = {
329
+ /** The endpoint-specific payload. */
330
+ readonly data: T;
331
+ /**
332
+ * IPU consumption metadata from response headers.
333
+ * `null` for `pk_anon` requests (no IPU concept in anonymous mode).
334
+ */
335
+ readonly ipu: CloudIPU | null;
336
+ };
337
+ /**
338
+ * IPU usage summary for the current billing period.
339
+ *
340
+ * Returned by `EnterstellarCloudClient.getUsage()` (`GET /v1/usage`).
341
+ * The server is authoritative — these values reconcile the local
342
+ * IPU tracker (CL1 hybrid tracking).
343
+ *
344
+ * @see Design Choice CL1 — hybrid metering, server authoritative.
345
+ * @see Design Choice CL2 — weighted IPU costs per operation.
346
+ * @see Design Choice AM11 — billing period is anniversary-based.
347
+ */
348
+ type CloudUsage = {
349
+ /** Total IPUs consumed in the current billing period. */
350
+ readonly used: number;
351
+ /** IPU limit for the current billing period (tier-dependent). */
352
+ readonly limit: number;
353
+ /**
354
+ * The project's service tier as reported by the server.
355
+ *
356
+ * A `string` (not a fixed union) to avoid breaking when new tiers
357
+ * are added server-side. Known values: `'free'`, `'starter'`,
358
+ * `'pro'`, `'enterprise'`.
359
+ */
360
+ readonly tier: string;
361
+ };
362
+ /**
363
+ * Options for `EnterstellarCloudClient.forge()` and `forge.stream()`.
364
+ *
365
+ * The `intent` field is the natural-language description of the desired
366
+ * component. Optional `constraints` allow the caller to pass additional
367
+ * generation hints (allowed tokens, max props, required states, etc.)
368
+ * to the CloudForge LLM prompt.
369
+ *
370
+ * @see Design Choice SD6 — dual forge API: `forge()` + `forge.stream()`.
371
+ * @see Design Choice F5 — LLM with system prompt constraints.
372
+ */
373
+ type ForgeOptions = {
374
+ /** Natural-language description of the desired component. */
375
+ readonly intent: string;
376
+ /**
377
+ * Additional generation constraints passed to the CloudForge prompt.
378
+ *
379
+ * These are forwarded as-is to the server's prompt builder. Known
380
+ * keys include `designTokens`, `maxComplexity`, `requiredStates`,
381
+ * `accessibility`. Unknown keys are silently ignored by the server.
382
+ */
383
+ readonly constraints?: Readonly<Record<string, unknown>> | undefined;
384
+ };
385
+ /**
386
+ * A single fragment yielded by `forge.stream()` during SSE streaming.
387
+ *
388
+ * The CloudForge endpoint (`POST /v1/forge`) streams Server-Sent Events
389
+ * (SSE) with typed `event:` fields (CF6). The SDK's SSE transport parses
390
+ * these into `ForgeFragment` objects and yields them via `AsyncGenerator`.
391
+ *
392
+ * **Fragment lifecycle:**
393
+ * 1. `meta` — first fragment, contains provider info and IPU data (F18).
394
+ * 2. `node` / `property` — zero or more data fragments as the LLM streams.
395
+ * 3. `complete` — final fragment with the full `ComponentContract` and IPU (F18).
396
+ * 4. `error` — emitted instead of `complete` if the generation fails.
397
+ *
398
+ * **IPU delivery (F18):** The `ipu` field is present on `meta` and `complete`
399
+ * fragments only. It is parsed from the HTTP response headers (available at
400
+ * stream start). Callers who only care about billing info can read it from
401
+ * either the first or last fragment.
402
+ *
403
+ * @see Design Choice SD6 — `forge.stream()` returns `AsyncGenerator<ForgeFragment>`.
404
+ * @see Design Choice CF6 — SSE event types: `node`, `property`, `complete`, `error`, `meta`.
405
+ * @see Design Choice CF9 — provider identity via SSE `meta` event.
406
+ * @see Audit Finding F18 — IPU delivery on `meta` and `complete` fragments.
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * for await (const fragment of client.forge.stream({ intent: 'card' })) {
411
+ * switch (fragment.type) {
412
+ * case 'meta':
413
+ * console.log(`Provider: ${fragment.data.provider}`);
414
+ * break;
415
+ * case 'complete':
416
+ * registerContract(fragment.data);
417
+ * break;
418
+ * case 'error':
419
+ * console.error(`Forge error: ${fragment.data.message}`);
420
+ * break;
421
+ * }
422
+ * }
423
+ * ```
424
+ */
425
+ type ForgeFragment = ForgeMetaFragment | ForgeNodeFragment | ForgePropertyFragment | ForgeCompleteFragment | ForgeErrorFragment;
426
+ /**
427
+ * SSE `meta` event — first fragment in the stream.
428
+ *
429
+ * Contains the LLM provider and model information (CF9), and IPU
430
+ * consumption data parsed from the HTTP response headers.
431
+ */
432
+ type ForgeMetaFragment = {
433
+ readonly type: 'meta';
434
+ /** Provider and model metadata delivered via SSE `meta` event (CF9). */
435
+ readonly data: {
436
+ /** The LLM provider used for this generation (e.g., `'anthropic'`, `'openai'`). */
437
+ readonly provider: string;
438
+ /** The specific model used (e.g., `'claude-sonnet-4-20250514'`). */
439
+ readonly model: string;
440
+ };
441
+ /** IPU consumption from HTTP response headers. `null` for `pk_anon`. */
442
+ readonly ipu: CloudIPU | null;
443
+ };
444
+ /**
445
+ * SSE `node` event — partial contract structure.
446
+ *
447
+ * Emitted as the LLM streams structural components of the contract.
448
+ * Contains a partial `ComponentContract` that can be used for
449
+ * progressive rendering of the generation process.
450
+ */
451
+ type ForgeNodeFragment = {
452
+ readonly type: 'node';
453
+ /** Partial contract data for progressive rendering. */
454
+ readonly data: Partial<ComponentContract>;
455
+ };
456
+ /**
457
+ * SSE `property` event — individual property update.
458
+ *
459
+ * Emitted as the LLM resolves specific contract properties.
460
+ * The `path` field uses dot notation for nested properties
461
+ * (e.g., `'tokens.background'`, `'accessibility.role'`).
462
+ */
463
+ type ForgePropertyFragment = {
464
+ readonly type: 'property';
465
+ /** Property path and value for incremental updates. */
466
+ readonly data: {
467
+ /** Dot-notation path to the property within the contract. */
468
+ readonly path: string;
469
+ /** The resolved property value. */
470
+ readonly value: unknown;
471
+ };
472
+ };
473
+ /**
474
+ * SSE `complete` event — final fragment with the full contract.
475
+ *
476
+ * Emitted once when the LLM finishes generation. Contains the complete,
477
+ * validated `ComponentContract` and IPU consumption data.
478
+ */
479
+ type ForgeCompleteFragment = {
480
+ readonly type: 'complete';
481
+ /** The complete, validated `ComponentContract` from the CloudForge LLM. */
482
+ readonly data: ComponentContract;
483
+ /** IPU consumption from HTTP response headers. `null` for `pk_anon`. */
484
+ readonly ipu: CloudIPU | null;
485
+ };
486
+ /**
487
+ * SSE `error` event — generation failure.
488
+ *
489
+ * Emitted instead of `complete` when the generation fails (LLM error,
490
+ * validation failure, provider timeout). The stream terminates after
491
+ * this fragment.
492
+ */
493
+ type ForgeErrorFragment = {
494
+ readonly type: 'error';
495
+ /** Error details from the server. */
496
+ readonly data: {
497
+ /** The `ENS-C{NNNN}` error code from the server. */
498
+ readonly code: string;
499
+ /** Human-readable error description. */
500
+ readonly message: string;
501
+ };
502
+ };
503
+ /**
504
+ * The callable type for `EnterstellarCloudClient.forge`.
505
+ *
506
+ * `forge` is both directly callable (returns a `Promise`) and has a
507
+ * `.stream()` method (returns an `AsyncGenerator`). This is achieved
508
+ * via TypeScript intersection: `ForgeFunction & { stream: ... }`.
509
+ *
510
+ * @see Design Choice SD6 — dual API: `forge()` + `forge.stream()`.
511
+ */
512
+ type ForgeFunction = (options: ForgeOptions) => Promise<CloudResult<ComponentContract>>;
513
+ /**
514
+ * Response shape for `POST /v1/route` — intent routing prediction.
515
+ *
516
+ * Contains an array of component predictions ranked by confidence, plus
517
+ * metadata about the model that produced them. For unknown intents,
518
+ * `predictions` is empty and metadata reflects the lookup context (IR3).
519
+ *
520
+ * **Batch ordering guarantee (F19):** When returned from `routeBatch()`,
521
+ * the array index matches the input index: `result.data[i]` corresponds
522
+ * to `intentHashes[i]`.
523
+ *
524
+ * @see Design Choice IR2 — response shape with predictions + metadata.
525
+ * @see Design Choice IR3 — empty predictions for unknown intents.
526
+ * @see Audit Finding F10 — type defined per IR2 shape.
527
+ * @see Audit Finding F19 — batch ordering documented as invariant.
528
+ *
529
+ * @example
530
+ * ```ts
531
+ * const { data } = await client.route('a1b2c3...');
532
+ *
533
+ * if (data.predictions.length > 0 && data.predictions[0].confidence >= 0.8) {
534
+ * // Use Router prediction — skip Forge.
535
+ * useComponent(data.predictions[0].componentName);
536
+ * }
537
+ * ```
538
+ */
539
+ type RouterPrediction = {
540
+ /** Ranked component predictions, highest confidence first. */
541
+ readonly predictions: readonly {
542
+ /** The predicted component name (PascalCase). */
543
+ readonly componentName: string;
544
+ /**
545
+ * Confidence score (0.0–1.0).
546
+ * Based on frequency data (Phase 2) or ML model (Phase 3, IR4).
547
+ */
548
+ readonly confidence: number;
549
+ /**
550
+ * URL of the federated registry where this contract is published.
551
+ * Present only for contracts from federated registries (GI1).
552
+ * `undefined` for contracts in the Global Index.
553
+ */
554
+ readonly registryUrl?: string | undefined;
555
+ }[];
556
+ /** Metadata about the prediction model and data quality. */
557
+ readonly metadata: {
558
+ /**
559
+ * Version identifier for the routing model or frequency table.
560
+ * Used for debugging and A/B testing (IR6).
561
+ */
562
+ readonly modelVersion: string;
563
+ /**
564
+ * Number of ForgeSignals backing this prediction.
565
+ * Higher count → higher statistical confidence.
566
+ */
567
+ readonly signalCount: number;
568
+ };
569
+ };
570
+ /**
571
+ * Query payload for `analytics()` and `businessAnalytics()`.
572
+ *
573
+ * Fixed query types map to pre-built, optimized ClickHouse queries.
574
+ * Each type has a known cost profile: 5 IPU per analytics call (§9.1).
575
+ *
576
+ * **Note (F17):** Bible §9.1 specifies `GET` for analytics endpoints,
577
+ * but this payload requires a JSON body. The SDK uses `POST` — a Bible
578
+ * §9.1 amendment has been flagged.
579
+ *
580
+ * @see Design Choice TA5 — fixed query types with filters.
581
+ * @see Audit Finding F17 — POST instead of GET for JSON body.
582
+ */
583
+ type AnalyticsQuery = {
584
+ /**
585
+ * The type of analytics query to execute.
586
+ * Each maps to a pre-built ClickHouse query with known cost (5 IPU).
587
+ */
588
+ readonly queryType: 'intent_patterns' | 'component_performance' | 'journey_reconstruction' | 'anomalies';
589
+ /**
590
+ * Query filters applied to the ClickHouse query.
591
+ *
592
+ * Known filter keys: `timeRange`, `projectId`, `intentCategory`, `limit`.
593
+ * Unknown keys are silently ignored by the server.
594
+ */
595
+ readonly filters?: Readonly<Record<string, unknown>> | undefined;
596
+ };
597
+ /**
598
+ * Result payload from `analytics()` and `businessAnalytics()`.
599
+ *
600
+ * Contains the query results as an array of rows, plus the query type
601
+ * that produced them (for client-side discrimination).
602
+ */
603
+ type AnalyticsResult = {
604
+ /** Query result rows. Schema varies by `queryType`. */
605
+ readonly rows: readonly Readonly<Record<string, unknown>>[];
606
+ /** The query type that produced these results (echoed from the request). */
607
+ readonly queryType: string;
608
+ };
609
+ /**
610
+ * Options for `EnterstellarCloudClient.getTraces()` — paginated trace listing.
611
+ *
612
+ * All fields are optional. When omitted, returns the most recent traces
613
+ * for the authenticated project.
614
+ */
615
+ type TraceListOptions = {
616
+ /** Filter by correlation ID (groups related traces across operations). */
617
+ readonly correlationId?: string | undefined;
618
+ /** Filter by thread ID (groups traces within a single conversation). */
619
+ readonly threadId?: string | undefined;
620
+ /**
621
+ * Pagination cursor from a previous response's `TracePage.cursor`.
622
+ * Omit for the first page.
623
+ */
624
+ readonly cursor?: string | undefined;
625
+ /**
626
+ * Maximum number of traces to return per page.
627
+ *
628
+ * @default 50
629
+ */
630
+ readonly limit?: number | undefined;
631
+ };
632
+ /**
633
+ * Paginated response for `getTraces()`.
634
+ *
635
+ * Uses cursor-based pagination — pass `cursor` to `TraceListOptions`
636
+ * to fetch the next page. When `hasMore` is `false`, all traces have
637
+ * been returned.
638
+ */
639
+ type TracePage = {
640
+ /** Trace records for this page. */
641
+ readonly items: readonly Readonly<Record<string, unknown>>[];
642
+ /**
643
+ * Cursor for fetching the next page.
644
+ * `null` when there are no more results.
645
+ */
646
+ readonly cursor: string | null;
647
+ /** Whether more pages are available after this one. */
648
+ readonly hasMore: boolean;
649
+ };
650
+ /**
651
+ * Options for `EnterstellarCloudClient.getLedger()` — paginated IPU ledger listing.
652
+ *
653
+ * Returns per-operation IPU charges for audit and billing verification.
654
+ * lookback period is tier-dependent (§9.1).
655
+ */
656
+ type LedgerListOptions = {
657
+ /**
658
+ * Pagination cursor from a previous response's `LedgerPage.cursor`.
659
+ * Omit for the first page.
660
+ */
661
+ readonly cursor?: string | undefined;
662
+ /**
663
+ * Maximum number of ledger entries to return per page.
664
+ *
665
+ * @default 50
666
+ */
667
+ readonly limit?: number | undefined;
668
+ };
669
+ /**
670
+ * Paginated response for `getLedger()`.
671
+ *
672
+ * Each item is an IPU ledger entry with `operation`, `ipu_cost`,
673
+ * `timestamp`, and `request_id` fields.
674
+ */
675
+ type LedgerPage = {
676
+ /** Ledger entries for this page. */
677
+ readonly items: readonly Readonly<Record<string, unknown>>[];
678
+ /**
679
+ * Cursor for fetching the next page.
680
+ * `null` when there are no more results.
681
+ */
682
+ readonly cursor: string | null;
683
+ /** Whether more pages are available after this one. */
684
+ readonly hasMore: boolean;
685
+ };
686
+ /**
687
+ * Result of `EnterstellarCloudClient.certify()` — "Enterstellar Certified" lifecycle initiation.
688
+ *
689
+ * The certification process is asynchronous:
690
+ * 1. `POST /v1/contracts/:id/certify` → `pending` (20 IPU charge, GI5).
691
+ * 2. Certification Runner executes tests on Fly.io microVM (CR5: max 60s).
692
+ * 3. Publisher polls `GET /v1/contracts/:id` and checks `certification_status`.
693
+ *
694
+ * The SDK returns the initial `pending` state with the polling URL.
695
+ * The caller is responsible for polling via the Global Index package.
696
+ *
697
+ * @see Design Choice GI5 — `pending → running → certified | failed`.
698
+ * @see Design Choice CR10 — polling on `GET /v1/contracts/:id`.
699
+ * @see Audit Finding F14 — type defined per GI5 shape.
700
+ */
701
+ type CertifyResult = {
702
+ /**
703
+ * The initial certification status. Always `'pending'` at creation time.
704
+ * The full lifecycle is: `none → pending → running → certified | failed`.
705
+ */
706
+ readonly status: 'pending';
707
+ /**
708
+ * URL path for polling certification status.
709
+ * Typically `'/v1/contracts/{contractId}'`. The caller polls this
710
+ * endpoint and checks the `certification_status` field.
711
+ *
712
+ * @see Design Choice CR10 — polling-based notification.
713
+ */
714
+ readonly pollUrl: string;
715
+ };
716
+ /**
717
+ * The Enterstellar Cloud SDK client — primary public API of `@enterstellar-ai/cloud`.
718
+ *
719
+ * Created via {@link createEnterstellarCloudClient}. Provides access to all
720
+ * Cloud-hosted capabilities: forge generation, semantic search, intent
721
+ * routing, trace analytics, IPU metering, and contract certification.
722
+ *
723
+ * **13 methods + `forge.stream()`** (per Bible §9.2):
724
+ *
725
+ * | Category | Methods | IPU |
726
+ * |:-----------------|:------------------------------------------------|:-----------|
727
+ * | **Generation** | `forge()`, `forge.stream()` | 10 |
728
+ * | **Search** | `search()` | 1 |
729
+ * | **Routing** | `route()`, `routeBatch()` | 1, 1×N |
730
+ * | **Signals** | `submitSignal()` | 0 (pk_anon)|
731
+ * | **Traces** | `submitTrace()`, `getTraces()` | 0 |
732
+ * | **Analytics** | `analytics()`, `businessAnalytics()` | 5 |
733
+ * | **Billing** | `getUsage()`, `getLedger()` | 0 |
734
+ * | **Operations** | `certify()`, `deleteProjectData()` | 20, 0 |
735
+ * | **Lifecycle** | `dispose()` | — |
736
+ *
737
+ * **Error policy (SD3):**
738
+ * - 429 (quota exceeded) → throw `CloudError` with `upgradeUrl` + `retryAfterMs`.
739
+ * - 5xx / network → retry 3× (SD5), then throw `CloudError` (`ENS-5005`).
740
+ * - 4xx (non-429) → throw `CloudError` immediately, no retry.
741
+ * - Post-dispose → throw `CloudError` (`ENS-5002`).
742
+ * - Anonymous mode → non-signal methods throw `CloudError` (`ENS-5004`).
743
+ *
744
+ * **Anonymous mode (SD1):**
745
+ * Clients created with `pk_anon_*` keys can only call `submitSignal()`
746
+ * and `dispose()`. All other methods throw `ENS-5004`.
747
+ *
748
+ * @see Bible §9.2 — SDK ↔ Cloud endpoint mapping.
749
+ * @see Design Choice SD2 — 8 new methods added (minor version bump).
750
+ * @see Design Choice SD3 — throw `CloudError` on 429.
751
+ * @see Design Choice SD6 — dual forge API: `forge()` + `forge.stream()`.
752
+ * @see Design Choice SD7 — every method returns `CloudResult<T>`.
753
+ *
754
+ * @example
755
+ * ```ts
756
+ * import { createEnterstellarCloudClient, CloudError } from '@enterstellar-ai/cloud';
757
+ *
758
+ * const client = createEnterstellarCloudClient({ apiKey: 'ak_my_key' });
759
+ *
760
+ * try {
761
+ * const { data: contract, ipu } = await client.forge({ intent: 'patient vitals card' });
762
+ * console.log(`Generated: ${contract.name}, IPU remaining: ${ipu?.remaining}`);
763
+ * } catch (error) {
764
+ * if (error instanceof CloudError && error.upgradeUrl) {
765
+ * showUpgradePrompt(error.upgradeUrl);
766
+ * }
767
+ * } finally {
768
+ * client.dispose();
769
+ * }
770
+ * ```
771
+ */
772
+ interface EnterstellarCloudClient {
773
+ /**
774
+ * Generate a `ComponentContract` via CloudForge.
775
+ *
776
+ * Callable and has a `.stream()` method for SSE streaming:
777
+ * - `forge(options)` → `Promise<CloudResult<ComponentContract>>` (buffers full stream).
778
+ * - `forge.stream(options)` → `AsyncGenerator<ForgeFragment>` (yields fragments).
779
+ *
780
+ * **IPU cost:** 10 per invocation (§9.1).
781
+ * **Timeout:** 30s default (P99 = 10s, §8.9).
782
+ * **Idempotency:** `X-Idempotency-Key` sent (AM10).
783
+ *
784
+ * @throws {CloudError} `ENS-C4290` if IPU quota exceeded (SD3).
785
+ * @throws {CloudError} `ENS-5005` if all 3 retries fail (SD5).
786
+ * @throws {CloudError} `ENS-5002` if client is disposed.
787
+ * @throws {CloudError} `ENS-5004` if in anonymous mode.
788
+ *
789
+ * @see Design Choice SD6 — dual API: `forge()` + `forge.stream()`.
790
+ * @see Design Choice CL2 — CloudForge = 10 IPU.
791
+ */
792
+ forge: ForgeFunction & {
793
+ /**
794
+ * Stream CloudForge generation via Server-Sent Events.
795
+ *
796
+ * Yields {@link ForgeFragment} objects as the LLM generates the
797
+ * contract. Use this for progressive rendering. The generator
798
+ * completes when a `complete` or `error` fragment is yielded.
799
+ *
800
+ * @param options - Forge generation options.
801
+ * @yields {ForgeFragment} Typed SSE fragments.
802
+ *
803
+ * @see Design Choice CF6 — SSE event types.
804
+ * @see Design Choice CF14 — SSE streaming format.
805
+ */
806
+ stream(options: ForgeOptions): AsyncGenerator<ForgeFragment, void, undefined>;
807
+ };
808
+ /**
809
+ * Search for components via Cloud Semantic Index.
810
+ *
811
+ * Proxies to `POST /v1/semantic-search`. Uses the authenticated
812
+ * project's private Vectorize index (optionally including the
813
+ * Global Index — see §9.1 note on search scope).
814
+ *
815
+ * **IPU cost:** 1 per invocation (§9.1).
816
+ * **Timeout:** 10s default.
817
+ * **Idempotency:** `X-Idempotency-Key` sent (AM10).
818
+ *
819
+ * @param query - Natural language search query (intent string).
820
+ * @param topK - Maximum number of results. Defaults to 5 (SI5).
821
+ * @returns Semantic search results with IPU metadata.
822
+ *
823
+ * @throws {CloudError} `ENS-C4290` if IPU quota exceeded.
824
+ * @throws {CloudError} `ENS-5005` if all retries fail.
825
+ * @throws {CloudError} `ENS-5002` if disposed. `ENS-5004` if anonymous.
826
+ *
827
+ * @see Design Choice CL2 — semantic search = 1 IPU.
828
+ */
829
+ search(query: string, topK?: number): Promise<CloudResult<readonly SemanticSearchResult[]>>;
830
+ /**
831
+ * Predict the component for a single intent hash.
832
+ *
833
+ * Proxies to `POST /v1/route`. Returns ranked predictions with
834
+ * confidence scores and metadata. For unknown intents, returns
835
+ * empty predictions (IR3) — the caller should fall through to Forge.
836
+ *
837
+ * **IPU cost:** 1 per invocation (§9.1).
838
+ * **Timeout:** 10s default.
839
+ *
840
+ * @param intentHash - SHA-256 hash of the intent string.
841
+ * @returns Ranked predictions with model metadata.
842
+ *
843
+ * @throws {CloudError} On quota, retry exhaustion, disposal, or anonymous mode.
844
+ *
845
+ * @see Design Choice IR2 — response shape.
846
+ * @see Design Choice IR3 — empty predictions for unknown intents.
847
+ */
848
+ route(intentHash: string): Promise<CloudResult<RouterPrediction>>;
849
+ /**
850
+ * Predict components for a batch of intent hashes (pre-rendering).
851
+ *
852
+ * Proxies to `POST /v1/route/batch`. Send likely next intents
853
+ * (e.g., from visible buttons) to pre-resolve contracts ahead of time.
854
+ *
855
+ * **IPU cost:** 1 × N per invocation (§9.1), where N = `intentHashes.length`.
856
+ * **Timeout:** 10s default.
857
+ *
858
+ * **Ordering guarantee (F19):** `result.data[i]` corresponds to
859
+ * `intentHashes[i]`. The server preserves input order.
860
+ *
861
+ * @param intentHashes - Array of SHA-256 intent hashes to resolve.
862
+ * @returns Array of predictions in the same order as input.
863
+ *
864
+ * @throws {CloudError} On quota, retry exhaustion, disposal, or anonymous mode.
865
+ *
866
+ * @see Design Choice IR5 — batch routing for pre-rendering.
867
+ * @see Audit Finding F19 — batch ordering invariant.
868
+ */
869
+ routeBatch(intentHashes: readonly string[]): Promise<CloudResult<readonly RouterPrediction[]>>;
870
+ /**
871
+ * Submit a `ForgeSignal` to the Cloud corpus.
872
+ *
873
+ * Proxies to `POST /v1/signals`. This is the **only method that works
874
+ * in anonymous mode** (`pk_anon_*` keys). The SDK transparently sets
875
+ * `Authorization: Bearer pk_anon_<install_id>` (SD4).
876
+ *
877
+ * **IPU cost:** 0 — signal ingestion is free (§9.1: "data collection
878
+ * is our #1 strategic asset — never charge for it").
879
+ * **No idempotency key** — 0 IPU, not required (AM10/F8).
880
+ *
881
+ * @param signal - The `ForgeSignal` to submit (from `@enterstellar-ai/telemetry`).
882
+ * @returns Acceptance confirmation.
883
+ *
884
+ * @throws {CloudError} `ENS-5005` if all retries fail. `ENS-5002` if disposed.
885
+ *
886
+ * @see Design Choice SD1 — anonymous mode: only `submitSignal()` available.
887
+ * @see Design Choice SD4 — `@enterstellar-ai/telemetry` uses SDK with `pk_anon`.
888
+ */
889
+ submitSignal(signal: ForgeSignal): Promise<CloudResult<{
890
+ readonly accepted: boolean;
891
+ }>>;
892
+ /**
893
+ * Submit an `AgentTrace` for cloud aggregation and analytics.
894
+ *
895
+ * Proxies to `POST /v1/traces`. **Triple consent gate (TA2, F13):**
896
+ * 1. `CloudConfig.traceConsent` must be `true` (client SDK flag).
897
+ * 2. `trace.consent.anonymizedAggregation` must be `true` (per-trace).
898
+ * 3. Server-side `projects.trace_consent` must be `true` (project flag).
899
+ *
900
+ * If either client-side check fails, returns immediately with
901
+ * `{ data: { accepted: false }, ipu: null }` — no network call.
902
+ *
903
+ * **IPU cost:** 0 — trace submission is free (§9.1 corrected).
904
+ *
905
+ * @param trace - The `AgentTrace` to submit. Must have consent fields.
906
+ * @returns Acceptance confirmation.
907
+ *
908
+ * @throws {CloudError} `ENS-5005` if all retries fail.
909
+ * @throws {CloudError} `ENS-5002` if disposed. `ENS-5004` if anonymous.
910
+ *
911
+ * @see Design Choice TA2 — dual-consent gate.
912
+ * @see Design Choice CL2 — trace submission = 0 IPU (corrected from 5).
913
+ */
914
+ submitTrace(trace: AgentTrace): Promise<CloudResult<{
915
+ readonly accepted: boolean;
916
+ }>>;
917
+ /**
918
+ * Query traces for the authenticated project.
919
+ *
920
+ * Proxies to `GET /v1/traces`. Returns paginated results filtered
921
+ * by `correlation_id` and/or `thread_id`.
922
+ *
923
+ * **IPU cost:** 0 (§9.1).
924
+ *
925
+ * @param options - Pagination and filter options. All optional.
926
+ * @returns Paginated trace listing.
927
+ *
928
+ * @throws {CloudError} `ENS-5002` if disposed. `ENS-5004` if anonymous.
929
+ */
930
+ getTraces(options?: TraceListOptions): Promise<CloudResult<TracePage>>;
931
+ /**
932
+ * Query trace analytics from ClickHouse.
933
+ *
934
+ * Proxies to `POST /v1/traces/analytics` (dedicated analytics Worker,
935
+ * TA3). Fixed query types with filters (TA5).
936
+ *
937
+ * **IPU cost:** 5 per invocation (§9.1).
938
+ * **Timeout:** 30s default (OLAP queries).
939
+ *
940
+ * @param query - The analytics query with `queryType` and optional `filters`.
941
+ * @returns Analytics result rows.
942
+ *
943
+ * @throws {CloudError} On quota, retry exhaustion, disposal, or anonymous mode.
944
+ *
945
+ * @see Design Choice TA3 — dedicated analytics Worker.
946
+ * @see Design Choice TA5 — fixed query types.
947
+ */
948
+ analytics(query: AnalyticsQuery): Promise<CloudResult<AnalyticsResult>>;
949
+ /**
950
+ * Query business/product analytics from ClickHouse.
951
+ *
952
+ * Proxies to `POST /v1/analytics/query`. Separate from trace analytics
953
+ * — this powers the Business Intelligence dashboard features (TA10).
954
+ *
955
+ * **IPU cost:** 5 per invocation (§9.1).
956
+ * **Timeout:** 30s default.
957
+ *
958
+ * @param query - The analytics query with `queryType` and optional `filters`.
959
+ * @returns Analytics result rows.
960
+ *
961
+ * @throws {CloudError} On quota, retry exhaustion, disposal, or anonymous mode.
962
+ *
963
+ * @see Design Choice TA10 — Enterstellar Analytics (separate from Trace Analytics).
964
+ */
965
+ businessAnalytics(query: AnalyticsQuery): Promise<CloudResult<AnalyticsResult>>;
966
+ /**
967
+ * Query IPU usage for the current billing period.
968
+ *
969
+ * Proxies to `GET /v1/usage`. The returned values are server-authoritative
970
+ * and reconcile the local IPU tracker (CL1 hybrid tracking).
971
+ *
972
+ * **IPU cost:** 0 (§9.1).
973
+ *
974
+ * @returns Current IPU usage, limit, and tier.
975
+ *
976
+ * @throws {CloudError} `ENS-5003` on fetch failure.
977
+ * @throws {CloudError} `ENS-5002` if disposed. `ENS-5004` if anonymous.
978
+ *
979
+ * @see Design Choice CL1 — hybrid metering, server authoritative.
980
+ */
981
+ getUsage(): Promise<CloudResult<CloudUsage>>;
982
+ /**
983
+ * Query the per-operation IPU ledger.
984
+ *
985
+ * Proxies to `GET /v1/usage/ledger`. Returns paginated IPU charges
986
+ * for audit and billing verification. Lookback period is tier-dependent.
987
+ *
988
+ * **IPU cost:** 0 (§9.1).
989
+ *
990
+ * @param options - Pagination options. All optional.
991
+ * @returns Paginated ledger entries.
992
+ *
993
+ * @throws {CloudError} `ENS-5002` if disposed. `ENS-5004` if anonymous.
994
+ *
995
+ * @see Design Choice AM13 — IPU ledger exposure to customers.
996
+ */
997
+ getLedger(options?: LedgerListOptions): Promise<CloudResult<LedgerPage>>;
998
+ /**
999
+ * Initiate "Enterstellar Certified" audit for a published contract.
1000
+ *
1001
+ * Proxies to `POST /v1/contracts/:id/certify`. Deducts 20 IPU,
1002
+ * enqueues the certification job, and returns a `pending` status
1003
+ * with a polling URL (GI5). The Certification Runner executes
1004
+ * tests on a Fly.io microVM (CR5, max 60s).
1005
+ *
1006
+ * Poll `GET /v1/contracts/:id` (via `@enterstellar-ai/global-index`) to check
1007
+ * `certification_status` for completion (CR10).
1008
+ *
1009
+ * **IPU cost:** 20 per invocation (§9.1).
1010
+ * **Timeout:** 90s default (CR5: max 60s + overhead).
1011
+ * **Idempotency:** `X-Idempotency-Key` sent (AM10).
1012
+ *
1013
+ * @param contractId - The contract ID to certify (e.g., `'comp_01HYX...'`).
1014
+ * @returns Pending status with polling URL.
1015
+ *
1016
+ * @throws {CloudError} On quota, retry exhaustion, disposal, or anonymous mode.
1017
+ *
1018
+ * @see Design Choice GI5 — certification lifecycle.
1019
+ * @see Design Choice CR10 — polling-based notification.
1020
+ */
1021
+ certify(contractId: string): Promise<CloudResult<CertifyResult>>;
1022
+ /**
1023
+ * Initiate GDPR right-to-delete for a project's data.
1024
+ *
1025
+ * Proxies to `DELETE /v1/project/:id/data`. Immediate soft-delete
1026
+ * in D1 (`deleted_at = NOW()`), background Worker hard-purges within
1027
+ * 72h across D1, R2, Vectorize, and ClickHouse (AG9).
1028
+ *
1029
+ * Returns `202 Accepted` — fire-and-forget from the SDK's perspective.
1030
+ *
1031
+ * **IPU cost:** 0 (§9.1).
1032
+ *
1033
+ * @param projectId - The project ID to delete data for.
1034
+ * @returns Acceptance confirmation (`{ accepted: true }`).
1035
+ *
1036
+ * @throws {CloudError} `ENS-5002` if disposed. `ENS-5004` if anonymous.
1037
+ *
1038
+ * @see Design Choice AG9 — two-phase delete: soft-delete + background purge.
1039
+ * @see Audit Finding F16 — fire-and-forget, no `jobId` (endpoint not in §9.1).
1040
+ */
1041
+ deleteProjectData(projectId: string): Promise<CloudResult<{
1042
+ readonly accepted: boolean;
1043
+ }>>;
1044
+ /**
1045
+ * Release all resources held by this client.
1046
+ *
1047
+ * After calling `dispose()`, all subsequent method calls throw
1048
+ * `CloudError` (`ENS-5002`). Safe to call multiple times (idempotent).
1049
+ *
1050
+ * Does NOT throw in anonymous mode — always allowed.
1051
+ */
1052
+ dispose(): void;
1053
+ }
1054
+
1055
+ /**
1056
+ * @module @enterstellar-ai/cloud/create-cloud-client
1057
+ * @description Factory function for creating the Enterstellar Cloud SDK client.
1058
+ *
1059
+ * This is the top-level entry point of `@enterstellar-ai/cloud`. It validates the
1060
+ * configuration, initializes all internal modules — HTTP transport, SSE
1061
+ * transport, IPU tracker, and 8 proxy modules — and returns a fully
1062
+ * wired {@link EnterstellarCloudClient} instance.
1063
+ *
1064
+ * **13 methods + `forge.stream()` + `dispose()`** wired from:
1065
+ *
1066
+ * | Method | Proxy Module |
1067
+ * |:----------------------|:-------------------------------|
1068
+ * | `forge` / `.stream()` | `CloudForgeProxy` |
1069
+ * | `search` | `CloudIndexProxy` |
1070
+ * | `route` | `CloudRouterProxy` |
1071
+ * | `routeBatch` | `CloudRouterProxy` |
1072
+ * | `submitSignal` | `SignalSubmitter` |
1073
+ * | `submitTrace` | `TraceSubmitter` |
1074
+ * | `getTraces` | `TracesQueryProxy` |
1075
+ * | `analytics` | `CloudAnalyticsProxy` |
1076
+ * | `businessAnalytics` | `CloudAnalyticsProxy` |
1077
+ * | `getUsage` | (inline — direct transport) |
1078
+ * | `getLedger` | `LedgerQueryProxy` |
1079
+ * | `certify` | `CertifyProxy` |
1080
+ * | `deleteProjectData` | `DataDeletionProxy` |
1081
+ *
1082
+ * **Anonymous mode (SD1):**
1083
+ * When the API key starts with `pk_anon_`, only `submitSignal()` and
1084
+ * `dispose()` are available. All other methods throw `ENS-5004`.
1085
+ *
1086
+ * **Error policy:**
1087
+ * - Config validation errors → throw `CloudError` (`ENS-5001`) at creation.
1088
+ * - Post-dispose calls → throw `CloudError` (`ENS-5002`).
1089
+ * - Anonymous mode violations → throw `CloudError` (`ENS-5004`).
1090
+ * - Operational errors → delegated to proxy modules / transport (SD3, SD5).
1091
+ *
1092
+ * @see Bible §9.2 — SDK ↔ Cloud endpoint mapping.
1093
+ * @see Design Choice SD1 — auto-detect `pk_anon_` → anonymous mode.
1094
+ * @see Design Choice SD6 — dual forge API: `forge()` + `forge.stream()`.
1095
+ * @see Design Choice SD7 — every method returns `CloudResult<T>`.
1096
+ * @see Design Choice SD8 — default `baseUrl` = `https://api.enterstellar.dev`.
1097
+ * @see Design Choice TA2 — `traceConsent` defaults to `false`.
1098
+ * @see Design Choice D111 — `sessionType` defaults to `'app'`.
1099
+ * @see Design Choices CL1–CL5 — metering, billing, degradation.
1100
+ * @see Principle L15 — zero framework imports.
1101
+ */
1102
+
1103
+ /**
1104
+ * Creates an {@link EnterstellarCloudClient} — the primary public API of `@enterstellar-ai/cloud`.
1105
+ *
1106
+ * Validates the configuration, initializes the HTTP and SSE transports
1107
+ * with bearer token auth (CL4), creates an IPU tracker for hybrid metering
1108
+ * (CL1), wires all 8 proxy modules, and returns the client interface.
1109
+ *
1110
+ * **Anonymous mode (SD1):** If `config.apiKey` starts with `pk_anon_`,
1111
+ * only `submitSignal()` and `dispose()` are available. All other method
1112
+ * calls throw `CloudError` (`ENS-5004`).
1113
+ *
1114
+ * @param config - Client configuration. See {@link CloudConfig} for details.
1115
+ * @returns A fully wired `EnterstellarCloudClient` instance.
1116
+ *
1117
+ * @throws {CloudError} `ENS-5001` if `apiKey` is empty or missing.
1118
+ *
1119
+ * @example
1120
+ * ```ts
1121
+ * import { createEnterstellarCloudClient, CloudError } from '@enterstellar-ai/cloud';
1122
+ *
1123
+ * // Full mode:
1124
+ * const client = createEnterstellarCloudClient({
1125
+ * apiKey: process.env['ENTERSTELLAR_API_KEY']!,
1126
+ * traceConsent: true,
1127
+ * sessionType: 'app',
1128
+ * });
1129
+ *
1130
+ * try {
1131
+ * const { data: contract, ipu } = await client.forge({ intent: 'patient vitals' });
1132
+ * console.log(`Generated: ${contract.name}, IPU remaining: ${ipu?.remaining}`);
1133
+ * } catch (error) {
1134
+ * if (error instanceof CloudError && error.upgradeUrl) {
1135
+ * showUpgradePrompt(error.upgradeUrl);
1136
+ * }
1137
+ * } finally {
1138
+ * client.dispose();
1139
+ * }
1140
+ *
1141
+ * // Anonymous mode:
1142
+ * const anonClient = createEnterstellarCloudClient({ apiKey: 'pk_anon_abc123' });
1143
+ * await anonClient.submitSignal(signal); // ✓ Works
1144
+ * await anonClient.forge({ intent: 'x' }); // ✗ Throws ENS-5004
1145
+ * ```
1146
+ *
1147
+ * @see Bible §9.2 — SDK ↔ Cloud endpoint mapping.
1148
+ * @see Design Choice SD1 — anonymous mode auto-detection.
1149
+ * @see Design Choice SD6 — dual forge API.
1150
+ * @see Design Choice SD7 — universal `CloudResult<T>` return wrapper.
1151
+ * @see Design Choices CL1–CL5 — metering and billing.
1152
+ */
1153
+ declare function createEnterstellarCloudClient(config: CloudConfig): EnterstellarCloudClient;
1154
+
1155
+ /**
1156
+ * @module @enterstellar-ai/cloud/version
1157
+ * @description SDK version constant for `@enterstellar-ai/cloud`.
1158
+ *
1159
+ * Used by the transport layer to set the `User-Agent` header on all
1160
+ * outgoing requests (`User-Agent: enterstellar-cloud-sdk/{CLOUD_SDK_VERSION}`),
1161
+ * and available to consumers for diagnostic logging.
1162
+ *
1163
+ * This value MUST match the `version` field in `packages/cloud/package.json`.
1164
+ * Updates are managed exclusively via Changesets (X4) — never manually.
1165
+ *
1166
+ * @see Enterstellar OS version constant convention
1167
+ * @see Design Choice SD9 — zero framework deps, `User-Agent` is the only
1168
+ * SDK-identifying header.
1169
+ */
1170
+ /**
1171
+ * The current version of the `@enterstellar-ai/cloud` SDK.
1172
+ *
1173
+ * @remarks
1174
+ * - Follows semver (major.minor.patch).
1175
+ * - Must stay in sync with `packages/cloud/package.json#version`.
1176
+ * - Typed as a string literal via `as const` for compile-time narrowing.
1177
+ * - Consumed by {@link CloudHttpTransport} for the `User-Agent` header.
1178
+ *
1179
+ * @example
1180
+ * ```ts
1181
+ * import { CLOUD_SDK_VERSION } from '@enterstellar-ai/cloud';
1182
+ *
1183
+ * console.log(`Running enterstellar-cloud-sdk v${CLOUD_SDK_VERSION}`);
1184
+ * // → "Running enterstellar-cloud-sdk v0.1.0"
1185
+ * ```
1186
+ */
1187
+ declare const CLOUD_SDK_VERSION: "0.1.0";
1188
+
1189
+ /**
1190
+ * @module @enterstellar-ai/cloud/metering/ipu-costs
1191
+ * @description Weighted IPU (Intent Processing Unit) cost constants.
1192
+ *
1193
+ * Each Enterstellar Cloud API operation has a fixed IPU cost. These constants
1194
+ * are the single source of truth for cost calculations across all
1195
+ * proxy modules. They are also exported from the barrel for consumer
1196
+ * use (e.g., pre-flight cost estimation in application code).
1197
+ *
1198
+ * **13 operations** defined per Bible §9.1 (corrected):
1199
+ *
1200
+ * | Operation | Constant | IPU |
1201
+ * |:---------------------|:--------------------------|:---:|
1202
+ * | Cloud Forge | `FORGE` | 10 |
1203
+ * | Semantic Search | `SEMANTIC_SEARCH` | 1 |
1204
+ * | Intent Route | `ROUTE` | 1 |
1205
+ * | Batch Route (per) | `ROUTE_BATCH_PER_INTENT` | 1 |
1206
+ * | Submit Signal | `SIGNAL_SUBMIT` | 0 |
1207
+ * | Submit Trace | `TRACE_SUBMIT` | 0 |
1208
+ * | Trace Analytics | `TRACE_ANALYTICS` | 5 |
1209
+ * | Business Analytics | `BUSINESS_ANALYTICS` | 5 |
1210
+ * | Certify | `CERTIFY` | 20 |
1211
+ * | Usage Query | `USAGE_QUERY` | 0 |
1212
+ * | Ledger Query | `LEDGER_QUERY` | 0 |
1213
+ * | Get Traces | `GET_TRACES` | 0 |
1214
+ * | Delete Project Data | `DELETE_PROJECT_DATA` | 0 |
1215
+ *
1216
+ * **Scope (F9):** This table covers SDK-triggered operations only.
1217
+ * Server-internal operations (`cold_path`, `hitl_review`, `global_index_publish`,
1218
+ * etc.) are defined in the Cloud monorepo's `shared/ipu.ts`.
1219
+ *
1220
+ * @see Design Choice CL2 — weighted IPU costs.
1221
+ * @see Bible §9.1 — API endpoint table with IPU costs.
1222
+ * @see Audit Finding F9 — SDK-triggered operations only.
1223
+ */
1224
+ /**
1225
+ * Weighted IPU costs per cloud API operation.
1226
+ *
1227
+ * These values are locked per Design Choice CL2 and Bible §9.1.
1228
+ * Do not modify without an explicit amendment to the design choices
1229
+ * document and the Implementation Bible.
1230
+ *
1231
+ * @example
1232
+ * ```ts
1233
+ * import { IPU_COSTS } from '@enterstellar-ai/cloud';
1234
+ *
1235
+ * // Pre-flight cost estimation:
1236
+ * const batchCost = intentHashes.length * IPU_COSTS.ROUTE_BATCH_PER_INTENT;
1237
+ * console.log(`Batch route will cost ${batchCost} IPU`);
1238
+ * ```
1239
+ */
1240
+ declare const IPU_COSTS: Readonly<{
1241
+ /**
1242
+ * CloudForge generation — LLM-based component contract generation.
1243
+ * Premium feature, highest per-operation cost.
1244
+ *
1245
+ * @see Design Choice CL2 — "CloudForge generation = 10 IPU"
1246
+ * @see Bible §9.1 — `POST /v1/forge`
1247
+ */
1248
+ readonly FORGE: 10;
1249
+ /**
1250
+ * Cloud semantic search — vector similarity lookup via Vectorize.
1251
+ * Lightweight operation, lowest per-operation cost.
1252
+ *
1253
+ * @see Design Choice CL2 — "cloud semantic search = 1 IPU"
1254
+ * @see Bible §9.1 — `POST /v1/semantic-search`
1255
+ */
1256
+ readonly SEMANTIC_SEARCH: 1;
1257
+ /**
1258
+ * Intent routing — frequency-based (Phase 2) or ML-based (Phase 3)
1259
+ * component prediction for a single intent hash.
1260
+ *
1261
+ * @see Design Choice IR2 — router prediction response shape.
1262
+ * @see Bible §9.1 — `POST /v1/route`
1263
+ */
1264
+ readonly ROUTE: 1;
1265
+ /**
1266
+ * Batch intent routing — per-intent cost within a batch request.
1267
+ * A batch of N intents costs `N × 1 IPU`.
1268
+ *
1269
+ * @see Design Choice IR5 — batch routing for pre-rendering.
1270
+ * @see Bible §9.1 — `POST /v1/route/batch`
1271
+ */
1272
+ readonly ROUTE_BATCH_PER_INTENT: 1;
1273
+ /**
1274
+ * ForgeSignal submission — telemetry data ingestion.
1275
+ * Free — signal data is Enterstellar's #1 strategic asset (§9.1:
1276
+ * "never charge for data collection").
1277
+ *
1278
+ * @see Design Choice SD4 — transparent `pk_anon` auth for signals.
1279
+ * @see Bible §9.1 — `POST /v1/signals`
1280
+ */
1281
+ readonly SIGNAL_SUBMIT: 0;
1282
+ /**
1283
+ * AgentTrace submission — trace data ingestion for aggregation.
1284
+ * Free — trace data is the feedstock for analytics features.
1285
+ *
1286
+ * **CORRECTED:** Was 5 IPU in the OSS Bible (§4.13). Changed to 0
1287
+ * in the Cloud Bible §9.1: "never charge for data collection."
1288
+ *
1289
+ * @see Bible §9.1 — `POST /v1/traces` (0 IPU)
1290
+ */
1291
+ readonly TRACE_SUBMIT: 0;
1292
+ /**
1293
+ * Trace analytics query — server-side OLAP aggregation via ClickHouse.
1294
+ * Moderate cost reflecting the compute intensity.
1295
+ *
1296
+ * @see Design Choice TA5 — fixed analytics query types.
1297
+ * @see Bible §9.1 — `POST /v1/traces/analytics`
1298
+ */
1299
+ readonly TRACE_ANALYTICS: 5;
1300
+ /**
1301
+ * Business analytics query — product intelligence via ClickHouse.
1302
+ * Same cost profile as trace analytics.
1303
+ *
1304
+ * @see Design Choice TA10 — Enterstellar Analytics (business intelligence).
1305
+ * @see Bible §9.1 — `POST /v1/analytics/*`
1306
+ */
1307
+ readonly BUSINESS_ANALYTICS: 5;
1308
+ /**
1309
+ * Contract certification — "Enterstellar Certified" audit initiation.
1310
+ * Highest cost — involves Fly.io microVM test execution (CR5).
1311
+ *
1312
+ * @see Design Choice GI5 — certification lifecycle.
1313
+ * @see Design Choice CR6 — certification costs 20 IPU.
1314
+ * @see Bible §9.1 — `POST /v1/contracts/:id/certify`
1315
+ */
1316
+ readonly CERTIFY: 20;
1317
+ /**
1318
+ * Usage query — returns current IPU consumption and tier.
1319
+ * Free — necessary for clients to monitor their own usage.
1320
+ *
1321
+ * @see Bible §9.1 — `GET /v1/usage`
1322
+ */
1323
+ readonly USAGE_QUERY: 0;
1324
+ /**
1325
+ * IPU ledger query — per-operation charge audit trail.
1326
+ * Free — billing transparency.
1327
+ *
1328
+ * @see Design Choice AM13 — IPU ledger exposure.
1329
+ * @see Bible §9.1 — `GET /v1/usage/ledger`
1330
+ */
1331
+ readonly LEDGER_QUERY: 0;
1332
+ /**
1333
+ * Trace listing query — paginated trace retrieval.
1334
+ * Free — reading your own data is never charged.
1335
+ *
1336
+ * @see Bible §9.1 — `GET /v1/traces`
1337
+ */
1338
+ readonly GET_TRACES: 0;
1339
+ /**
1340
+ * GDPR data deletion — initiate project data purge.
1341
+ * Free — compliance operations are never charged.
1342
+ *
1343
+ * @see Design Choice AG9 — two-phase delete.
1344
+ * @see Design Choice D110 — GDPR soft-delete.
1345
+ * @see Bible §9.1 — `DELETE /v1/project/:id/data`
1346
+ */
1347
+ readonly DELETE_PROJECT_DATA: 0;
1348
+ }>;
1349
+ /**
1350
+ * Union type of all valid IPU cost values.
1351
+ *
1352
+ * Derived from the `IPU_COSTS` constant object. Useful for
1353
+ * type-constraining function parameters that accept IPU costs.
1354
+ *
1355
+ * Currently: `0 | 1 | 5 | 10 | 20`.
1356
+ */
1357
+ type IPUCostValue = (typeof IPU_COSTS)[keyof typeof IPU_COSTS];
1358
+
1359
+ export { type AnalyticsQuery, type AnalyticsResult, CLOUD_SDK_VERSION, type CertifyResult, type CloudConfig, CloudError, type CloudErrorBody, type CloudIPU, type CloudResult, type CloudUsage, type EnterstellarCloudClient, type ForgeCompleteFragment, type ForgeErrorFragment, type ForgeFragment, type ForgeFunction, type ForgeMetaFragment, type ForgeNodeFragment, type ForgeOptions, type ForgePropertyFragment, type IPUCostValue, IPU_COSTS, type LedgerListOptions, type LedgerPage, type RouterPrediction, type SessionType, type TraceListOptions, type TracePage, createEnterstellarCloudClient };