@hypertabai/mcp 0.2.0 → 1.0.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 (75) hide show
  1. package/README.md +264 -0
  2. package/dist/bridge/api-client.d.ts +157 -0
  3. package/dist/bridge/api-client.d.ts.map +1 -0
  4. package/dist/bridge/api-client.js +140 -0
  5. package/dist/bridge/api-client.js.map +1 -0
  6. package/dist/bridge/artifacts.d.ts +11 -0
  7. package/dist/bridge/artifacts.d.ts.map +1 -0
  8. package/dist/bridge/artifacts.js +45 -0
  9. package/dist/bridge/artifacts.js.map +1 -0
  10. package/dist/bridge/command-contract.d.ts +14 -0
  11. package/dist/bridge/command-contract.d.ts.map +1 -0
  12. package/dist/bridge/command-contract.js +152 -0
  13. package/dist/bridge/command-contract.js.map +1 -0
  14. package/dist/bridge/index.d.ts +248 -0
  15. package/dist/bridge/index.d.ts.map +1 -0
  16. package/dist/bridge/index.js +875 -0
  17. package/dist/bridge/index.js.map +1 -0
  18. package/dist/bridge/spool.d.ts +30 -0
  19. package/dist/bridge/spool.d.ts.map +1 -0
  20. package/dist/bridge/spool.js +108 -0
  21. package/dist/bridge/spool.js.map +1 -0
  22. package/dist/connect.js +1 -1
  23. package/dist/idempotency.d.ts +11 -0
  24. package/dist/idempotency.d.ts.map +1 -0
  25. package/dist/idempotency.js +63 -0
  26. package/dist/idempotency.js.map +1 -0
  27. package/dist/index.js +5 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/install/skill-writer.d.ts +1 -1
  30. package/dist/install/skill-writer.d.ts.map +1 -1
  31. package/dist/install/skill-writer.js +21 -1
  32. package/dist/install/skill-writer.js.map +1 -1
  33. package/dist/surfaces/build.d.ts +22 -0
  34. package/dist/surfaces/build.d.ts.map +1 -0
  35. package/dist/surfaces/build.js +122 -0
  36. package/dist/surfaces/build.js.map +1 -0
  37. package/dist/surfaces/detect.d.ts +20 -0
  38. package/dist/surfaces/detect.d.ts.map +1 -0
  39. package/dist/surfaces/detect.js +130 -0
  40. package/dist/surfaces/detect.js.map +1 -0
  41. package/dist/surfaces/index.d.ts +35 -0
  42. package/dist/surfaces/index.d.ts.map +1 -0
  43. package/dist/surfaces/index.js +117 -0
  44. package/dist/surfaces/index.js.map +1 -0
  45. package/dist/surfaces/package.d.ts +48 -0
  46. package/dist/surfaces/package.d.ts.map +1 -0
  47. package/dist/surfaces/package.js +86 -0
  48. package/dist/surfaces/package.js.map +1 -0
  49. package/dist/surfaces/publish-client.d.ts +40 -0
  50. package/dist/surfaces/publish-client.d.ts.map +1 -0
  51. package/dist/surfaces/publish-client.js +111 -0
  52. package/dist/surfaces/publish-client.js.map +1 -0
  53. package/package.json +8 -3
  54. package/templates/bridge-wrapper.mjs +138 -0
  55. package/templates/bridge-wrapper.sh +78 -0
  56. package/dist/__tests__/config-writer.test.d.ts +0 -2
  57. package/dist/__tests__/config-writer.test.d.ts.map +0 -1
  58. package/dist/__tests__/config-writer.test.js +0 -186
  59. package/dist/__tests__/config-writer.test.js.map +0 -1
  60. package/dist/__tests__/index.test.d.ts +0 -2
  61. package/dist/__tests__/index.test.d.ts.map +0 -1
  62. package/dist/__tests__/index.test.js +0 -113
  63. package/dist/__tests__/index.test.js.map +0 -1
  64. package/dist/__tests__/install.test.d.ts +0 -2
  65. package/dist/__tests__/install.test.d.ts.map +0 -1
  66. package/dist/__tests__/install.test.js +0 -211
  67. package/dist/__tests__/install.test.js.map +0 -1
  68. package/dist/__tests__/platforms.test.d.ts +0 -2
  69. package/dist/__tests__/platforms.test.d.ts.map +0 -1
  70. package/dist/__tests__/platforms.test.js +0 -109
  71. package/dist/__tests__/platforms.test.js.map +0 -1
  72. package/dist/__tests__/uninstall.test.d.ts +0 -2
  73. package/dist/__tests__/uninstall.test.d.ts.map +0 -1
  74. package/dist/__tests__/uninstall.test.js +0 -117
  75. package/dist/__tests__/uninstall.test.js.map +0 -1
