@outcrawl/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.
@@ -0,0 +1,466 @@
1
+ /**
2
+ * The capability registry.
3
+ *
4
+ * One list, four surfaces. The API is the truth; the SDK, MCP server and CLI
5
+ * are generated or checked against this array. The failure mode it exists to
6
+ * prevent is a feature landing in the SDK and reaching MCP six months later —
7
+ * which has already happened once, at a smaller scale, with session replay.
8
+ *
9
+ * Adding a capability means adding one row here and letting every surface fail
10
+ * until it carries it. Removing a column from a row is not allowed — but two
11
+ * of the columns are legitimately empty, and that is a different fact.
12
+ *
13
+ * `mcpTool` and `cliCommand` are nullable, because a capability appears in a
14
+ * surface only where its user can act on it: an assistant must never manage a
15
+ * credit card or connect an integration, and the CLI serves a human and CI and
16
+ * does not need a replay viewer. The matrix is in `docs/AGENTS.md` and it is
17
+ * the design, not a backlog. What is still forbidden is the OMISSION: both
18
+ * fields are required-and-nullable, so a row that has no MCP tool has to write
19
+ * `mcpTool: null` and a row that forgot does not compile. See the field docs.
20
+ *
21
+ * **A deliberate `null` and a forgotten field must not be spellable the same
22
+ * way.** This is the third time this codebase has arrived at that rule — after
23
+ * `streamsWhen` below, and after `AgentBindingOptions`, where `model`,
24
+ * `solveChallenge`, `tabs` and `pointerSink` were each optional, each omitted
25
+ * at a composition root, and each absent in production for the life of a
26
+ * feature with nothing failing. Somebody being tidy will propose `?:` here
27
+ * again; the answer is no, and this paragraph is why.
28
+ */
29
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
30
+ export interface Capability {
31
+ /** Dotted, stable. The key every surface addresses this capability by. */
32
+ name: string;
33
+ method: HttpMethod;
34
+ /** REST path. `{id}` marks a path parameter. */
35
+ path: string;
36
+ /**
37
+ * One line. This is product copy for an audience of one model — MCP tool
38
+ * descriptions are prompts, and a model picks between tools on this text
39
+ * alone, so each says what the tool is *not* for.
40
+ */
41
+ summary: string;
42
+ /**
43
+ * MCP tool name, or `null` when no MCP tool should exist.
44
+ *
45
+ * Required rather than optional, for the same reason as `streamsWhen` below:
46
+ * `mcpTool?: string` compiles on a row that omits it, so "we decided this
47
+ * capability has no tool" and "nobody said" would be the same bytes. They are
48
+ * not the same fact — the first is the `docs/AGENTS.md` matrix and the second
49
+ * is the defect this file exists to prevent. Never the empty string, which
50
+ * would be a third spelling of the same idea; `core/test/registry.test.ts`
51
+ * refuses it.
52
+ *
53
+ * The nulls do not cost the exhaustiveness that makes this registry worth
54
+ * having. They split it: {@link McpCapabilityName} and
55
+ * {@link CliCapabilityName} are derived from these two columns, and MCP and
56
+ * the CLI key their per-capability tables by those instead of by
57
+ * `CapabilityName`. So a row that declares a tool still fails the MCP build
58
+ * until it has a shape and copy, and a row that declares `null` cannot
59
+ * acquire one — the key is not in the union, and an object literal that
60
+ * offers it is an excess property.
61
+ */
62
+ mcpTool: string | null;
63
+ /**
64
+ * CLI invocation without the `outcrawl` prefix, or `null` when no command
65
+ * should exist. Required-and-nullable on the same terms as `mcpTool`.
66
+ */
67
+ cliCommand: string | null;
68
+ /**
69
+ * Every capability is authenticated: the router checks an API key and an IP
70
+ * allowlist before it picks a worker. Health and version endpoints are not
71
+ * capabilities and are not listed here.
72
+ */
73
+ requiresAuth: boolean;
74
+ /**
75
+ * How the response body is framed.
76
+ *
77
+ * `'json'` is one object. `'ndjson'` is a header frame followed by zero or
78
+ * more item frames, one JSON object per line, delivered as they are produced.
79
+ *
80
+ * This field exists because the registry could not express it, and two
81
+ * surfaces immediately disagreed about the same capability: the SDK read
82
+ * crawl as a stream because §7 specifies `for await`, while the CLI declined
83
+ * to offer `--stream` because no row said it was one. Both reasoned correctly
84
+ * from an incomplete registry. A capability whose framing is undeclared is
85
+ * one every surface has to guess about, which is the failure this registry
86
+ * exists to prevent.
87
+ */
88
+ framing: 'json' | 'ndjson';
89
+ /**
90
+ * The request field that switches this row to `'ndjson'`, when it has one.
91
+ *
92
+ * Three rows stream and they do not stream the same way. `crawl` is always
93
+ * ndjson. `agent` is json unless the request sets `stream`. `sessions.get` is
94
+ * json unless it sets `live`. Declaring only a single default framing was a
95
+ * half-fix: it said something false about the two rows that switch, and left
96
+ * a surface to invent the field name — which is exactly what happened, since
97
+ * `live` reached the SDK before it reached this registry.
98
+ *
99
+ * `null` means the framing above is the only one this row produces.
100
+ * Required rather than optional on purpose: an optional field that every
101
+ * surface is supposed to consult is the field that gets forgotten, and on a
102
+ * const-asserted array it is not even reachable on the rows that omit it —
103
+ * MCP hit exactly that. A new row must now state whether it streams.
104
+ */
105
+ streamsWhen: string | null;
106
+ }
107
+ /**
108
+ * Not listed, deliberately: the live Playwright `page` — `page.act`,
109
+ * `page.observe`, `page.hands`. It only exists in the SDK because it needs a
110
+ * live CDP connection in the caller's own process. API, MCP and CLI reach the
111
+ * same capabilities through `agent` and `scrape`, which run the loop on our
112
+ * side. That is a difference in kind, not an omission.
113
+ */
114
+ export declare const CAPABILITIES: readonly [{
115
+ readonly name: "scrape";
116
+ readonly method: "POST";
117
+ readonly path: "/v1/scrape";
118
+ readonly summary: "Fetch one URL and return clean content in the requested formats. Use for a single known page; not for following links, and not for tasks that need decisions.";
119
+ readonly mcpTool: "outcrawl_scrape";
120
+ readonly cliCommand: "scrape";
121
+ readonly requiresAuth: true;
122
+ readonly framing: "json";
123
+ readonly streamsWhen: null;
124
+ }, {
125
+ readonly name: "crawl";
126
+ readonly method: "POST";
127
+ readonly path: "/v1/crawl";
128
+ readonly summary: "Walk a site from a seed URL and stream every page as it is scraped. Use when the set of URLs is unknown; not for one page, and not for content behind a login flow.";
129
+ readonly mcpTool: "outcrawl_crawl";
130
+ readonly cliCommand: "crawl";
131
+ readonly requiresAuth: true;
132
+ readonly framing: "ndjson";
133
+ readonly streamsWhen: null;
134
+ }, {
135
+ readonly name: "search";
136
+ readonly method: "POST";
137
+ readonly path: "/v1/search";
138
+ readonly summary: "Web search, optionally with every hit rendered through our scrape pipeline. Use to find pages; not to read one you already have a URL for.";
139
+ readonly mcpTool: "outcrawl_search";
140
+ readonly cliCommand: "search";
141
+ readonly requiresAuth: true;
142
+ readonly framing: "json";
143
+ readonly streamsWhen: null;
144
+ }, {
145
+ readonly name: "monitors.create";
146
+ readonly method: "POST";
147
+ readonly path: "/v1/monitors";
148
+ readonly summary: "Watch a URL on a schedule and notify on real change via Discord, Slack or webhook. Use for recurring checks; not for a one-off comparison.";
149
+ readonly mcpTool: "outcrawl_monitor_create";
150
+ readonly cliCommand: "monitors create";
151
+ readonly requiresAuth: true;
152
+ readonly framing: "json";
153
+ readonly streamsWhen: null;
154
+ }, {
155
+ readonly name: "monitors.list";
156
+ readonly method: "GET";
157
+ readonly path: "/v1/monitors";
158
+ readonly summary: "List monitors with their last check status.";
159
+ readonly mcpTool: "outcrawl_monitor_list";
160
+ readonly cliCommand: "monitors ls";
161
+ readonly requiresAuth: true;
162
+ readonly framing: "json";
163
+ readonly streamsWhen: null;
164
+ }, {
165
+ readonly name: "monitors.delete";
166
+ readonly method: "DELETE";
167
+ readonly path: "/v1/monitors/{id}";
168
+ readonly summary: "Delete a monitor and stop its schedule. Snapshots are discarded.";
169
+ readonly mcpTool: "outcrawl_monitor_delete";
170
+ readonly cliCommand: "monitors rm";
171
+ readonly requiresAuth: true;
172
+ readonly framing: "json";
173
+ readonly streamsWhen: null;
174
+ }, {
175
+ readonly name: "agent";
176
+ readonly method: "POST";
177
+ readonly path: "/v1/agent";
178
+ readonly summary: "Submit a natural-language browser task as a JOB and get an id back in milliseconds. The run is not held open on this call and hours are normal: read outcrawl_agent_status for the answer, outcrawl_agent_results for the records it appended, and outcrawl_agent_cancel to stop it. Use when the page needs decisions or interaction; not for plain reading, where scrape is far cheaper.";
179
+ readonly mcpTool: "outcrawl_agent";
180
+ readonly cliCommand: "agent";
181
+ readonly requiresAuth: true;
182
+ readonly framing: "json";
183
+ readonly streamsWhen: null;
184
+ }, {
185
+ readonly name: "agent.get";
186
+ readonly method: "GET";
187
+ readonly path: "/v1/agent/{id}";
188
+ readonly summary: "Where one run has got to: status, the plan it stated, what it has spent, and its answer once it has one. Safe to call as often as you like — it is a row read, not a browser. Use it to find out whether a submitted run has finished; not to fetch the records it produced, which is outcrawl_agent_results.";
189
+ readonly mcpTool: "outcrawl_agent_status";
190
+ readonly cliCommand: "agent status";
191
+ readonly requiresAuth: true;
192
+ readonly framing: "json";
193
+ readonly streamsWhen: null;
194
+ }, {
195
+ readonly name: "agent.events";
196
+ readonly method: "GET";
197
+ readonly path: "/v1/agent/{id}/events";
198
+ readonly summary: "Everything a run has done, in order, from a cursor: steps, findings, dead ends, plan changes. Ask for the verbosity you want with `level`, and resume with the `after` sequence you last saw rather than re-reading from the start. Use it to watch or audit a run; not to get its answer, which is outcrawl_agent_status.";
199
+ readonly mcpTool: "outcrawl_agent_events";
200
+ readonly cliCommand: "agent events";
201
+ readonly requiresAuth: true;
202
+ readonly framing: "ndjson";
203
+ readonly streamsWhen: null;
204
+ }, {
205
+ readonly name: "agent.results";
206
+ readonly method: "GET";
207
+ readonly path: "/v1/agent/{id}/results";
208
+ readonly summary: "The records a run appended, a page at a time, oldest first. Records land DURING the run, so this answers before the run has finished and a killed run still delivers what it bought. Use it for the data; not for whether the run is done, which is outcrawl_agent_status.";
209
+ readonly mcpTool: "outcrawl_agent_results";
210
+ readonly cliCommand: "agent results";
211
+ readonly requiresAuth: true;
212
+ readonly framing: "json";
213
+ readonly streamsWhen: null;
214
+ }, {
215
+ readonly name: "agent.cancel";
216
+ readonly method: "POST";
217
+ readonly path: "/v1/agent/{id}/cancel";
218
+ readonly summary: "Stop a run. It settles with whatever it had reached and everything it already appended stays yours; work already performed is still billed, because caps are the protection and not a refund argued afterwards. Use it to stop spending; not to delete the output.";
219
+ readonly mcpTool: "outcrawl_agent_cancel";
220
+ readonly cliCommand: "agent cancel";
221
+ readonly requiresAuth: true;
222
+ readonly framing: "json";
223
+ readonly streamsWhen: null;
224
+ }, {
225
+ readonly name: "agent.control";
226
+ readonly method: "POST";
227
+ readonly path: "/v1/agent/{id}/control";
228
+ readonly summary: "Take the wheel of a live run, or hand it back. Taking it PAUSES the agent where it stands with the browser still open, and answers the URL a person drives it at; handing it back resumes the same run on whatever page you left it on. Use it when a run needs a human for one step — a login you will not automate, a form only you can fill; not to stop a run, which is outcrawl_agent_cancel, and not to answer a question the agent asked, which is outcrawl_agent_answer.";
229
+ readonly mcpTool: "outcrawl_agent_control";
230
+ readonly cliCommand: "agent control";
231
+ readonly requiresAuth: true;
232
+ readonly framing: "json";
233
+ readonly streamsWhen: null;
234
+ }, {
235
+ readonly name: "agent.answer";
236
+ readonly method: "POST";
237
+ readonly path: "/v1/agent/{id}/answer";
238
+ readonly summary: "Answer the question a paused run is waiting on, and it carries on from where it stopped. A run parks when it needs something only you know — which of two options, a detail you did not give it — and reports the question on its status and its event stream. Use it to unblock a run whose status is paused; not to send a run new instructions, which no route does, and not to take over the browser yourself, which is outcrawl_agent_control.";
239
+ readonly mcpTool: "outcrawl_agent_answer";
240
+ readonly cliCommand: "agent answer";
241
+ readonly requiresAuth: true;
242
+ readonly framing: "json";
243
+ readonly streamsWhen: null;
244
+ }, {
245
+ readonly name: "agent.files";
246
+ readonly method: "POST";
247
+ readonly path: "/v1/agent/{id}/files";
248
+ readonly summary: "Hand a file to a run so it can attach it to a page — at submit time, mid-run, or before its first step. Answers a HANDLE the agent uses with attachFile; you never send the bytes twice and the model never sees them. The file is destroyed when the run ends, on every ending. Use it for something the task needs to upload; not to fetch a file the run produced, because downloads do not exist.";
249
+ readonly mcpTool: "outcrawl_agent_file_add";
250
+ readonly cliCommand: "agent files add";
251
+ readonly requiresAuth: true;
252
+ readonly framing: "json";
253
+ readonly streamsWhen: null;
254
+ }, {
255
+ readonly name: "profiles.create";
256
+ readonly method: "POST";
257
+ readonly path: "/v1/profiles";
258
+ readonly summary: "Mint a durable identity with pinned exit and persistent storage. Use to keep a login across sessions; the identity itself is minted, never chosen.";
259
+ readonly mcpTool: "outcrawl_profile_create";
260
+ readonly cliCommand: "profiles create";
261
+ readonly requiresAuth: true;
262
+ readonly framing: "json";
263
+ readonly streamsWhen: null;
264
+ }, {
265
+ readonly name: "profiles.list";
266
+ readonly method: "GET";
267
+ readonly path: "/v1/profiles";
268
+ readonly summary: "List profiles, optionally filtered by a label glob.";
269
+ readonly mcpTool: "outcrawl_profile_list";
270
+ readonly cliCommand: "profiles ls";
271
+ readonly requiresAuth: true;
272
+ readonly framing: "json";
273
+ readonly streamsWhen: null;
274
+ }, {
275
+ readonly name: "profiles.get";
276
+ readonly method: "GET";
277
+ readonly path: "/v1/profiles/{id}";
278
+ readonly summary: "Fetch one profile: its label, pinned exit and creation time.";
279
+ readonly mcpTool: "outcrawl_profile_get";
280
+ readonly cliCommand: "profiles get";
281
+ readonly requiresAuth: true;
282
+ readonly framing: "json";
283
+ readonly streamsWhen: null;
284
+ }, {
285
+ readonly name: "profiles.delete";
286
+ readonly method: "DELETE";
287
+ readonly path: "/v1/profiles/{id}";
288
+ readonly summary: "Delete a profile and its stored cookies and site data. Irreversible.";
289
+ readonly mcpTool: "outcrawl_profile_delete";
290
+ readonly cliCommand: "profiles rm";
291
+ readonly requiresAuth: true;
292
+ readonly framing: "json";
293
+ readonly streamsWhen: null;
294
+ }, {
295
+ readonly name: "sessions.list";
296
+ readonly method: "GET";
297
+ readonly path: "/v1/sessions";
298
+ readonly summary: "Query past sessions by status, outcome, task or age — twenty replays to watch rather than twenty log lines to guess from.";
299
+ readonly mcpTool: null;
300
+ readonly cliCommand: null;
301
+ readonly requiresAuth: true;
302
+ readonly framing: "json";
303
+ readonly streamsWhen: null;
304
+ }, {
305
+ readonly name: "sessions.get";
306
+ readonly method: "GET";
307
+ readonly path: "/v1/sessions/{id}";
308
+ readonly summary: "Fetch one session with its replay URL, duration, page count and usage. This is how a charge is disputed: watch what it bought.";
309
+ readonly mcpTool: null;
310
+ readonly cliCommand: null;
311
+ readonly requiresAuth: true;
312
+ readonly framing: "json";
313
+ readonly streamsWhen: "live";
314
+ }, {
315
+ readonly name: "sessions.export";
316
+ readonly method: "POST";
317
+ readonly path: "/v1/sessions/{id}/export";
318
+ readonly summary: "Export a session as a portable bundle that plays offline.";
319
+ readonly mcpTool: null;
320
+ readonly cliCommand: null;
321
+ readonly requiresAuth: true;
322
+ readonly framing: "json";
323
+ readonly streamsWhen: null;
324
+ }, {
325
+ readonly name: "usage";
326
+ readonly method: "GET";
327
+ readonly path: "/v1/usage";
328
+ readonly summary: "Aggregate the same usage numbers already attached to each call. Nothing appears here that was not visible on the call that caused it.";
329
+ readonly mcpTool: "outcrawl_usage";
330
+ readonly cliCommand: "usage";
331
+ readonly requiresAuth: true;
332
+ readonly framing: "json";
333
+ readonly streamsWhen: null;
334
+ }, {
335
+ readonly name: "credits";
336
+ readonly method: "GET";
337
+ readonly path: "/v1/credits";
338
+ readonly summary: "What this account has been granted, what it has spent against the grant, and what is left. Use to see a promotional or student balance and when it lapses; not for the monthly plan allowance, and not for per-call cost, which every response already carries.";
339
+ readonly mcpTool: "outcrawl_credits";
340
+ readonly cliCommand: "credits";
341
+ readonly requiresAuth: true;
342
+ readonly framing: "json";
343
+ readonly streamsWhen: null;
344
+ }, {
345
+ readonly name: "secrets.create";
346
+ readonly method: "POST";
347
+ readonly path: "/v1/secrets";
348
+ readonly summary: "Store a credential under a handle an agent can reference but never read. Use to save a card or an environment variable for a run to use; not to read one back, which nothing can do.";
349
+ readonly mcpTool: null;
350
+ readonly cliCommand: "secrets create";
351
+ readonly requiresAuth: true;
352
+ readonly framing: "json";
353
+ readonly streamsWhen: null;
354
+ }, {
355
+ readonly name: "secrets.list";
356
+ readonly method: "GET";
357
+ readonly path: "/v1/secrets";
358
+ readonly summary: "List stored credentials by handle, with the last four digits of a card and nothing else. No route returns a value, and that absence is the point.";
359
+ readonly mcpTool: null;
360
+ readonly cliCommand: "secrets ls";
361
+ readonly requiresAuth: true;
362
+ readonly framing: "json";
363
+ readonly streamsWhen: null;
364
+ }, {
365
+ readonly name: "secrets.delete";
366
+ readonly method: "DELETE";
367
+ readonly path: "/v1/secrets/{id}";
368
+ readonly summary: "Delete a credential and the record of which runs used it. Takes effect on the next fill: a run holding a grant finds nothing to resolve.";
369
+ readonly mcpTool: null;
370
+ readonly cliCommand: "secrets rm";
371
+ readonly requiresAuth: true;
372
+ readonly framing: "json";
373
+ readonly streamsWhen: null;
374
+ }, {
375
+ readonly name: "rules.get";
376
+ readonly method: "GET";
377
+ readonly path: "/v1/rules";
378
+ readonly summary: "The workspace rules and, for each one, whether it is ENFORCED as a gate that blocks a dispatch or is only GUIDANCE in the prompt. Use it to check that a rule you wrote is actually enforced; the class is the answer, not the text.";
379
+ readonly mcpTool: "outcrawl_rules_get";
380
+ readonly cliCommand: "rules get";
381
+ readonly requiresAuth: true;
382
+ readonly framing: "json";
383
+ readonly streamsWhen: null;
384
+ }, {
385
+ readonly name: "rules.set";
386
+ readonly method: "PUT";
387
+ readonly path: "/v1/rules";
388
+ readonly summary: "Replace the workspace rules with these plain-language sentences and get the classification back on the same call. Use to forbid something in your own words; a rule that could not be compiled into a gate comes back as guidance with the reason.";
389
+ readonly mcpTool: "outcrawl_rules_set";
390
+ readonly cliCommand: "rules set";
391
+ readonly requiresAuth: true;
392
+ readonly framing: "json";
393
+ readonly streamsWhen: null;
394
+ }, {
395
+ readonly name: "integrations.connect";
396
+ readonly method: "POST";
397
+ readonly path: "/v1/integrations";
398
+ readonly summary: "Connect an MCP server — Gmail, Slack, Twilio — so a run can call its tools mid-task. HTTPS endpoints only, authenticated by a secret handle, and no run reaches it unless the run names it. Use to give an agent a way past a wall the browser cannot climb; not to store the credential itself, which is a secret and has no tool.";
399
+ readonly mcpTool: null;
400
+ readonly cliCommand: "integrations connect";
401
+ readonly requiresAuth: true;
402
+ readonly framing: "json";
403
+ readonly streamsWhen: null;
404
+ }, {
405
+ readonly name: "integrations.list";
406
+ readonly method: "GET";
407
+ readonly path: "/v1/integrations";
408
+ readonly summary: "Everything an agent can reach outside the browser: each connected server, the tools it exposes, and the secret handle it authenticates with. This is the blast radius, and a customer who cannot see it cannot consent to it.";
409
+ readonly mcpTool: null;
410
+ readonly cliCommand: "integrations ls";
411
+ readonly requiresAuth: true;
412
+ readonly framing: "json";
413
+ readonly streamsWhen: null;
414
+ }, {
415
+ readonly name: "integrations.delete";
416
+ readonly method: "DELETE";
417
+ readonly path: "/v1/integrations/{id}";
418
+ readonly summary: "Disconnect an MCP server. Takes effect on the next call: a run already holding a grant finds the connector gone and is told so. The credential is untouched — it lives in the secrets store and is deleted there.";
419
+ readonly mcpTool: null;
420
+ readonly cliCommand: "integrations rm";
421
+ readonly requiresAuth: true;
422
+ readonly framing: "json";
423
+ readonly streamsWhen: null;
424
+ }];
425
+ export type CapabilityName = (typeof CAPABILITIES)[number]['name'];
426
+ /**
427
+ * One row of the array above, with its literal `name` intact.
428
+ *
429
+ * Not `Capability`: the interface declares `name: string`, and reading a row
430
+ * through it turns every `Record<CapabilityName, …>` downstream into
431
+ * `Record<string, …>`, which checks nothing.
432
+ */
433
+ type RegistryRow = (typeof CAPABILITIES)[number];
434
+ /**
435
+ * The rows that declare an MCP tool, and the rows that declare a CLI command.
436
+ *
437
+ * This is where the nullable columns pay for themselves. `Extract` keeps only
438
+ * the rows whose column is a string, so `McpCapabilityName` is the exact set of
439
+ * capabilities MCP is supposed to carry — no wider, and derived rather than
440
+ * listed a second time. MCP keys its shapes and copy by it and the CLI keys its
441
+ * arguments by its own, which makes both tables exhaustive over their own
442
+ * surface: a row that declares a tool does not compile until it has one, and a
443
+ * row that declares `null` cannot be given one.
444
+ */
445
+ export type McpCapability = Extract<RegistryRow, {
446
+ mcpTool: string;
447
+ }>;
448
+ export type CliCapability = Extract<RegistryRow, {
449
+ cliCommand: string;
450
+ }>;
451
+ export type McpCapabilityName = McpCapability['name'];
452
+ export type CliCapabilityName = CliCapability['name'];
453
+ /**
454
+ * The same rows, in registry order, for the surfaces to map over. The
455
+ * predicates are type guards, so the narrowed element type carries a `string`
456
+ * column and a surface never has to check a null the registry ruled out.
457
+ */
458
+ export declare const MCP_CAPABILITIES: readonly McpCapability[];
459
+ export declare const CLI_CAPABILITIES: readonly CliCapability[];
460
+ /**
461
+ * Look up a capability by name. Throws rather than returning undefined: every
462
+ * caller here is a surface being built against the registry, and a missing
463
+ * capability is a build-time bug, not a runtime condition to handle.
464
+ */
465
+ export declare function getCapability(name: CapabilityName): Capability;
466
+ export {};