@unicity-astrid/sdk 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.
Files changed (124) hide show
  1. package/README.md +120 -0
  2. package/dist/approval.d.ts +23 -0
  3. package/dist/approval.d.ts.map +1 -0
  4. package/dist/approval.js +29 -0
  5. package/dist/approval.js.map +1 -0
  6. package/dist/capabilities.d.ts +14 -0
  7. package/dist/capabilities.d.ts.map +1 -0
  8. package/dist/capabilities.js +19 -0
  9. package/dist/capabilities.js.map +1 -0
  10. package/dist/capsule.d.ts +39 -0
  11. package/dist/capsule.d.ts.map +1 -0
  12. package/dist/capsule.js +67 -0
  13. package/dist/capsule.js.map +1 -0
  14. package/dist/contracts.d.ts +1104 -0
  15. package/dist/contracts.d.ts.map +1 -0
  16. package/dist/contracts.js +4 -0
  17. package/dist/contracts.js.map +1 -0
  18. package/dist/elicit.d.ts +30 -0
  19. package/dist/elicit.d.ts.map +1 -0
  20. package/dist/elicit.js +103 -0
  21. package/dist/elicit.js.map +1 -0
  22. package/dist/env.d.ts +19 -0
  23. package/dist/env.d.ts.map +1 -0
  24. package/dist/env.js +27 -0
  25. package/dist/env.js.map +1 -0
  26. package/dist/errors.d.ts +46 -0
  27. package/dist/errors.d.ts.map +1 -0
  28. package/dist/errors.js +108 -0
  29. package/dist/errors.js.map +1 -0
  30. package/dist/fs.d.ts +135 -0
  31. package/dist/fs.d.ts.map +1 -0
  32. package/dist/fs.js +257 -0
  33. package/dist/fs.js.map +1 -0
  34. package/dist/http.d.ts +90 -0
  35. package/dist/http.d.ts.map +1 -0
  36. package/dist/http.js +276 -0
  37. package/dist/http.js.map +1 -0
  38. package/dist/identity.d.ts +46 -0
  39. package/dist/identity.d.ts.map +1 -0
  40. package/dist/identity.js +69 -0
  41. package/dist/identity.js.map +1 -0
  42. package/dist/index.d.ts +30 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +27 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/interceptors.d.ts +21 -0
  47. package/dist/interceptors.d.ts.map +1 -0
  48. package/dist/interceptors.js +22 -0
  49. package/dist/interceptors.js.map +1 -0
  50. package/dist/ipc.d.ts +143 -0
  51. package/dist/ipc.d.ts.map +1 -0
  52. package/dist/ipc.js +261 -0
  53. package/dist/ipc.js.map +1 -0
  54. package/dist/kv.d.ts +45 -0
  55. package/dist/kv.d.ts.map +1 -0
  56. package/dist/kv.js +91 -0
  57. package/dist/kv.js.map +1 -0
  58. package/dist/log.d.ts +17 -0
  59. package/dist/log.d.ts.map +1 -0
  60. package/dist/log.js +40 -0
  61. package/dist/log.js.map +1 -0
  62. package/dist/net.d.ts +154 -0
  63. package/dist/net.d.ts.map +1 -0
  64. package/dist/net.js +421 -0
  65. package/dist/net.js.map +1 -0
  66. package/dist/process.d.ts +77 -0
  67. package/dist/process.d.ts.map +1 -0
  68. package/dist/process.js +128 -0
  69. package/dist/process.js.map +1 -0
  70. package/dist/runtime/bridge.d.ts +34 -0
  71. package/dist/runtime/bridge.d.ts.map +1 -0
  72. package/dist/runtime/bridge.js +326 -0
  73. package/dist/runtime/bridge.js.map +1 -0
  74. package/dist/runtime/index.d.ts +3 -0
  75. package/dist/runtime/index.d.ts.map +1 -0
  76. package/dist/runtime/index.js +3 -0
  77. package/dist/runtime/index.js.map +1 -0
  78. package/dist/runtime/registry.d.ts +58 -0
  79. package/dist/runtime/registry.d.ts.map +1 -0
  80. package/dist/runtime/registry.js +129 -0
  81. package/dist/runtime/registry.js.map +1 -0
  82. package/dist/runtime.d.ts +36 -0
  83. package/dist/runtime.d.ts.map +1 -0
  84. package/dist/runtime.js +50 -0
  85. package/dist/runtime.js.map +1 -0
  86. package/dist/time.d.ts +29 -0
  87. package/dist/time.d.ts.map +1 -0
  88. package/dist/time.js +43 -0
  89. package/dist/time.js.map +1 -0
  90. package/dist/tool.d.ts +48 -0
  91. package/dist/tool.d.ts.map +1 -0
  92. package/dist/tool.js +86 -0
  93. package/dist/tool.js.map +1 -0
  94. package/dist/uplink.d.ts +27 -0
  95. package/dist/uplink.d.ts.map +1 -0
  96. package/dist/uplink.js +36 -0
  97. package/dist/uplink.js.map +1 -0
  98. package/package.json +38 -0
  99. package/src/approval.ts +38 -0
  100. package/src/capabilities.ts +22 -0
  101. package/src/capsule.ts +90 -0
  102. package/src/contracts.ts +1189 -0
  103. package/src/elicit.ts +136 -0
  104. package/src/env.ts +31 -0
  105. package/src/errors.ts +122 -0
  106. package/src/fs.ts +357 -0
  107. package/src/http.ts +345 -0
  108. package/src/identity.ts +101 -0
  109. package/src/index.ts +83 -0
  110. package/src/interceptors.ts +25 -0
  111. package/src/ipc.ts +354 -0
  112. package/src/kv.ts +123 -0
  113. package/src/log.ts +43 -0
  114. package/src/net.ts +545 -0
  115. package/src/process.ts +205 -0
  116. package/src/runtime/bridge.ts +374 -0
  117. package/src/runtime/index.ts +11 -0
  118. package/src/runtime/registry.ts +178 -0
  119. package/src/runtime.ts +70 -0
  120. package/src/time.ts +48 -0
  121. package/src/tool.ts +125 -0
  122. package/src/uplink.ts +49 -0
  123. package/src/wit-imports.d.ts +689 -0
  124. package/wit-contracts/astrid-contracts.wit +1266 -0