package/README.md CHANGED
@@ -82,6 +82,37 @@ npx @hypertabai/mcp connect --api-key ht_sk_...
82
82
 
83
83
  Lists every Hypertab tool the server exposes. Useful for verifying credentials before wiring up an agent.
84
84
 
85
+ ## Retry-safe writes
86
+
87
+ Installed Hypertab skills tell agents to pass `idempotency_key` on mutating MCP tools that expose it. The key must stay
88
+ stable when retrying the same logical write and must change when the payload, target, or intent changes. This lets
89
+ Hypertab dedupe transient retries, meter one logical operation once, and reject over-budget writes before mutation.
90
+
91
+ Use 8-128 characters with letters, numbers, dot, underscore, colon, or hyphen. A good pattern is
92
+ `agent:<tool>:<target>:<short-hash-or-counter>`. Batch row writes use one key per tool call, not one key per row.
93
+
94
+ First-party REST commands that perform writes generate `Idempotency-Key` headers automatically unless an explicit key is
95
+ provided by the command implementation.
96
+
97
+ ## Surface publishing
98
+
99
+ The CLI now exposes the hosted-surface command group:
100
+
101
+ ```bash
102
+ npx @hypertabai/mcp surfaces publish --dir ./dashboard --out-dir dist --slug ops-dashboard
103
+ ```
104
+
105
+ This command detects the local project, runs or skips the local build, validates static output, prepares a publish manifest and file payloads, then uploads the surface through Hypertab's publish API.
106
+
107
+ Current detection support:
108
+
109
+ - Supported v1 targets: Vite React, Vite, Astro static, and plain static HTML.
110
+ - Static output is considered ready when the output directory exists and contains `index.html`.
111
+ - If output is not ready, the CLI runs `--build <command>` or the detected `package.json` `build` script, then validates output again.
112
+ - Packaging computes MIME types, byte sizes, SHA-256 hashes, cache policies, and base64 file payloads for the server publish API.
113
+ - API keys come from `--api-key` or `HYPERTAB_API_KEY`; use `--json` for machine-readable agent output.
114
+ - Server app targets such as Next, SvelteKit, Nuxt, Remix, Express, and Fastify are rejected with guidance to convert the dashboard to a static browser app that calls Hypertab APIs.
115
+
85
116
  ## Flags
86
117
 
87
118
  ### `install`
@@ -109,6 +140,239 @@ Lists every Hypertab tool the server exposes. Useful for verifying credentials b
109
140
  | `-u, --url <url>` | `https://api.hypertab.ai/mcp` | MCP server URL |
110
141
  | `-t, --transport <type>` | `streamable-http` | `streamable-http`, `sse`, or `stdio` |
111
142
 
143
+ ### `surfaces publish`
144
+
145
+ | Flag | Default | Description |
146
+ |---|---|---|
147
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` later | Hypertab API key |
148
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab API URL |
149
+ | `-d, --dir <path>` | `.` | Project directory to inspect and build |
150
+ | `--out-dir <path>` | unset | Static build output directory |
151
+ | `--slug <slug>` | unset | Hosted surface slug |
152
+ | `--title <title>` | unset | Hosted surface title |
153
+ | `--build <command>` | unset | Build command to run before packaging |
154
+ | `--no-activate` | false | Upload without activating the new deployment |
155
+ | `--json` | false | Print machine-readable JSON output |
156
+ | `--timeout-ms <ms>` | `60000` | Publish API request timeout; stalled requests fail with `SURFACE_PUBLISH_TIMEOUT` |
157
+
158
+ ### `bridge start`
159
+
160
+ | Flag | Default | Description |
161
+ |---|---|---|
162
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key |
163
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
164
+ | `--client-name <name>` | machine hostname | Stable local agent client name |
165
+ | `--client-type <type>` | `codex` | `codex`, `claude_code`, `cursor`, `browser`, `cloud`, or `other` |
166
+ | `--heartbeat-interval-ms <ms>` | `30000` | Heartbeat interval for long-running mode |
167
+ | `--command-interval-ms <ms>` | `5000` | Command claim interval for long-running mode |
168
+ | `--command-limit <n>` | `10` | Max commands claimed per poll, capped at 50 |
169
+ | `--session` | false | Start a durable agent session |
170
+ | `--objective <text>` | unset | Create a durable run for this objective |
171
+ | `--run-title <title>` | first 120 chars of objective | Run title |
172
+ | `--source <source>` | `cli_bridge` | Run source label |
173
+ | `--once` | false | Run one heartbeat/claim cycle and exit |
174
+ | `--json` | false | Print machine-readable JSON lines |
175
+ | `--spool-file <path>` | `~/.hypertab/bridge-spool.jsonl` | Local JSONL spool path |
176
+ | `--no-spool` | false | Disable local event/result spooling |
177
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
178
+
179
+ ### `bridge result`
180
+
181
+ | Flag | Default | Description |
182
+ |---|---|---|
183
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key |
184
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
185
+ | `--command-id <id>` | required | Delivered command id |
186
+ | `--client-id <id>` | unset | Client id for broad bridge tokens; bridge-client tokens can omit it |
187
+ | `--status <status>` | required | `completed`, `failed`, or `cancelled` |
188
+ | `--error-message <message>` | unset | Failure/cancellation details |
189
+ | `--json` | false | Print machine-readable JSON output |
190
+ | `--spool-file <path>` | `~/.hypertab/bridge-spool.jsonl` | Local JSONL spool path |
191
+ | `--no-spool` | false | Disable local result spooling on retryable failures |
192
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
193
+
194
+ ### `bridge status`
195
+
196
+ | Flag | Default | Description |
197
+ |---|---|---|
198
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key |
199
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
200
+ | `--client-id <id>` | unset | Optional client id for broad bridge/API keys |
201
+ | `--limit <n>` | `50` | Max clients/runs/commands to inspect, capped at 100 |
202
+ | `--json` | false | Print machine-readable JSON output |
203
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
204
+
205
+ ### `bridge token create`
206
+
207
+ | Flag | Default | Description |
208
+ |---|---|---|
209
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Admin Hypertab API key used only to mint the bridge token |
210
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
211
+ | `--name <name>` | `<client-name> bridge` | Token display name |
212
+ | `--client-name <name>` | required | Stable local client name bound into the token |
213
+ | `--client-type <type>` | `codex` | `codex`, `claude_code`, `cursor`, `browser`, `cloud`, or `other` |
214
+ | `--expires-in-days <days>` | `30` | Token lifetime in days, 1-365 |
215
+ | `--json` | false | Print machine-readable JSON output with follow-up wrapper commands |
216
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
217
+
218
+ ### `bridge event batch`
219
+
220
+ | Flag | Default | Description |
221
+ |---|---|---|
222
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key |
223
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
224
+ | `--file <path>` | required | JSON file containing `{ "events": [...] }` or an events array |
225
+ | `--json` | false | Print machine-readable JSON output |
226
+ | `--spool-file <path>` | `~/.hypertab/bridge-spool.jsonl` | Local JSONL spool path |
227
+ | `--no-spool` | false | Disable local event spooling on retryable failures |
228
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
229
+
230
+ ### `bridge flush`
231
+
232
+ | Flag | Default | Description |
233
+ |---|---|---|
234
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key |
235
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
236
+ | `--spool-file <path>` | `~/.hypertab/bridge-spool.jsonl` | Local JSONL spool path |
237
+ | `--json` | false | Print machine-readable JSON output |
238
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
239
+
240
+ ### `bridge artifact upload`
241
+
242
+ | Flag | Default | Description |
243
+ |---|---|---|
244
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key |
245
+ | `-u, --api-url <url>` | `https://api.hypertab.ai` | Hypertab REST API URL |
246
+ | `--file <path>` | required | Local file to upload |
247
+ | `--run-id <id>` | unset | Agent run id to attach the artifact to. Bridge-client tokens should provide this. |
248
+ | `--name <name>` | file basename | Artifact display name |
249
+ | `--artifact-type <type>` | inferred | `screenshot`, `report`, `log`, `dataset`, `file`, or a custom artifact type |
250
+ | `--mime-type <type>` | inferred | Override MIME type |
251
+ | `--metadata <json>` | unset | Metadata JSON object |
252
+ | `--json` | false | Print machine-readable JSON output |
253
+ | `--timeout-ms <ms>` | `30000` | Bridge API request timeout; stalled requests fail with `BRIDGE_REQUEST_TIMEOUT` |
254
+
255
+ In non-JSON mode the CLI prints an `Uploading <name> (<size>) to <api-url>...` line before the request so a stalled API never leaves the command silent. Stalled or dropped uploads are retried once automatically with a stable `Idempotency-Key` header before failing.
256
+
257
+ ### `bridge wrapper init`
258
+
259
+ | Flag | Default | Description |
260
+ |---|---|---|
261
+ | `--type <type>` | `node` | Starter type: `node` or `shell` |
262
+ | `--out <path>` | `.hypertab/bridge-wrapper.mjs` or `.hypertab/bridge-wrapper.sh` | Output path |
263
+ | `--force` | false | Overwrite the output file if it already exists |
264
+ | `--json` | false | Print machine-readable JSON output |
265
+
266
+ ### `bridge wrapper doctor`
267
+
268
+ | Flag | Default | Description |
269
+ |---|---|---|
270
+ | `--path <path>` | `.hypertab/bridge-wrapper.mjs` | Wrapper path to inspect |
271
+ | `-k, --api-key <key>` | `$HYPERTAB_API_KEY` | Hypertab bridge/API key presence check |
272
+ | `--spool-file <path>` | `~/.hypertab/bridge-spool.jsonl` | Local JSONL spool path |
273
+ | `--json` | false | Print machine-readable JSON output |
274
+
275
+ Supported v1 targets are static browser dashboards: Vite, Vite React, static Astro, or plain HTML output with
276
+ `index.html`. If detection finds a server app such as Next.js SSR/API routes, SvelteKit server routes, Nuxt, Remix,
277
+ Express, or Fastify, convert it to a static browser surface instead of deploying it elsewhere. Keep the UI, move data and
278
+ actions to Hypertab APIs through scoped browser tokens, keep secrets in Hypertab providers/accounts, then publish the
279
+ static output.
280
+
281
+ ## Local bridge daemon
282
+
283
+ The CLI also exposes a bridge command group for local agent activity:
284
+
285
+ ```bash
286
+ # Mint a scoped bridge-client token with an admin key. The returned token is shown once.
287
+ HYPERTAB_API_KEY=ht_sk_admin... npx @hypertabai/mcp bridge token create \
288
+ --client-name "$(hostname)-codex" \
289
+ --client-type codex \
290
+ --expires-in-days 30 \
291
+ --json
292
+
293
+ # One heartbeat + command-claim cycle, useful for testing a bridge token
294
+ HYPERTAB_API_KEY=ht_sk_bridge... npx @hypertabai/mcp bridge start --client-name "$(hostname)-codex" --once --json
295
+
296
+ # Long-running bridge for Codex/Claude Code/Cursor wrappers
297
+ HYPERTAB_API_KEY=ht_sk_bridge... npx @hypertabai/mcp bridge start --client-name suleman-macbook --client-type codex --json
298
+
299
+ # Create a durable session/run while starting the bridge
300
+ npx @hypertabai/mcp bridge start --api-key ht_sk_... --objective "Run today's CRM enrichment audit" --json
301
+
302
+ # Report the result after a wrapper handles a delivered command
303
+ npx @hypertabai/mcp bridge result --api-key ht_sk_... --command-id cmd_... --status completed --json
304
+
305
+ # Inspect cloud-visible bridge freshness and command delivery state
306
+ npx @hypertabai/mcp bridge status --api-key ht_sk_... --json
307
+
308
+ # Send a batch of local progress events
309
+ npx @hypertabai/mcp bridge event batch --api-key ht_sk_... --file ./.hypertab/events.json --json
310
+
311
+ # Force replay of locally spooled bridge records
312
+ npx @hypertabai/mcp bridge flush --api-key ht_sk_... --json
313
+
314
+ # Upload a local screenshot/report/log/dataset into Hypertab artifact storage
315
+ npx @hypertabai/mcp bridge artifact upload --api-key ht_sk_... --run-id run_... --file ./screenshots/final.png --json
316
+
317
+ # Copy a safe starter wrapper into the current project
318
+ npx @hypertabai/mcp bridge wrapper init --type node --out ./.hypertab/bridge-wrapper.mjs --json
319
+
320
+ # Check local wrapper readiness before starting the loop
321
+ HYPERTAB_API_KEY=ht_sk_bridge... npx @hypertabai/mcp bridge wrapper doctor --path ./.hypertab/bridge-wrapper.mjs --json
322
+
323
+ # Run the starter wrapper with the same client identity bound into the bridge token
324
+ HYPERTAB_API_KEY=ht_sk_bridge... \
325
+ HYPERTAB_BRIDGE_CLIENT_NAME="$(hostname)-codex" \
326
+ HYPERTAB_BRIDGE_CLIENT_TYPE=codex \
327
+ node ./.hypertab/bridge-wrapper.mjs "Report local bridge health"
328
+ ```
329
+
330
+ `bridge token create` calls `POST /auth/bridge-token` with an admin-scoped key and prints the newly minted bridge-client
331
+ token once. Use the returned bridge token, not the admin key, for `bridge start`, wrapper doctor, wrapper run, event
332
+ batch, command result, status, and artifact upload. The JSON output includes `commands.doctor` and `commands.run` with
333
+ the correct `HYPERTAB_BRIDGE_CLIENT_NAME` and `HYPERTAB_BRIDGE_CLIENT_TYPE`; bridge-client tokens are bound to that
334
+ identity, so wrapper runs must keep those values stable.
335
+
336
+ `bridge start` calls the hosted REST API, not the MCP transport. It heartbeats the local client, optionally starts a
337
+ session/run, writes a start event through the batch endpoint, claims queued commands for that client, and prints each
338
+ command as JSON lines when `--json` is set. A wrapper around Codex, Claude Code, Cursor, or another local process can read
339
+ those lines, inspect the included `contract` metadata, handle the request under a local allowlist/confirmation policy,
340
+ then call `bridge result`.
341
+
342
+ `bridge status` reads the hosted bridge-health snapshot. It reports online/stale/offline/never-seen clients, attention
343
+ counts, queued commands, delivered commands waiting for a result, unsafe live commands, and per-client attention reasons.
344
+
345
+ `bridge event batch` reads a JSON file containing `{ "events": [...] }` or a raw events array and posts it to the
346
+ idempotent event-batch endpoint. Retryable failures are spooled locally and can be replayed with `bridge flush`.
347
+
348
+ Retryable event-batch and command-result failures are stored in a local JSONL spool at
349
+ `~/.hypertab/bridge-spool.jsonl` by default. `bridge start` flushes the spool during its loop, and `bridge flush` can be
350
+ used to replay it on demand. Set `HYPERTAB_BRIDGE_SPOOL` or `--spool-file` to choose a different path.
351
+
352
+ `bridge artifact upload` reads a local file, infers name/MIME/artifact type when not provided, base64-encodes the content,
353
+ and sends it to Hypertab's authenticated artifact API. The server stores upload bytes in R2, records artifact metadata,
354
+ and applies bridge/artifact budget checks before accepting the upload.
355
+
356
+ Wrapper recipes for Codex, Claude Code, Cursor, command-result reporting, batched progress events, and artifact upload
357
+ live in `docs/LOCAL-BRIDGE-WRAPPER-RECIPES.md` in the Hypertab repo. Safe command types and wrapper refusal rules live
358
+ in `docs/LOCAL-BRIDGE-COMMAND-CONTRACT.md`. `bridge_command` JSON lines include `contract.allowed`, plus a refusal
359
+ `reason` and `message` when the claimed command is unsafe or malformed.
360
+
361
+ Starter wrappers ship in `templates/`:
362
+
363
+ - `templates/bridge-wrapper.sh` -- minimal shell wrapper for one safe bridge cycle.
364
+ - `templates/bridge-wrapper.mjs` -- Node wrapper with safer JSON handling and command result reporting.
365
+
366
+ Both starters call `bridge start`, `bridge event batch`, `bridge status`, and `bridge result`, inspect
367
+ `bridge_command.contract.allowed`, and refuse or cancel commands that need local policy instead of executing payloads.
368
+ Run `hypertab bridge wrapper init --type node` or `--type shell` to copy one into `.hypertab/` with overwrite
369
+ protection. Use `--force` only when replacing a local wrapper intentionally.
370
+
371
+ Run `hypertab bridge wrapper doctor` after initialization or customization. It does not contact Hypertab; it checks the
372
+ local wrapper file, key availability, starter safety markers, and pending local spool records. It exits nonzero only for
373
+ hard blockers such as a missing wrapper or missing API key; custom wrapper marker gaps and pending spool records are
374
+ warnings.
375
+
112
376
  ## Troubleshooting