package/src/http.ts ADDED
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Outbound HTTP. Two public shapes:
3
+ *
4
+ * 1. A builder-style {@link Request} / {@link Response} mirroring the Rust
5
+ * SDK's reqwest-like API (`http.get(url)`, `http.send(req)`).
6
+ * 2. A WHATWG `fetch(url, init)` polyfill registered onto `globalThis`
7
+ * at SDK init via {@link installFetchPolyfill}. Routes through the same
8
+ * capability-gated host imports so users can't bypass the per-capsule
9
+ * net allow-list by reaching for the platform fetch.
10
+ *
11
+ * Streaming: {@link streamStart} returns an {@link HttpStream} resource
12
+ * handle with `read-chunk` for explicit per-chunk pulls, an `async-iterator`
13
+ * convenience, and access to the body as an `astrid:io/streams` `InputStream`
14
+ * for capsules forwarding the body into another sink.
15
+ */
16
+
17
+ import {
18
+ httpRequest as hostRequest,
19
+ httpStreamStart as hostStreamStart,
20
+ type HttpRequestData,
21
+ type HttpResponseData,
22
+ type HttpStream as WitHttpStream,
23
+ type HttpMethod as WitHttpMethod,
24
+ type KeyValuePair,
25
+ } from "astrid:http/host@1.0.0";
26
+ import { SysError, callHost } from "./errors.js";
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Method type
30
+ // ---------------------------------------------------------------------------
31
+
32
+ export type HttpMethod =
33
+ | "GET"
34
+ | "HEAD"
35
+ | "POST"
36
+ | "PUT"
37
+ | "DELETE"
38
+ | "CONNECT"
39
+ | "OPTIONS"
40
+ | "TRACE"
41
+ | "PATCH"
42
+ | string;
43
+
44
+ /** Convert a string method name into the WIT variant the host expects. */
45
+ function methodToWit(method: string): WitHttpMethod {
46
+ switch (method.toUpperCase()) {
47
+ case "GET":
48
+ return { tag: "get" };
49
+ case "HEAD":
50
+ return { tag: "head" };
51
+ case "POST":
52
+ return { tag: "post" };
53
+ case "PUT":
54
+ return { tag: "put" };
55
+ case "DELETE":
56
+ return { tag: "delete" };
57
+ case "CONNECT":
58
+ return { tag: "connect" };
59
+ case "OPTIONS":
60
+ return { tag: "options" };
61
+ case "TRACE":
62
+ return { tag: "trace" };
63
+ case "PATCH":
64
+ return { tag: "patch" };
65
+ default:
66
+ return { tag: "other", val: method };
67
+ }
68
+ }
69
+
70
+ // ---------------------------------------------------------------------------
71
+ // Builder API (reqwest shape)
72
+ // ---------------------------------------------------------------------------
73
+
74
+ export class Request {
75
+ url: string;
76
+ method: string;
77
+ headers: Map<string, string>;
78
+ body: Uint8Array | undefined;
79
+
80
+ constructor(method: string, url: string) {
81
+ this.method = method;
82
+ this.url = url;
83
+ this.headers = new Map();
84
+ this.body = undefined;
85
+ }
86
+
87
+ static get(url: string): Request {
88
+ return new Request("GET", url);
89
+ }
90
+ static post(url: string): Request {
91
+ return new Request("POST", url);
92
+ }
93
+ static put(url: string): Request {
94
+ return new Request("PUT", url);
95
+ }
96
+ static delete(url: string): Request {
97
+ return new Request("DELETE", url);
98
+ }
99
+ static patch(url: string): Request {
100
+ return new Request("PATCH", url);
101
+ }
102
+ static head(url: string): Request {
103
+ return new Request("HEAD", url);
104
+ }
105
+
106
+ header(key: string, value: string): this {
107
+ this.headers.set(key, value);
108
+ return this;
109
+ }
110
+
111
+ setBody(body: string | Uint8Array): this {
112
+ this.body = typeof body === "string" ? new TextEncoder().encode(body) : body;
113
+ return this;
114
+ }
115
+
116
+ json<T>(value: T): this {
117
+ this.headers.set("Content-Type", "application/json");
118
+ let s: string;
119
+ try {
120
+ s = JSON.stringify(value);
121
+ } catch (err) {
122
+ throw SysError.json(`http.Request.json: ${(err as Error).message}`, err);
123
+ }
124
+ this.body = new TextEncoder().encode(s);
125
+ return this;
126
+ }
127
+
128
+ toWit(): HttpRequestData {
129
+ return {
130
+ url: this.url,
131
+ method: methodToWit(this.method),
132
+ headers: Array.from(this.headers, ([key, value]) => ({ key, value })),
133
+ body: this.body,
134
+ };
135
+ }
136
+ }
137
+
138
+ export class Response {
139
+ readonly status: number;
140
+ readonly headers: Map<string, string>;
141
+ readonly #body: Uint8Array;
142
+
143
+ constructor(raw: HttpResponseData) {
144
+ this.status = raw.status;
145
+ this.headers = new Map(raw.headers.map((h) => [h.key, h.value]));
146
+ this.#body = raw.body;
147
+ }
148
+
149
+ bytes(): Uint8Array {
150
+ return this.#body;
151
+ }
152
+
153
+ text(): string {
154
+ return new TextDecoder().decode(this.#body);
155
+ }
156
+
157
+ json<T = unknown>(): T {
158
+ try {
159
+ return JSON.parse(this.text()) as T;
160
+ } catch (err) {
161
+ throw SysError.json(`http.Response.json: ${(err as Error).message}`, err);
162
+ }
163
+ }
164
+
165
+ ok(): boolean {
166
+ return this.status >= 200 && this.status < 300;
167
+ }
168
+ }
169
+
170
+ export function send(req: Request): Response {
171
+ const wit = req.toWit();
172
+ const raw = callHost(`http.send ${req.method} ${req.url}`, () => hostRequest(wit));
173
+ return new Response(raw);
174
+ }
175
+
176
+ // ---------------------------------------------------------------------------
177
+ // Streaming
178
+ // ---------------------------------------------------------------------------
179
+
180
+ /**
181
+ * Streaming HTTP response. The kernel buffers chunks server-side; the
182
+ * capsule reads them via `.read()` (or the async iterator) until EOF. Drop
183
+ * (via `using` or `.close()`) releases the host-side resource.
184
+ */
185
+ export class HttpStreamHandle {
186
+ #inner: WitHttpStream | undefined;
187
+ readonly status: number;
188
+ readonly headers: Map<string, string>;
189
+
190
+ constructor(inner: WitHttpStream) {
191
+ this.#inner = inner;
192
+ this.status = inner.status();
193
+ this.headers = new Map(inner.headers().map((h: KeyValuePair) => [h.key, h.value]));
194
+ }
195
+
196
+ /** Read the next chunk. Returns `undefined` at EOF. */
197
+ read(): Uint8Array | undefined {
198
+ if (this.#inner === undefined) return undefined;
199
+ const chunk = callHost("http.HttpStream.readChunk", () => this.#inner!.readChunk());
200
+ if (chunk.length === 0) return undefined;
201
+ return chunk;
202
+ }
203
+
204
+ close(): void {
205
+ if (this.#inner === undefined) return;
206
+ const inner = this.#inner;
207
+ this.#inner = undefined;
208
+ try {
209
+ // Explicit close mirrors the WIT-defined `.close()`; the Drop step still
210
+ // runs on resource release regardless.
211
+ inner.close();
212
+ } catch {
213
+ // idempotent close — host may have already released it.
214
+ }
215
+ try {
216
+ inner[Symbol.dispose]();
217
+ } catch {
218
+ // already released
219
+ }
220
+ }
221
+
222
+ [Symbol.dispose](): void {
223
+ this.close();
224
+ }
225
+
226
+ /** Async iterator that yields each chunk until EOF. Auto-closes on completion. */
227
+ async *[Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {
228
+ try {
229
+ while (true) {
230
+ const chunk = this.read();
231
+ if (chunk === undefined) return;
232
+ yield chunk;
233
+ }
234
+ } finally {
235
+ this.close();
236
+ }
237
+ }
238
+ }
239
+
240
+ export interface StreamStart {
241
+ handle: HttpStreamHandle;
242
+ status: number;
243
+ headers: Map<string, string>;
244
+ }
245
+
246
+ export function streamStart(req: Request): StreamStart {
247
+ const wit = req.toWit();
248
+ const inner: WitHttpStream = callHost(
249
+ `http.streamStart ${req.method} ${req.url}`,
250
+ () => hostStreamStart(wit),
251
+ );
252
+ const handle = new HttpStreamHandle(inner);
253
+ return { handle, status: handle.status, headers: handle.headers };
254
+ }
255
+
256
+ // ---------------------------------------------------------------------------
257
+ // WHATWG fetch polyfill
258
+ // ---------------------------------------------------------------------------
259
+
260
+ export interface FetchInit {
261
+ method?: string;
262
+ headers?: Record<string, string> | Map<string, string> | [string, string][];
263
+ body?: string | Uint8Array | Record<string, unknown>;
264
+ }
265
+
266
+ export class FetchResponse {
267
+ readonly status: number;
268
+ readonly statusText: string;
269
+ readonly headers: Headers;
270
+ readonly url: string;
271
+ readonly ok: boolean;
272
+ readonly #body: Uint8Array;
273
+
274
+ constructor(url: string, status: number, headerEntries: [string, string][], body: Uint8Array) {
275
+ this.url = url;
276
+ this.status = status;
277
+ this.statusText = httpStatusText(status);
278
+ this.headers = new Headers(headerEntries);
279
+ this.ok = status >= 200 && status < 300;
280
+ this.#body = body;
281
+ }
282
+
283
+ async text(): Promise<string> {
284
+ return new TextDecoder().decode(this.#body);
285
+ }
286
+
287
+ async json<T = unknown>(): Promise<T> {
288
+ return JSON.parse(await this.text()) as T;
289
+ }
290
+
291
+ async arrayBuffer(): Promise<ArrayBuffer> {
292
+ return this.#body.buffer.slice(
293
+ this.#body.byteOffset,
294
+ this.#body.byteOffset + this.#body.byteLength,
295
+ ) as ArrayBuffer;
296
+ }
297
+
298
+ async bytes(): Promise<Uint8Array> {
299
+ return this.#body;
300
+ }
301
+ }
302
+
303
+ export async function fetchPolyfill(url: string, init: FetchInit = {}): Promise<FetchResponse> {
304
+ const req = new Request(init.method ?? "GET", url);
305
+ if (init.headers) {
306
+ for (const [k, v] of normalizeHeaders(init.headers)) {
307
+ req.header(k, v);
308
+ }
309
+ }
310
+ if (init.body !== undefined) {
311
+ if (typeof init.body === "string") {
312
+ req.setBody(init.body);
313
+ } else if (init.body instanceof Uint8Array) {
314
+ req.setBody(init.body);
315
+ } else {
316
+ req.json(init.body);
317
+ }
318
+ }
319
+ const raw = callHost(`fetch ${req.method} ${url}`, () => hostRequest(req.toWit()));
320
+ return new FetchResponse(url, raw.status, raw.headers.map((h) => [h.key, h.value]), raw.body);
321
+ }
322
+
323
+ /** Install the polyfill on `globalThis.fetch`. */
324
+ export function installFetchPolyfill(): void {
325
+ (globalThis as unknown as { fetch?: typeof fetchPolyfill }).fetch = fetchPolyfill;
326
+ }
327
+
328
+ function normalizeHeaders(
329
+ input: NonNullable<FetchInit["headers"]>,
330
+ ): Iterable<[string, string]> {
331
+ if (input instanceof Map) return input.entries();
332
+ if (Array.isArray(input)) return input;
333
+ return Object.entries(input);
334
+ }
335
+
336
+ function httpStatusText(code: number): string {
337
+ const map: Record<number, string> = {
338
+ 200: "OK", 201: "Created", 202: "Accepted", 204: "No Content",
339
+ 301: "Moved Permanently", 302: "Found", 304: "Not Modified",
340
+ 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found",
341
+ 409: "Conflict", 422: "Unprocessable Entity", 429: "Too Many Requests",
342
+ 500: "Internal Server Error", 502: "Bad Gateway", 503: "Service Unavailable",
343
+ };
344
+ return map[code] ?? "";
345
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Multi-platform identity resolution and linking. Mirrors `astrid_sdk::identity`.
3
+ *
4
+ * Required capability in `Capsule.toml`:
5
+ * `["resolve"]` — resolve platform users
6
+ * `["link"]` — resolve, link, unlink, list-links
7
+ * `["admin"]` — all of the above + create new users
8
+ *
9
+ * Post per-domain WIT split, the host returns typed records directly (no
10
+ * `linksJson` blob, no `ok` flags). Errors surface as `SysError` with
11
+ * `code` set to the WIT variant (`link-not-found`, `already-linked`, etc.).
12
+ *
13
+ * The {@link resolve} helper preserves the pre-migration "absent → undefined"
14
+ * shape by catching `link-not-found` and returning `undefined`. Other errors
15
+ * propagate.
16
+ */
17
+
18
+ import {
19
+ identityResolve as hostResolve,
20
+ identityLink as hostLink,
21
+ identityUnlink as hostUnlink,
22
+ identityCreateUser as hostCreateUser,
23
+ identityListLinks as hostListLinks,
24
+ } from "astrid:identity/host@1.0.0";
25
+ import { SysError, callHost } from "./errors.js";
26
+
27
+ export interface ResolvedUser {
28
+ userId: string;
29
+ displayName: string | undefined;
30
+ }
31
+
32
+ export interface Link {
33
+ platform: string;
34
+ platformUserId: string;
35
+ /** ISO 8601 timestamp the link was created. */
36
+ linkedAt: string;
37
+ /** Auth method used at link time (e.g. "passkey", "token"). */
38
+ method: string;
39
+ }
40
+
41
+ /**
42
+ * Resolve a platform identity to an Astrid user, or `undefined` if no link
43
+ * exists. Other identity errors (capability-denied, store-unavailable, etc.)
44
+ * propagate as `SysError`.
45
+ */
46
+ export function resolve(platform: string, platformUserId: string): ResolvedUser | undefined {
47
+ try {
48
+ const resp = callHost(`identity.resolve(${JSON.stringify(platform)})`, () =>
49
+ hostResolve({ platform, platformUserId }),
50
+ );
51
+ return { userId: resp.userId, displayName: resp.displayName };
52
+ } catch (err) {
53
+ if (err instanceof SysError && err.code === "link-not-found") return undefined;
54
+ throw err;
55
+ }
56
+ }
57
+
58
+ /** Link a platform identity to an Astrid user. */
59
+ export function link(
60
+ platform: string,
61
+ platformUserId: string,
62
+ astridUserId: string,
63
+ method: string,
64
+ ): void {
65
+ callHost("identity.link", () =>
66
+ hostLink({ platform, platformUserId, astridUserId, method }),
67
+ );
68
+ }
69
+
70
+ /**
71
+ * Unlink a platform identity. Returns `true` if a link was removed,
72
+ * `false` if there was nothing to remove.
73
+ */
74
+ export function unlink(platform: string, platformUserId: string): boolean {
75
+ try {
76
+ callHost("identity.unlink", () => hostUnlink({ platform, platformUserId }));
77
+ return true;
78
+ } catch (err) {
79
+ if (err instanceof SysError && err.code === "link-not-found") return false;
80
+ throw err;
81
+ }
82
+ }
83
+
84
+ /** Create a new Astrid user. Returns the new user UUID. */
85
+ export function createUser(displayName?: string): string {
86
+ const resp = callHost("identity.createUser", () =>
87
+ hostCreateUser({ displayName }),
88
+ );
89
+ return resp.userId;
90
+ }
91
+
92
+ /** List all platform links for an Astrid user. */
93
+ export function listLinks(astridUserId: string): Link[] {
94
+ const links = callHost("identity.listLinks", () => hostListLinks(astridUserId));
95
+ return links.map((l) => ({
96
+ platform: l.platform,
97
+ platformUserId: l.platformUserId,
98
+ linkedAt: l.linkedAt,
99
+ method: l.method,
100
+ }));
101
+ }
package/src/index.ts ADDED
@@ -0,0 +1,83 @@
1
+ // Public API of @unicity-astrid/sdk.
2
+ //
3
+ // Module-by-module mirror of `astrid_sdk::prelude`, with idiom translated
4
+ // from Rust-std to Node/WHATWG conventions where appropriate.
5
+
6
+ export { SysError, type SysErrorKind } from "./errors.js";
7
+
8
+ export { capsule, install, upgrade, run } from "./capsule.js";
9
+ export {
10
+ tool,
11
+ interceptor,
12
+ command,
13
+ type ToolOptions,
14
+ type InterceptorOptions,
15
+ type CommandOptions,
16
+ } from "./tool.js";
17
+
18
+ // Namespaced submodules. Authors import as
19
+ // `import { fs, http, ipc, ... } from "@unicity-astrid/sdk"` and call
20
+ // `await fs.readFile(...)`, `ipc.publish(...)`, etc.
21
+ export * as log from "./log.js";
22
+ export * as kv from "./kv.js";
23
+ export * as ipc from "./ipc.js";
24
+ export * as fs from "./fs.js";
25
+ export * as http from "./http.js";
26
+ export * as net from "./net.js";
27
+ export * as process from "./process.js";
28
+ export * as env from "./env.js";
29
+ export * as time from "./time.js";
30
+ export * as runtime from "./runtime.js";
31
+ export * as capabilities from "./capabilities.js";
32
+ export * as elicit from "./elicit.js";
33
+ export * as identity from "./identity.js";
34
+ export * as approval from "./approval.js";
35
+ export * as uplink from "./uplink.js";
36
+ export * as interceptors from "./interceptors.js";
37
+
38
+ // Type re-exports for ergonomic imports.
39
+ export type {
40
+ IpcMessage,
41
+ PollResult,
42
+ Subscription,
43
+ InterceptorBinding,
44
+ PrincipalAttribution,
45
+ } from "./ipc.js";
46
+ export type { Stats, Dirent, FileHandle, OpenMode, FileType } from "./fs.js";
47
+ export type {
48
+ Request as HttpRequest,
49
+ Response as HttpResponse,
50
+ HttpMethod,
51
+ HttpStreamHandle,
52
+ StreamStart,
53
+ FetchInit,
54
+ FetchResponse,
55
+ } from "./http.js";
56
+ export type {
57
+ UnixListener,
58
+ TcpListener,
59
+ TcpStream,
60
+ UdpSocket,
61
+ ListenerHandle,
62
+ StreamHandle,
63
+ RecvError,
64
+ SendError,
65
+ TryRecvError,
66
+ ShutdownHow,
67
+ NetReadStatus,
68
+ UdpDatagram,
69
+ } from "./net.js";
70
+ export type {
71
+ ProcessResult,
72
+ ProcessLogs,
73
+ KillResult,
74
+ BackgroundProcessHandle,
75
+ SpawnOptions,
76
+ ProcessSignal,
77
+ EnvVar,
78
+ } from "./process.js";
79
+ export type { CallerContext } from "./runtime.js";
80
+ export type { ResolvedUser, Link } from "./identity.js";
81
+ export type { UplinkId, UplinkProfile } from "./uplink.js";
82
+ export type { ApprovalDecision } from "./approval.js";
83
+ export type { KeyPage } from "./kv.js";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Interceptor binding registry — metadata for the kernel-managed
3
+ * interceptor subscriptions a capsule declared in `Capsule.toml`.
4
+ *
5
+ * Mirrors `astrid_sdk::interceptors`. Under the per-domain ABI, interceptor
6
+ * events are delivered to the capsule via `astrid-hook-trigger` rather than
7
+ * a run-loop IPC subscription. The host fn `get-interceptor-bindings` returns
8
+ * metadata-only — capsules use it to enumerate the `(action, topic)` pairs
9
+ * they're subscribed to for debugging, introspection, and tooling. `handle`
10
+ * is the kernel-side registry handle (for log correlation only); it is NOT
11
+ * convertible into an `ipc.Subscription`.
12
+ */
13
+
14
+ import { runtimeInterceptors, type InterceptorBinding } from "./ipc.js";
15
+
16
+ export type { InterceptorBinding } from "./ipc.js";
17
+
18
+ /**
19
+ * Query the runtime for auto-subscribed interceptor handles. Returns an
20
+ * empty array if this capsule has no auto-subscribed interceptors (i.e. it
21
+ * does not have both `@run` and `[[interceptor]]`).
22
+ */
23
+ export function bindings(): InterceptorBinding[] {
24
+ return runtimeInterceptors();
25
+ }