113
377
 
114
378
  **"Failed to parse existing config"** — your client's existing config file has invalid JSON. Fix it or delete it and re-run.
@@ -0,0 +1,157 @@
1
+ export type BridgeClientType = 'codex' | 'claude_code' | 'cursor' | 'browser' | 'cloud' | 'other';
2
+ export type BridgeCommandResultStatus = 'completed' | 'failed' | 'cancelled';
3
+ export declare const DEFAULT_BRIDGE_TIMEOUT_MS = 30000;
4
+ export interface BridgeAgentClient {
5
+ id: string;
6
+ name?: string;
7
+ type?: BridgeClientType;
8
+ [key: string]: unknown;
9
+ }
10
+ export interface BridgeAgentSession {
11
+ id: string;
12
+ client_id?: string | null;
13
+ [key: string]: unknown;
14
+ }
15
+ export interface BridgeAgentRun {
16
+ id: string;
17
+ client_id?: string | null;
18
+ session_id?: string | null;
19
+ [key: string]: unknown;
20
+ }
21
+ export interface BridgeAgentCommand {
22
+ id: string;
23
+ command_type: string;
24
+ payload?: Record<string, unknown>;
25
+ status?: string;
26
+ [key: string]: unknown;
27
+ }
28
+ export interface BridgeAgentArtifact {
29
+ id: string;
30
+ name?: string;
31
+ type?: string;
32
+ uri?: string | null;
33
+ mime_type?: string | null;
34
+ size_bytes?: number | null;
35
+ [key: string]: unknown;
36
+ }
37
+ export interface BridgeToken {
38
+ id: string;
39
+ api_key: string;
40
+ key_prefix: string;
41
+ name: string;
42
+ scopes: string[];
43
+ expires_at: string;
44
+ claims?: Record<string, unknown>;
45
+ }
46
+ export interface BridgeTokenCreatePayload {
47
+ name?: string;
48
+ client_name: string;
49
+ client_type: BridgeClientType;
50
+ expires_in_days: number;
51
+ metadata?: Record<string, unknown>;
52
+ }
53
+ export interface BridgeHealthSnapshot {
54
+ generated_at?: string;
55
+ summary?: Record<string, unknown>;
56
+ clients?: Array<Record<string, unknown>>;
57
+ [key: string]: unknown;
58
+ }
59
+ export interface BridgeEventBatchPayload {
60
+ events: Array<{
61
+ run_id: string;
62
+ type: 'message' | 'step' | 'tool_call' | 'file_change' | 'artifact' | 'approval' | 'error' | 'status';
63
+ message: string;
64
+ data?: Record<string, unknown>;
65
+ idempotency_key?: string;
66
+ }>;
67
+ }
68
+ export interface BridgeCommandResultPayload {
69
+ command_id: string;
70
+ client_id?: string;
71
+ status: BridgeCommandResultStatus;
72
+ error_message?: string | null;
73
+ }
74
+ export interface BridgeArtifactUploadPayload {
75
+ run_id?: string | null;
76
+ name: string;
77
+ type: string;
78
+ content_base64: string;
79
+ mime_type?: string | null;
80
+ size_bytes: number;
81
+ metadata?: Record<string, unknown>;
82
+ }
83
+ export interface BridgeApiError {
84
+ code: string;
85
+ message: string;
86
+ details?: unknown;
87
+ }
88
+ export type BridgeApiResponse<T> = {
89
+ ok: true;
90
+ status: number;
91
+ data: T;
92
+ } | {
93
+ ok: false;
94
+ status: number;
95
+ error: BridgeApiError;
96
+ };
97
+ export interface BridgeApiClient {
98
+ heartbeat(input: {
99
+ name: string;
100
+ type: BridgeClientType;
101
+ metadata?: Record<string, unknown>;
102
+ }): Promise<BridgeApiResponse<{
103
+ client: BridgeAgentClient;
104
+ }>>;
105
+ startSession(input: {
106
+ client_id: string;
107
+ metadata?: Record<string, unknown>;
108
+ }): Promise<BridgeApiResponse<{
109
+ session: BridgeAgentSession;
110
+ }>>;
111
+ createRun(input: {
112
+ title: string;
113
+ objective: string;
114
+ client_id: string;
115
+ session_id?: string | null;
116
+ source?: string;
117
+ metadata?: Record<string, unknown>;
118
+ }): Promise<BridgeApiResponse<{
119
+ run: BridgeAgentRun;
120
+ }>>;
121
+ appendEventBatch(input: BridgeEventBatchPayload): Promise<BridgeApiResponse<{
122
+ accepted: number;
123
+ deduped: number;
124
+ events: unknown[];
125
+ }>>;
126
+ claimCommands(input: {
127
+ client_id: string;
128
+ limit?: number;
129
+ }): Promise<BridgeApiResponse<{
130
+ commands: BridgeAgentCommand[];
131
+ delivered: number;
132
+ }>>;
133
+ reportCommandResult(input: BridgeCommandResultPayload): Promise<BridgeApiResponse<{
134
+ command: BridgeAgentCommand;
135
+ }>>;
136
+ uploadArtifact(input: BridgeArtifactUploadPayload): Promise<BridgeApiResponse<{
137
+ artifact: BridgeAgentArtifact;
138
+ }>>;
139
+ createBridgeToken(input: BridgeTokenCreatePayload): Promise<BridgeApiResponse<{
140
+ token: BridgeToken;
141
+ client: BridgeAgentClient;
142
+ }>>;
143
+ getBridgeHealth(input: {
144
+ client_id?: string;
145
+ limit?: number;
146
+ }): Promise<BridgeApiResponse<{
147
+ bridge_health: BridgeHealthSnapshot;
148
+ }>>;
149
+ }
150
+ export interface BridgeApiClientOptions {
151
+ apiUrl: string;
152
+ apiKey: string;
153
+ timeoutMs?: number;
154
+ fetchImpl?: typeof fetch;
155
+ }
156
+ export declare function createBridgeApiClient(options: BridgeApiClientOptions): BridgeApiClient;
157
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/bridge/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import { buildClientOperationIdempotencyKey, OPERATION_IDEMPOTENCY_HEADER } from '../idempotency.js';
2
+ export const DEFAULT_BRIDGE_TIMEOUT_MS = 30_000;
3
+ export function createBridgeApiClient(options) {
4
+ const timeoutMs = options.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
5
+ const requestOnce = async (path, input) => {
6
+ const fetchImpl = options.fetchImpl ?? fetch;
7
+ const controller = new AbortController();
8
+ let timedOut = false;
9
+ const timer = setTimeout(() => {
10
+ timedOut = true;
11
+ controller.abort();
12
+ }, timeoutMs);
13
+ try {
14
+ const headers = {
15
+ Authorization: `Bearer ${options.apiKey}`,
16
+ 'Content-Type': 'application/json',
17
+ };
18
+ if (input.idempotencyKey)
19
+ headers[OPERATION_IDEMPOTENCY_HEADER] = input.idempotencyKey;
20
+ const res = await fetchImpl(`${options.apiUrl.replace(/\/$/, '')}${path}`, {
21
+ method: input.method ?? (input.body === undefined ? 'GET' : 'POST'),
22
+ headers,
23
+ body: input.body === undefined ? undefined : JSON.stringify(input.body),
24
+ signal: controller.signal,
25
+ });
26
+ return await parseBridgeResponse(res);
27
+ }
28
+ catch (error) {
29
+ if (timedOut) {
30
+ return {
31
+ ok: false,
32
+ status: 0,
33
+ error: {
34
+ code: 'BRIDGE_REQUEST_TIMEOUT',
35
+ message: `Bridge API request to ${path} timed out after ${timeoutMs}ms without a response. ` +
36
+ 'The Hypertab API may be stalled. Retry the command, or pass --timeout-ms to wait longer. ' +
37
+ 'Spooled event/result records stay queued locally and flush on the next bridge cycle.',
38
+ details: { path, timeout_ms: timeoutMs },
39
+ },
40
+ };
41
+ }
42
+ return {
43
+ ok: false,
44
+ status: 0,
45
+ error: {
46
+ code: 'BRIDGE_API_UNREACHABLE',
47
+ message: error instanceof Error ? error.message : 'Bridge API request failed before receiving a response.',
48
+ },
49
+ };
50
+ }
51
+ finally {
52
+ clearTimeout(timer);
53
+ }
54
+ };
55
+ const request = async (path, input = {}) => {
56
+ const first = await requestOnce(path, input);
57
+ // Retry exactly once, only for operations that carry an idempotent contract,
58
+ // and only on transient failures where no response was received (status 0).
59
+ if (first.ok || !input.retryOnTransientFailure || first.status !== 0)
60
+ return first;
61
+ return requestOnce(path, input);
62
+ };
63
+ return {
64
+ heartbeat: (input) => request('/api/agent/clients/heartbeat', { body: input }),
65
+ startSession: (input) => request('/api/agent/sessions', { body: input }),
66
+ createRun: (input) => request('/api/agent/runs', { body: input }),
67
+ appendEventBatch: (input) => request('/api/agent/events/batch', { body: input }),
68
+ claimCommands: (input) => request('/api/agent/commands/claim', { body: input }),
69
+ reportCommandResult: (input) => request(`/api/agent/commands/${encodeURIComponent(input.command_id)}/result`, {
70
+ body: {
71
+ client_id: input.client_id,
72
+ status: input.status,
73
+ error_message: input.error_message,
74
+ },
75
+ retryOnTransientFailure: true,
76
+ idempotencyKey: buildClientOperationIdempotencyKey({
77
+ operation: 'bridge.command.result',
78
+ target: input.command_id,
79
+ payload: {
80
+ client_id: input.client_id ?? null,
81
+ status: input.status,
82
+ error_message: input.error_message ?? null,
83
+ },
84
+ }),
85
+ }),
86
+ uploadArtifact: (input) => request('/api/agent/artifacts', {
87
+ body: input,
88
+ retryOnTransientFailure: true,
89
+ idempotencyKey: buildClientOperationIdempotencyKey({
90
+ operation: 'bridge.artifact.upload',
91
+ target: input.run_id ?? undefined,
92
+ fingerprint: `${input.name}|${input.size_bytes}|${input.content_base64}`,
93
+ }),
94
+ }),
95
+ createBridgeToken: (input) => request('/auth/bridge-token', { body: input }),
96
+ getBridgeHealth: (input) => request(`/api/agent/bridge/health${bridgeHealthQuery(input)}`, { retryOnTransientFailure: true }),
97
+ };
98
+ }
99
+ function bridgeHealthQuery(input) {
100
+ const params = new URLSearchParams();
101
+ if (input.client_id)
102
+ params.set('client_id', input.client_id);
103
+ if (input.limit)
104
+ params.set('limit', String(input.limit));
105
+ const query = params.toString();
106
+ return query ? `?${query}` : '';
107
+ }
108
+ async function parseBridgeResponse(res) {
109
+ const text = await res.text();
110
+ const payload = parseEnvelope(text);
111
+ if (res.ok && payload.success === true) {
112
+ return { ok: true, status: res.status, data: payload.data };
113
+ }
114
+ return {
115
+ ok: false,
116
+ status: res.status,
117
+ error: {
118
+ code: payload.error?.code ?? 'BRIDGE_API_FAILED',
119
+ message: payload.error?.message ?? `Bridge API failed with HTTP ${res.status}.`,
120
+ details: payload.error?.details,
121
+ },
122
+ };
123
+ }
124
+ function parseEnvelope(text) {
125
+ if (!text)
126
+ return {};
127
+ try {
128
+ return JSON.parse(text);
129
+ }
130
+ catch {
131
+ return {
132
+ success: false,
133
+ error: {
134
+ code: 'BRIDGE_API_INVALID_JSON',
135
+ message: text.slice(0, 500),
136
+ },
137
+ };
138
+ }
139
+ }
140
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/bridge/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { BridgeArtifactUploadPayload } from './api-client.js';
2
+ export interface PrepareBridgeArtifactInput {
3
+ file: string;
4
+ runId?: string;
5
+ name?: string;
6
+ type?: string;
7
+ mimeType?: string;
8
+ metadataJson?: string;
9
+ }
10
+ export declare function prepareBridgeArtifactUpload(input: PrepareBridgeArtifactInput): Promise<BridgeArtifactUploadPayload>;
11
+ //# sourceMappingURL=artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../../src/bridge/artifacts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAA;AAElE,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAYzH"}
@@ -0,0 +1,45 @@
1
+ import { readFile, stat } from 'node:fs/promises';
2
+ import { basename } from 'node:path';
3
+ import { lookup } from 'mime-types';
4
+ export async function prepareBridgeArtifactUpload(input) {
5
+ const [bytes, stats] = await Promise.all([readFile(input.file), stat(input.file)]);
6
+ if (!stats.isFile())
7
+ throw new Error(`Artifact path '${input.file}' is not a file.`);
8
+ return {
9
+ run_id: input.runId ?? null,
10
+ name: input.name ?? basename(input.file),
11
+ type: input.type ?? inferArtifactType(input.file),
12
+ content_base64: bytes.toString('base64'),
13
+ mime_type: input.mimeType ?? inferMimeType(input.file),
14
+ size_bytes: bytes.byteLength,
15
+ metadata: parseMetadata(input.metadataJson),
16
+ };
17
+ }
18
+ function inferMimeType(file) {
19
+ const detected = lookup(file);
20
+ return typeof detected === 'string' ? detected : 'application/octet-stream';
21
+ }
22
+ function inferArtifactType(file) {
23
+ const mimeType = inferMimeType(file);
24
+ if (mimeType === 'application/json')
25
+ return 'dataset';
26
+ if (mimeType === 'text/csv')
27
+ return 'dataset';
28
+ if (mimeType?.startsWith('image/'))
29
+ return 'screenshot';
30
+ if (mimeType?.startsWith('text/'))
31
+ return 'log';
32
+ if (mimeType === 'application/pdf')
33
+ return 'report';
34
+ return 'file';
35
+ }
36
+ function parseMetadata(metadataJson) {
37
+ if (!metadataJson)
38
+ return undefined;
39
+ const parsed = JSON.parse(metadataJson);
40
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
41
+ throw new Error('Artifact metadata must be a JSON object.');
42
+ }
43
+ return parsed;
44
+ }
45
+ //# sourceMappingURL=artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../src/bridge/artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAYnC,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAAiC;IAClF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAClF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,CAAC,IAAI,kBAAkB,CAAC,CAAA;IACpF,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;QAC3B,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QACxC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC;QACjD,cAAc,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACxC,SAAS,EAAE,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC;QACtD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,YAAY,CAAC;KAC3C,CAAA;AACF,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAC7B,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,0BAA0B,CAAA;AAC5E,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACtC,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IACpC,IAAI,QAAQ,KAAK,kBAAkB;QAAE,OAAO,SAAS,CAAA;IACrD,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO,SAAS,CAAA;IAC7C,IAAI,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,YAAY,CAAA;IACvD,IAAI,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAC/C,IAAI,QAAQ,KAAK,iBAAiB;QAAE,OAAO,QAAQ,CAAA;IACnD,OAAO,MAAM,CAAA;AACd,CAAC;AAED,SAAS,aAAa,CAAC,YAAgC;IACtD,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAA;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAY,CAAA;IAClD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,MAAiC,CAAA;AACzC,CAAC"}