@yaklabs-ai/plugin-sdk 0.15.3 → 0.26.3
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.
- package/README.md +25 -5
- package/THIRD-PARTY-INVENTORY.json +9 -9
- package/THIRD-PARTY-NOTICES.md +8 -8
- package/dist/agent-conversation.d.ts +1 -1
- package/dist/canonical-transcript.d.ts +133 -123
- package/dist/canonical-transcript.js +111 -39
- package/dist/disclosure.d.ts +1582 -744
- package/dist/disclosure.js +48 -59
- package/dist/kay-agent-testing.d.ts +2505 -590
- package/dist/kay-agent-testing.js +96 -3
- package/dist/kay-agent.d.ts +1784 -1716
- package/dist/kay-agent.js +302 -310
- package/dist/kay-app-session-summary.d.ts +999 -144
- package/dist/kay-app-session-summary.js +15 -15
- package/dist/kay-app.d.ts +3414 -830
- package/dist/kay-app.js +412 -6
- package/dist/phase-shift.d.ts +4 -4
- package/dist/system-one.d.ts +13 -0
- package/dist/time.d.ts +2 -4
- package/dist/transcript-review.d.ts +10 -0
- package/dist/transcript-review.js +104 -31
- package/dist/transcript.d.ts +8 -6
- package/dist/vendored-mcp.d.ts +434 -305
- package/dist/vendored-mcp.js +278 -101
- package/dist/whiteboard.d.ts +82 -0
- package/dist/whiteboard.js +174 -0
- package/package.json +5 -1
package/dist/vendored-mcp.d.ts
CHANGED
|
@@ -12,23 +12,30 @@
|
|
|
12
12
|
* It could, and V1 deliberately does not. These servers have no uniform read: several expose only
|
|
13
13
|
* tools, and PostHog's is a single `exec` tool over a CLI-style DSL. There is no shape to project
|
|
14
14
|
* generically, so a generic MCP read would be a guess per vendor wearing one function's clothes.
|
|
15
|
-
* Instead `read` returns a reference card
|
|
15
|
+
* Instead `read` returns a reference card - what the resource is, its captured ids, the URL that
|
|
16
16
|
* opens it, and the server to call for anything deeper. When a vendor earns a real projection, it
|
|
17
17
|
* attaches as a per-vendor `read` beside this one; the shared card stays the floor.
|
|
18
18
|
*
|
|
19
19
|
* ## Why there is no `requiresAuth`
|
|
20
20
|
*
|
|
21
21
|
* Linear's module declares one because its `read` calls MCP and genuinely needs a credential.
|
|
22
|
-
* This module's `read` is a pure projection of the URI it was handed
|
|
22
|
+
* This module's `read` is a pure projection of the URI it was handed - no network, no credential.
|
|
23
23
|
* Declaring `requiresAuth` anyway would not be a harmless formality: an auth-gated module whose
|
|
24
24
|
* binding is unsatisfied has its public-web `urlPattern` claims suppressed and its `matches()`
|
|
25
25
|
* wrapped to decline `http(s)` (herd-agent's `uri-catalog-projection.ts`: `suppressPublicUrlClaims`,
|
|
26
26
|
* and `authSuppressedCatalogModule` for discovery). A pasted Supabase link would therefore stay
|
|
27
|
-
* unbranded for every user who has not yet connected Supabase
|
|
27
|
+
* unbranded for every user who has not yet connected Supabase - which is exactly the user the
|
|
28
28
|
* branded pill is for. The vendor's MCP tools remain gated on their own, by the MCP host.
|
|
29
29
|
*/
|
|
30
30
|
export declare function createVendoredMcpUriModule(descriptor: VendoredMcpDescriptor): UriExtensionModule;
|
|
31
31
|
|
|
32
|
+
declare interface FactPattern {
|
|
33
|
+
protocol?: string;
|
|
34
|
+
hostname?: string;
|
|
35
|
+
pathname?: string;
|
|
36
|
+
search?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
32
39
|
declare type JsonPrimitive = string | number | boolean | null;
|
|
33
40
|
|
|
34
41
|
declare type JsonSchema = Record<string, unknown>;
|
|
@@ -47,12 +54,107 @@ declare interface LineSelector {
|
|
|
47
54
|
readonly raw: boolean;
|
|
48
55
|
}
|
|
49
56
|
|
|
57
|
+
/**
|
|
58
|
+
* A source-native read of one URI, shaped for downstream indexing rather than
|
|
59
|
+
* direct model consumption. A module's read returns it in
|
|
60
|
+
* `RawResource.observations`, built from the same fetch as the content, once
|
|
61
|
+
* per document it wants indexed; absence means "not indexed".
|
|
62
|
+
*
|
|
63
|
+
* Gone signal: the index retires a doc when a read throws `UriNotFoundError`
|
|
64
|
+
* or an error whose `.status === 404`. A module whose vendor signals "gone"
|
|
65
|
+
* differently (HTTP 410, a 200-body `{ok:false}`/`archived:true`, a
|
|
66
|
+
* 403/404-ambiguous lost-access response) must translate that into one of
|
|
67
|
+
* those two shapes itself; losing access to a resource counts as gone too.
|
|
68
|
+
* A read that cannot build a complete observation (a secondary fetch failed)
|
|
69
|
+
* returns none rather than a partial one.
|
|
70
|
+
*
|
|
71
|
+
* Account-qualified identity: a module whose read can resolve against more
|
|
72
|
+
* than one connected account (the account selector is stripped before route
|
|
73
|
+
* parsing, so two accounts reading the same opaque provider id would
|
|
74
|
+
* otherwise collide on one doc key) must fold `ctx.auth.credential.accountId`
|
|
75
|
+
* into `uri` - e.g. `gmail://@<accountId>/threads/<threadId>` - never the
|
|
76
|
+
* user-renamable connection/selector label. `ctx.auth.credential` is the
|
|
77
|
+
* reliable source of the resolved account at a `requiresAuth` module's
|
|
78
|
+
* `read()`: it is always populated once auth resolution runs (an
|
|
79
|
+
* `authContext`-style check already throws first when no credential
|
|
80
|
+
* resolved). `ctx.connection` may ALSO be populated by dispatch - a
|
|
81
|
+
* connection-required module receives it whenever the host has a tracked
|
|
82
|
+
* connection for the account - so do not assume it is absent; a module that
|
|
83
|
+
* wants the human-facing label rather than the account id reads
|
|
84
|
+
* `ctx.connection?.displayName`.
|
|
85
|
+
*
|
|
86
|
+
* `accountId` is guaranteed stable only for the life of the stored credential
|
|
87
|
+
* record, not necessarily across a disconnect/reconnect of the same
|
|
88
|
+
* real-world provider account. A scheme that mints an opaque id at connect
|
|
89
|
+
* time (the default for an api-key or delegated scheme, absent a
|
|
90
|
+
* provider-derived override) gets a fresh id on every connect; a scheme that
|
|
91
|
+
* instead derives the id from provider data (an oauth2-pkce scheme supplying
|
|
92
|
+
* `resolveAccountId`, e.g. reading an OIDC `sub`) keeps the same id across
|
|
93
|
+
* reconnect. A module on a scheme without a provider-stable id has two honest
|
|
94
|
+
* choices: derive its own stable identity from provider data at read time
|
|
95
|
+
* (call the provider's own account/"who am I" endpoint with the resolved
|
|
96
|
+
* credential and fold THAT into `uri` instead of `accountId`), or
|
|
97
|
+
* account-qualify with `accountId` knowing a disconnect/reconnect of the same
|
|
98
|
+
* real-world account re-keys its documents under a new id rather than
|
|
99
|
+
* updating them in place - nothing on the host side reconciles the old and
|
|
100
|
+
* new keys.
|
|
101
|
+
*/
|
|
102
|
+
declare interface ObservationMaterial {
|
|
103
|
+
/** Canonical URI of the observed resource - may differ from the input URI. */
|
|
104
|
+
readonly uri: string;
|
|
105
|
+
/** Scheme-prefixed content type, e.g. `"github.pr"`, `"gmail.thread"`, `"wikipedia.article"`. */
|
|
106
|
+
readonly kind: string;
|
|
107
|
+
readonly title?: string;
|
|
108
|
+
/** Source-native seams: one element per message/comment/section, in source order. */
|
|
109
|
+
readonly text?: readonly string[];
|
|
110
|
+
/** ISO-8601 creation time; provenance only - not persisted by the store yet. */
|
|
111
|
+
readonly createdAt?: string;
|
|
112
|
+
/** ISO-8601 last-update time; provenance only - not persisted by the store yet. */
|
|
113
|
+
readonly updatedAt?: string;
|
|
114
|
+
/** Source-native revision/version marker, when the source exposes one. */
|
|
115
|
+
readonly version?: string;
|
|
116
|
+
/**
|
|
117
|
+
* How long this resource stays worth semantically searching, measured from
|
|
118
|
+
* the LAST time it was observed - not from when it was first indexed. Every
|
|
119
|
+
* observation of an unchanged resource pushes the deadline out again, so a
|
|
120
|
+
* thread that keeps getting read keeps living and a quiet one ages out.
|
|
121
|
+
*
|
|
122
|
+
* Retention is opt-in per resource: absent means the index keeps the
|
|
123
|
+
* resource until its source says it is gone. A route declares this only
|
|
124
|
+
* when staleness is real for that shape - a chat thread or an inbox
|
|
125
|
+
* conversation goes cold, a durable note the user wrote does not.
|
|
126
|
+
*/
|
|
127
|
+
readonly retainForMs?: number;
|
|
128
|
+
}
|
|
129
|
+
|
|
50
130
|
declare interface RawResource {
|
|
51
131
|
readonly uri: string;
|
|
52
132
|
readonly content: string | Uint8Array;
|
|
53
133
|
readonly mimeType: string;
|
|
54
134
|
readonly metadata?: RawResourceMetadata;
|
|
55
135
|
readonly selector?: SelectorDisposition;
|
|
136
|
+
/**
|
|
137
|
+
* The indexable forms of this resource, built from the same fetch as
|
|
138
|
+
* `content`: one per document the read wants indexed (a thread read offers
|
|
139
|
+
* one per message). Absent or empty means nothing is indexed. The read tool
|
|
140
|
+
* takes them off before the cache and the model; other host reads
|
|
141
|
+
* (out-of-band host reads) return them untouched.
|
|
142
|
+
*/
|
|
143
|
+
readonly observations?: readonly ObservationMaterial[];
|
|
144
|
+
/** How long the host may cache this result; see {@link UriCachePolicy.ttlMs}. */
|
|
145
|
+
readonly cachePolicy?: Pick<UriCachePolicy, "ttlMs">;
|
|
146
|
+
/**
|
|
147
|
+
* A short name for the resource this call touched, for the transcript row; absent shows the
|
|
148
|
+
* address. Render-only: the host stamps it on the tool result's `details`, never in `content`.
|
|
149
|
+
*/
|
|
150
|
+
readonly label?: UriResourceLabel;
|
|
151
|
+
/**
|
|
152
|
+
* Answer to a `read` called with `ctx.knownRevision`: the module checked the source's current
|
|
153
|
+
* revision and it equals `knownRevision`, so `content` is empty and `metadata.revision` equals
|
|
154
|
+
* `knownRevision`. Set it only when that check was made and matched; a module that cannot
|
|
155
|
+
* check cheaply, or that found a different revision, returns the full resource without it.
|
|
156
|
+
*/
|
|
157
|
+
readonly unchanged?: true;
|
|
56
158
|
}
|
|
57
159
|
|
|
58
160
|
declare interface RawResourceCacheControl {
|
|
@@ -96,7 +198,7 @@ declare interface RawResourceMetadata {
|
|
|
96
198
|
readonly resourceIdentity?: RawResourceIdentity;
|
|
97
199
|
/**
|
|
98
200
|
* The resource's stable public address when `uri` reports something more
|
|
99
|
-
* specific than the address a consumer names it by
|
|
201
|
+
* specific than the address a consumer names it by - a retained revision
|
|
100
202
|
* (`skill://<id>/@revision/<version>`) served for a `skill://<source>/<name>`
|
|
101
203
|
* read. Present only when the two differ. Consumers that attribute by name
|
|
102
204
|
* (the read tool's `skillName` detail, and everything keyed off it) read
|
|
@@ -105,6 +207,24 @@ declare interface RawResourceMetadata {
|
|
|
105
207
|
readonly canonicalUri?: string;
|
|
106
208
|
}
|
|
107
209
|
|
|
210
|
+
/**
|
|
211
|
+
* The credential the host resolved for one call to plugin code that declares `requiresAuth`: a URI
|
|
212
|
+
* verb (`ctx.auth.credential`), a tool (`ctx.credential`) or a search provider (`ctx.credential`).
|
|
213
|
+
* Plain data, so it crosses a process boundary with the call; plugin code never asks for one.
|
|
214
|
+
*/
|
|
215
|
+
declare interface ResolvedCredential {
|
|
216
|
+
/** Bearer for OAuth schemes, apiKey for api-key schemes. Host-resolved and refreshed. */
|
|
217
|
+
readonly accessToken: string;
|
|
218
|
+
readonly accountId: string;
|
|
219
|
+
readonly schemeId: string;
|
|
220
|
+
readonly scopes?: readonly string[];
|
|
221
|
+
/**
|
|
222
|
+
* Every value of a multi-field api-key credential, keyed by the scheme's declared field id
|
|
223
|
+
* (`accessToken` mirrors the primary field). Absent for single-secret schemes.
|
|
224
|
+
*/
|
|
225
|
+
readonly fields?: Readonly<Record<string, string>>;
|
|
226
|
+
}
|
|
227
|
+
|
|
108
228
|
/** One all-of arm in an ordered scope requirement. */
|
|
109
229
|
declare interface ScopeAlternative {
|
|
110
230
|
readonly allOf: readonly ScopeNeed[];
|
|
@@ -144,32 +264,43 @@ declare interface UriAgentHint {
|
|
|
144
264
|
readonly triggers?: UriHintTriggers;
|
|
145
265
|
/**
|
|
146
266
|
* Skill invocation names (flat `localId`s, e.g. `"gmail-email-triage"`) that hold this module's
|
|
147
|
-
* deeper workflow judgment
|
|
267
|
+
* deeper workflow judgment - the name a `read skill://<name>` dispatch resolves, not a display
|
|
148
268
|
* title or a path. Point here only at skills that actually exist in the composed skill roster;
|
|
149
269
|
* a dangling name sends the agent to a `skill://` read for nothing.
|
|
150
270
|
*/
|
|
151
271
|
readonly skills?: readonly string[];
|
|
152
272
|
}
|
|
153
273
|
|
|
154
|
-
declare type UriAuthActionClassification = {
|
|
155
|
-
readonly kind: "action";
|
|
156
|
-
readonly actionId: string;
|
|
157
|
-
} | {
|
|
158
|
-
readonly kind: "public";
|
|
159
|
-
};
|
|
160
|
-
|
|
161
274
|
/**
|
|
162
|
-
* Finite authorization actions plus the
|
|
163
|
-
*
|
|
275
|
+
* Finite authorization actions plus the rules that select one before dispatch. A call no rule
|
|
276
|
+
* matches, or a rule naming an action that is not in `actions`, fails closed in the host.
|
|
164
277
|
*/
|
|
165
278
|
declare interface UriAuthActionPolicy {
|
|
166
279
|
readonly actions: Readonly<Record<string, ScopeRequirement>>;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
readonly uri: string;
|
|
170
|
-
}): UriAuthActionClassification | undefined;
|
|
280
|
+
/** Absent matches no call, so every call fails closed. */
|
|
281
|
+
readonly rules?: readonly UriAuthActionRule[];
|
|
171
282
|
}
|
|
172
283
|
|
|
284
|
+
/**
|
|
285
|
+
* One row of a module's sign-in action rules: which calls need which action. A row matches a call
|
|
286
|
+
* when every condition it names holds; a condition it leaves out matches anything. The first
|
|
287
|
+
* matching row decides, so a row with no conditions at the end means "everything else".
|
|
288
|
+
*/
|
|
289
|
+
declare type UriAuthActionRule = {
|
|
290
|
+
/** The verbs this row covers. */
|
|
291
|
+
readonly operations?: readonly UriOperation[];
|
|
292
|
+
/** The claim `route` ids this row covers, matched against the call's address. */
|
|
293
|
+
readonly routes?: readonly string[];
|
|
294
|
+
/** Query parameters the address must carry with exactly these values (`{ permanent: "true" }`). */
|
|
295
|
+
readonly query?: Readonly<Record<string, string>>;
|
|
296
|
+
} & ({
|
|
297
|
+
/** The {@link UriAuthActionPolicy.actions} entry the call needs. */
|
|
298
|
+
readonly action: string;
|
|
299
|
+
} | {
|
|
300
|
+
/** The call needs no credential. */
|
|
301
|
+
readonly public: true;
|
|
302
|
+
});
|
|
303
|
+
|
|
173
304
|
declare interface UriAuthRef {
|
|
174
305
|
readonly serviceId: string;
|
|
175
306
|
readonly schemeId: string;
|
|
@@ -191,7 +322,7 @@ declare interface UriAuthRequirement {
|
|
|
191
322
|
*/
|
|
192
323
|
readonly requiredScopes?: readonly string[];
|
|
193
324
|
/**
|
|
194
|
-
* The service id connect guidance should NAME when this module is gated
|
|
325
|
+
* The service id connect guidance should NAME when this module is gated - a host-composed
|
|
195
326
|
* front door whose connect grants exactly this module's scopes (e.g. `gmail` expanding onto
|
|
196
327
|
* the shared `google.account` credential). Guidance only; resolution keys on
|
|
197
328
|
* `(serviceId, schemeId)`. Absent, guidance names `serviceId`.
|
|
@@ -237,6 +368,21 @@ declare type UriCachePolicyResolver = (operation: UriOperation, cacheUri: string
|
|
|
237
368
|
|
|
238
369
|
declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
|
|
239
370
|
|
|
371
|
+
/**
|
|
372
|
+
* A URL with `:name` placeholders for the claim's captures. Each capture is escaped for where it
|
|
373
|
+
* lands: lowercased in the host, one path segment (a `:name*` capture keeps its `/`), or a query
|
|
374
|
+
* or fragment value. `{transform(...)}` runs one named, built-in transform over the text inside
|
|
375
|
+
* it, captures pasted in unescaped, and escapes the output for where it lands:
|
|
376
|
+
*
|
|
377
|
+
* - `base64`: unpadded base64 of the UTF-8 text (`{base64(:id :calendar)}`).
|
|
378
|
+
* - `slackTimestamp`: a Slack archive message token as the API's timestamp
|
|
379
|
+
* (`p1783350000000100` becomes `1783350000.000100`).
|
|
380
|
+
*
|
|
381
|
+
* A transform that cannot read its input fills nothing. A claim whose `normalizeTo` fills nothing
|
|
382
|
+
* does not match; a `sourceUrl` that fills nothing paints no link.
|
|
383
|
+
*/
|
|
384
|
+
declare type UriClaimTemplate = string;
|
|
385
|
+
|
|
240
386
|
declare interface UriCommonFlow {
|
|
241
387
|
readonly label: string;
|
|
242
388
|
readonly when?: string;
|
|
@@ -286,41 +432,28 @@ declare interface UriExample {
|
|
|
286
432
|
readonly operation?: UriOperation;
|
|
287
433
|
}
|
|
288
434
|
|
|
289
|
-
|
|
435
|
+
/**
|
|
436
|
+
* A plugin's URI module. Its claims route, spell and describe its addresses, so it has no
|
|
437
|
+
* `matches`, `normalize` or `describe`. It also has no `fallback` (a plugin's addresses are always
|
|
438
|
+
* claimed) and no `locate` (a plugin has no file on disk for the daemon to open).
|
|
439
|
+
*/
|
|
440
|
+
declare interface UriExtensionModule extends Omit<UriModule, "verbs" | "normalize" | "matches" | "describe" | "fallback" | "locate"> {
|
|
290
441
|
readonly verbs: UriVerbSupport;
|
|
291
442
|
/** Human-facing per-verb effect docs; see {@link UriVerbDocs}. */
|
|
292
443
|
readonly verbDocs?: UriVerbDocs;
|
|
293
444
|
/**
|
|
294
445
|
* Plugin-declared default permission per verb group. A verb group set to `"ask"`
|
|
295
|
-
* compiles into a defaults-level ask rule
|
|
446
|
+
* compiles into a defaults-level ask rule - the user is prompted by default but can
|
|
296
447
|
* override with an explicit allow. Undeclared = `"allow"` (fail-open).
|
|
297
448
|
* See {@link UriPermissionDefaults}.
|
|
298
449
|
*/
|
|
299
450
|
readonly permissionDefaults?: UriPermissionDefaults;
|
|
300
451
|
/** Requires a resolved URI connection before any verb handler runs. */
|
|
301
452
|
readonly requiresConnection?: boolean;
|
|
302
|
-
/** Pure route-aware permission facts; see {@link UriExtensionOperationPermissionPolicy}. */
|
|
303
|
-
readonly permission?: UriExtensionOperationPermissionPolicy;
|
|
304
453
|
/** False rejects generic write-tool `source` copies before source fetch. */
|
|
305
454
|
readonly acceptsSourceCopy?: boolean;
|
|
306
455
|
}
|
|
307
456
|
|
|
308
|
-
declare interface UriExtensionOperationPermissionPolicy {
|
|
309
|
-
/**
|
|
310
|
-
* Classify one canonical route, purely. `write`/`edit`/`delete` may only be made stricter
|
|
311
|
-
* than the verb default; `help`/`read`/`list`/`search` must stay `"read"` (a `ruleKey` is
|
|
312
|
-
* allowed), because the kernel reruns a crash-interrupted read without asking again. Any
|
|
313
|
-
* other answer, or a throw, fails the call closed.
|
|
314
|
-
*/
|
|
315
|
-
classifyOperation(request: {
|
|
316
|
-
readonly operation: UriOperation;
|
|
317
|
-
readonly uri: string;
|
|
318
|
-
}): {
|
|
319
|
-
readonly kind: "read" | "mutate" | "destructive" | "execute";
|
|
320
|
-
readonly ruleKey?: string;
|
|
321
|
-
} | undefined;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
457
|
declare interface UriExternalCliRunner {
|
|
325
458
|
readonly run: (request: UriExternalCliRunRequest) => Promise<UriExternalCliRunResult>;
|
|
326
459
|
}
|
|
@@ -355,6 +488,8 @@ declare interface UriHelp {
|
|
|
355
488
|
* than text the module's author wrote. Absent: the module's own text.
|
|
356
489
|
*/
|
|
357
490
|
readonly thirdPartyContent?: true;
|
|
491
|
+
/** The module's own markdown for this result, shown instead of the host's default rendering. */
|
|
492
|
+
readonly markdown?: string;
|
|
358
493
|
}
|
|
359
494
|
|
|
360
495
|
declare interface UriHintTriggers {
|
|
@@ -394,6 +529,12 @@ declare interface UriListResult {
|
|
|
394
529
|
readonly items: readonly UriListItem[];
|
|
395
530
|
readonly nextCursor?: string;
|
|
396
531
|
readonly metadata?: UriListMetadata;
|
|
532
|
+
/** How long the host may cache this result; see {@link UriCachePolicy.ttlMs}. */
|
|
533
|
+
readonly cachePolicy?: Pick<UriCachePolicy, "ttlMs">;
|
|
534
|
+
/** The module's own markdown for this result, shown instead of the host's default rendering. */
|
|
535
|
+
readonly markdown?: string;
|
|
536
|
+
/** The touched resource's name for the transcript row, as on `RawResource.label`. */
|
|
537
|
+
readonly label?: UriResourceLabel;
|
|
397
538
|
}
|
|
398
539
|
|
|
399
540
|
declare type UriLocateContext = Pick<UriResolveContext, "cwd" | "signal" | "connection" | "sessionId" | "paths"> & {
|
|
@@ -411,31 +552,13 @@ declare type UriLocateResult = {
|
|
|
411
552
|
readonly kind: "not-disk-backed";
|
|
412
553
|
};
|
|
413
554
|
|
|
414
|
-
declare type UriMarkdownRenderInput = {
|
|
415
|
-
readonly operation: "help";
|
|
416
|
-
readonly uri: string;
|
|
417
|
-
readonly result: UriHelp;
|
|
418
|
-
} | {
|
|
419
|
-
readonly operation: "list";
|
|
420
|
-
readonly uri: string;
|
|
421
|
-
readonly result: UriListResult;
|
|
422
|
-
} | {
|
|
423
|
-
readonly operation: "search";
|
|
424
|
-
readonly uri: string;
|
|
425
|
-
readonly result: UriSearchResult;
|
|
426
|
-
} | {
|
|
427
|
-
readonly operation: Extract<UriOperation, "write" | "edit" | "delete">;
|
|
428
|
-
readonly uri: string;
|
|
429
|
-
readonly result: UriMutationResult;
|
|
430
|
-
};
|
|
431
|
-
|
|
432
555
|
declare interface UriModule {
|
|
433
556
|
readonly id: string;
|
|
434
557
|
/**
|
|
435
558
|
* Explicit human-readable name for catalog/display purposes (the plugin
|
|
436
559
|
* manifest's `contributes.uriModules[].displayName`, threaded through by
|
|
437
|
-
* hand since there is no automatic manifest
|
|
438
|
-
* step). Falls back to a mechanical id-derived title when absent
|
|
560
|
+
* hand since there is no automatic manifest->runtime-module composition
|
|
561
|
+
* step). Falls back to a mechanical id-derived title when absent - see
|
|
439
562
|
* `uriCatalogTitle`.
|
|
440
563
|
*/
|
|
441
564
|
readonly title?: string;
|
|
@@ -455,14 +578,26 @@ declare interface UriModule {
|
|
|
455
578
|
* calls `parseLineSelector` itself and reports what it did through `RawResource.selector`.
|
|
456
579
|
*/
|
|
457
580
|
readonly ownsLineSelectors?: boolean;
|
|
581
|
+
/** Opt in to host-resolved supplementary sources; absent means unsupported. */
|
|
582
|
+
readonly acceptsWriteSources?: boolean;
|
|
583
|
+
/**
|
|
584
|
+
* Opt in to raw bytes as `write`'s content; absent means text and JSON only. The `write`
|
|
585
|
+
* tool's `source` copy leg is the only producer: a provider's binary resource (an attachment,
|
|
586
|
+
* an image, a PDF) reaches a module that declares this as a `Uint8Array`, never decoded into
|
|
587
|
+
* the model's context, and a binary copy to any other module is refused before it runs.
|
|
588
|
+
*/
|
|
589
|
+
readonly acceptsBytes?: boolean;
|
|
458
590
|
readonly claims?: readonly UriClaim[];
|
|
591
|
+
/**
|
|
592
|
+
* The routes the module's scheme-root `help` lists, as data, so a host can list them without
|
|
593
|
+
* calling `help`.
|
|
594
|
+
*/
|
|
595
|
+
readonly templates?: readonly UriTemplate[];
|
|
459
596
|
/** Migration-only prompt summary until structured help/catalog coverage replaces prose. */
|
|
460
597
|
readonly description?: string;
|
|
461
598
|
readonly agentHint?: UriAgentHint;
|
|
462
599
|
readonly requiresAuth?: UriAuthRequirement;
|
|
463
600
|
readonly authActions?: UriAuthActionPolicy;
|
|
464
|
-
/** Pure route/payload validation applied before a consequential permission ask. */
|
|
465
|
-
readonly preflight?: UriOperationPreflightPolicy;
|
|
466
601
|
/**
|
|
467
602
|
* Structured facts for approval surfaces, or `undefined` when unavailable.
|
|
468
603
|
* A one-line description must name the whole consequence; `preview` instead
|
|
@@ -472,120 +607,46 @@ declare interface UriModule {
|
|
|
472
607
|
* of covered payload fields and query parameters. Unknown fields cost the summary.
|
|
473
608
|
* The host owns framing, the whole-quote fit (no elision) and display-safety admission.
|
|
474
609
|
*
|
|
475
|
-
*
|
|
610
|
+
* This hook is async and may do I/O. Resolve names through `ctx`,
|
|
476
611
|
* the same dispatch context used by execution, never an ambient or cached account. A name
|
|
477
612
|
* the module resolved under that account may be cached for a bounded time, keyed by that
|
|
478
613
|
* account's identity and never answered to another account or after a failed lookup.
|
|
479
|
-
* The host calls it once before raising the ask
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
readonly operation: UriOperation;
|
|
485
|
-
readonly uri: string;
|
|
486
|
-
readonly payload: unknown;
|
|
487
|
-
}, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
|
|
488
|
-
/**
|
|
489
|
-
* Rebuild a call from the person's "Allow with edits" answer: the same payload
|
|
490
|
-
* {@link describeOperation} was given, with the values the person typed into the preview's
|
|
491
|
-
* `editable` fields put in their place. Implement it beside any preview that marks a field
|
|
492
|
-
* `editable`; without it the host drops every editable marker from that module's previews, so
|
|
493
|
-
* a field is never offered for editing that cannot be honoured.
|
|
494
|
-
*
|
|
495
|
-
* Pure and fast: it must not send, write or otherwise act, and it should not do I/O (it gets
|
|
496
|
-
* the dispatch context `ctx` only so a name can be resolved the way `describeOperation` does).
|
|
497
|
-
* Return the COMPLETE amended payload in the shape the module's own handler reads. Validate it
|
|
498
|
-
* with the handler's own schema, so an amended call is exactly as valid as one the model made.
|
|
499
|
-
* Decline by returning `undefined` or throwing; either denies the call with nothing done.
|
|
614
|
+
* The host calls it once before raising the ask and waits for the answer, with no deadline;
|
|
615
|
+
* `ctx.signal` fires when the host stops waiting (the session closes, or a caller gives up),
|
|
616
|
+
* and a late answer is discarded. A throw yields no
|
|
617
|
+
* summary and a module-attributed diagnostic; declining costs a click into the app, never an
|
|
618
|
+
* under-described approval.
|
|
500
619
|
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
* The host then holds the amended call to what the person was shown, in two steps, and runs it
|
|
509
|
-
* only if both pass. It classifies the amended call again and requires the same tool, rule key,
|
|
510
|
-
* kind, resources, scheme and target address, so an edit cannot reach a different route. It then
|
|
511
|
-
* calls {@link describeOperation} on the amended call and requires that preview to read exactly
|
|
512
|
-
* as the one the person saw, apart from the values of the fields they edited: the same title, the
|
|
513
|
-
* same fields in the same order, each with the same label, key, `editable` marker and
|
|
620
|
+
* "Allow with edits": a field marked `editable` may be rewritten by the person on the card.
|
|
621
|
+
* The host rebuilds the call itself (see the field's `editable`), then holds the rebuilt call to
|
|
622
|
+
* what the person was shown, in two steps, and runs it only if both pass. It classifies the
|
|
623
|
+
* rebuilt call again and requires the same tool, rule key, kind, resources, scheme and target
|
|
624
|
+
* address. It then calls this hook on the rebuilt call and requires that preview to read exactly
|
|
625
|
+
* as the one the person saw, apart from the values of the fields they edited: the same title,
|
|
626
|
+
* the same fields in the same order, each with the same label, key, `editable` marker and
|
|
514
627
|
* `maxLength`, and every read-only field with the same value. Anything else refuses the call
|
|
515
|
-
* with nothing done: a mismatch, and also
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
* So rebuild from the original payload and change only the fields you offered. A recipient, a
|
|
519
|
-
* thread or an attachment list that an amendment changed is caught by the second step, but only
|
|
520
|
-
* where the preview shows it: put whatever says where a call goes, or what it does beyond its
|
|
628
|
+
* with nothing done: a mismatch, and also an answer of `undefined` or a throw. The `description`
|
|
629
|
+
* line is not compared. So put whatever says where a call goes, or what it does beyond its
|
|
521
630
|
* editable fields, in the preview's `title` or a field, never only in its `description`, and
|
|
522
631
|
* keep recipients, destinations and thread bindings out of `editable` fields.
|
|
523
632
|
*/
|
|
524
|
-
|
|
633
|
+
describeOperation?(request: {
|
|
525
634
|
readonly operation: UriOperation;
|
|
526
635
|
readonly uri: string;
|
|
527
636
|
readonly payload: unknown;
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* A short, render-only name for the resource a settled call on `request.uri` touched, which the
|
|
532
|
-
* host stamps on the tool result's `details` so a transcript row can name it where it would
|
|
533
|
-
* otherwise print the address (`#lane-analytics` and `thread`, not a channel id). Answer
|
|
534
|
-
* `undefined` for any address you cannot honestly name.
|
|
535
|
-
*
|
|
536
|
-
* Called once per successful URI verb call, AFTER the verb handler has returned, with the same
|
|
537
|
-
* dispatch context. Resolve names through `ctx` and nothing else, and prefer a cache your own
|
|
538
|
-
* verb handlers warm, keyed by the executing account: a name one account saw is never answered
|
|
539
|
-
* to another, and a failed, blank or aborted lookup is never cached. The host bounds the wait
|
|
540
|
-
* (a finished result is held at most a quarter of a second), gives `ctx.signal` a hard deadline,
|
|
541
|
-
* and drops a late, thrown or refused answer without failing the call; a throw is reported as a
|
|
542
|
-
* module-attributed diagnostic. The label is a label, never an identity: the address remains the
|
|
543
|
-
* click target, hover text and accessible name. It is UI-only, so it never enters the tool
|
|
544
|
-
* result's content and no telemetry reads it.
|
|
545
|
-
*
|
|
546
|
-
* Unlike `describeOperation` this is not an approval surface: it carries no consequence, no
|
|
547
|
-
* quote and no coverage claim, and nothing may gate a permission on it.
|
|
548
|
-
*/
|
|
549
|
-
labelResource?(request: UriResourceLabelRequest, ctx: UriResolveContext): Promise<UriResourceLabel | undefined>;
|
|
637
|
+
}, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
|
|
638
|
+
readonly getCachePolicy?: UriCachePolicyResolver;
|
|
550
639
|
/**
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
* Route-parse only — cheap, side-effect-free, no I/O, no auth (the same
|
|
554
|
-
* discipline as `matches`); a throw is treated as `false`. Returning true
|
|
555
|
-
* is the resource's contract that its observation read returns an
|
|
556
|
-
* observation render and that failures under that format throw typed,
|
|
557
|
-
* status-bearing errors rather than resolving a friendly fallback page.
|
|
558
|
-
* The kernel stamps the answer onto the resource's access events, which is
|
|
559
|
-
* what ambient index consumers replay on — so "PRs are observable" is
|
|
560
|
-
* declared here, route by route, never module-wide. Absent means no read
|
|
561
|
-
* of this module is observable. A vendor's own gone-vocabulary (HTTP 410,
|
|
562
|
-
* a 200-body "ok:false"/"archived:true"/"status:cancelled", or a
|
|
563
|
-
* 403/404-ambiguous lost-access response) is this module's job to
|
|
564
|
-
* translate into `UriNotFoundError` or a `status: 404` error under the
|
|
565
|
-
* observation format — the fold that retires a doc never learns vendor
|
|
566
|
-
* vocabulary (see `ObservationMaterial`'s doc comment).
|
|
640
|
+
* Code matching, for the host's own modules whose addresses no claim can describe (a bare file
|
|
641
|
+
* path). A plugin module has none; it routes through its `claims` alone.
|
|
567
642
|
*/
|
|
568
|
-
|
|
643
|
+
matches?(input: string, ctx: UriResolveContext): boolean;
|
|
644
|
+
/** The official spelling, for the host's own modules; a plugin's comes from its claims' `normalizeTo`. */
|
|
645
|
+
normalize?(input: string, ctx: UriResolveContext): UriNormalizeResult | undefined;
|
|
569
646
|
/**
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
* cheaply. The host calls it before a repeat `read` of an address the
|
|
573
|
-
* session already holds, with `ctx.expectedRevision` set to the revision
|
|
574
|
-
* that read reported (`RawResourceMetadata.revision`); a value equal to it
|
|
575
|
-
* means "unchanged" and the fetch is skipped, anything else falls through
|
|
576
|
-
* to the ordinary read. A module whose read revision embeds more than the
|
|
577
|
-
* head can know (a content digest beside a stat stamp) may answer relative
|
|
578
|
-
* to `expectedRevision` — return it when the cheap part matches, `undefined`
|
|
579
|
-
* when it does not — but must never return a value it has not verified.
|
|
580
|
-
* `undefined` is always safe: it costs one fetch, never a wrong answer.
|
|
581
|
-
* Must be cheaper than the read (a metadata request, a `stat`); a throw is
|
|
582
|
-
* treated as `undefined`.
|
|
647
|
+
* The pill's title and link, for the host's own modules only; a plugin module has none, and its
|
|
648
|
+
* pill comes from its claims' `title` and `sourceUrl`.
|
|
583
649
|
*/
|
|
584
|
-
revision?(uri: string, ctx: UriResolveContext): Promise<string | undefined>;
|
|
585
|
-
readonly getCachePolicy?: UriCachePolicyResolver;
|
|
586
|
-
/** Retained matching escape hatch; future dispatch should prefer compiled claims. */
|
|
587
|
-
matches(input: string, ctx: UriResolveContext): boolean;
|
|
588
|
-
normalize?(input: string, ctx: UriResolveContext): UriNormalizeResult | undefined;
|
|
589
650
|
describe?(input: string, ctx: UriDescribeContext): UriResourceDescription | undefined;
|
|
590
651
|
locate?(input: string, ctx: UriLocateContext): Promise<UriLocateResult>;
|
|
591
652
|
/**
|
|
@@ -598,33 +659,21 @@ declare interface UriModule {
|
|
|
598
659
|
read(input: string, ctx: UriResolveContext): Promise<RawResource>;
|
|
599
660
|
/** Observes only; see {@link read}. */
|
|
600
661
|
help?(input: string, ctx: UriResolveContext): Promise<UriHelp>;
|
|
601
|
-
write?(input: string, content: UriPayload, ctx: UriResolveContext): Promise<UriMutationResult | void>;
|
|
602
|
-
/** Opt-in structured write with one or more host-resolved resources delivered beside the content. */
|
|
603
|
-
writeWithSources?(input: string, content: UriPayload, sources: readonly UriWriteSource[], ctx: UriResolveContext): Promise<UriMutationResult | void>;
|
|
604
662
|
/**
|
|
605
|
-
*
|
|
606
|
-
* `
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
* context. A module that omits it is text-only, and a binary copy targeting
|
|
612
|
-
* it is refused with an error naming a byte-capable destination.
|
|
613
|
-
*
|
|
614
|
-
* `source` describes what the bytes are: a filesystem-backed sink can ignore
|
|
615
|
-
* it (the target path already carries the name), while a remote provider
|
|
616
|
-
* sink needs it to name and type the stored file. It sits before `ctx` so a
|
|
617
|
-
* forwarding wrapper that fails to thread it is a compile error, not a
|
|
618
|
-
* silent drop.
|
|
663
|
+
* `sources` is empty for ordinary writes; populated only with `acceptsWriteSources: true`.
|
|
664
|
+
* `content` is a `Uint8Array` only with `acceptsBytes: true`, and then `ctx.writeSource`
|
|
665
|
+
* names and types it. It is `undefined` when the call carried neither `content` nor `source`.
|
|
666
|
+
* The module decides what that means: a route that takes no body (a folder
|
|
667
|
+
* create) proceeds, and a route that needs one refuses with an error naming
|
|
668
|
+
* what is missing. Never treat it as empty content.
|
|
619
669
|
*/
|
|
620
|
-
|
|
670
|
+
write?(input: string, content: UriPayload | Uint8Array | undefined, sources: readonly UriWriteSource[], ctx: UriResolveContext): Promise<UriMutationResult | void>;
|
|
621
671
|
edit?(input: string, patch: UriPayload, ctx: UriResolveContext): Promise<UriMutationResult>;
|
|
622
672
|
/** Observes only; see {@link read}. */
|
|
623
673
|
list?(input: string, params: UriListParams, ctx: UriResolveContext): Promise<UriListResult>;
|
|
624
674
|
/** Observes only; see {@link read}. */
|
|
625
675
|
search?(input: string, params: UriSearchParams, ctx: UriResolveContext): Promise<UriSearchResult>;
|
|
626
676
|
delete?(input: string, ctx: UriResolveContext): Promise<UriMutationResult>;
|
|
627
|
-
toMarkdown?(input: UriMarkdownRenderInput, ctx: UriResolveContext): string | undefined;
|
|
628
677
|
}
|
|
629
678
|
|
|
630
679
|
/** Authoritative lifecycle facts for a successful record-like URI mutation. */
|
|
@@ -650,6 +699,12 @@ declare interface UriMutationResult {
|
|
|
650
699
|
readonly receipt?: UriMutationReceipt;
|
|
651
700
|
/** Opaque source-native revision after this successful mutation. */
|
|
652
701
|
readonly revision?: string;
|
|
702
|
+
/** Cached reads this mutation made stale; see {@link UriCachePolicy.invalidate}. */
|
|
703
|
+
readonly cachePolicy?: Pick<UriCachePolicy, "invalidate">;
|
|
704
|
+
/** The module's own markdown for this result, shown instead of the host's default rendering. */
|
|
705
|
+
readonly markdown?: string;
|
|
706
|
+
/** The touched resource's name for the transcript row, as on `RawResource.label`. */
|
|
707
|
+
readonly label?: UriResourceLabel;
|
|
653
708
|
}
|
|
654
709
|
|
|
655
710
|
declare interface UriNodeCapability {
|
|
@@ -670,11 +725,6 @@ declare interface UriNormalizeResult {
|
|
|
670
725
|
|
|
671
726
|
declare type UriOperation = "help" | "read" | "write" | "edit" | "list" | "search" | "delete";
|
|
672
727
|
|
|
673
|
-
/** The call {@link UriModule.amendOperation} rebuilt: the whole payload, in the shape the module reads. */
|
|
674
|
-
declare interface UriOperationAmendment {
|
|
675
|
-
readonly payload: unknown;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
728
|
declare interface UriOperationDescription {
|
|
679
729
|
/** Static verb phrase authored by the module. Never interpolated from input. */
|
|
680
730
|
readonly action: string;
|
|
@@ -697,9 +747,11 @@ declare interface UriOperationDescription {
|
|
|
697
747
|
*/
|
|
698
748
|
readonly key?: string;
|
|
699
749
|
/**
|
|
700
|
-
* `true` offers this field to the person for editing on the approval card.
|
|
701
|
-
*
|
|
702
|
-
*
|
|
750
|
+
* `true` offers this field to the person for editing on the approval card. The host applies
|
|
751
|
+
* an edit itself: it copies the payload and replaces the value of the top-level string
|
|
752
|
+
* property named `key`. So offer a field only when the payload is an object, `key` is one
|
|
753
|
+
* of its string properties, and the module would send any value within `maxLength` as it
|
|
754
|
+
* sends the model's; the host drops the offer otherwise. Absent means read-only.
|
|
703
755
|
*/
|
|
704
756
|
readonly editable?: true;
|
|
705
757
|
/** Longest edited value, in UTF-16 code units. Meaningful only with `editable`. */
|
|
@@ -717,56 +769,6 @@ declare interface UriOperationDescription {
|
|
|
717
769
|
};
|
|
718
770
|
}
|
|
719
771
|
|
|
720
|
-
/**
|
|
721
|
-
* Pure, route-aware validation that runs before permission policy can surface an ask.
|
|
722
|
-
*
|
|
723
|
-
* This is deliberately narrower than execution: it receives only the canonical URI,
|
|
724
|
-
* operation, and operation payload, performs no I/O, and returns a user-actionable
|
|
725
|
-
* rejection for calls that the module already knows cannot succeed. The handler must
|
|
726
|
-
* still validate again when it executes because approval is not an authority boundary.
|
|
727
|
-
*/
|
|
728
|
-
declare interface UriOperationPreflightPolicy {
|
|
729
|
-
/**
|
|
730
|
-
* The rejection half. Optional since kay#7684: a module whose only preflight
|
|
731
|
-
* fact is affirmative (`acceptsPayloadlessWrite`) must not have to stub a
|
|
732
|
-
* validator that never rejects.
|
|
733
|
-
*/
|
|
734
|
-
validateOperation?(request: {
|
|
735
|
-
readonly operation: UriOperation;
|
|
736
|
-
readonly uri: string;
|
|
737
|
-
readonly payload: unknown;
|
|
738
|
-
}): string | undefined;
|
|
739
|
-
/**
|
|
740
|
-
* Route-level affirmative: may a `write` to this URI carry NO payload at all
|
|
741
|
-
* — neither `content` nor `source`? (The canonical case is folder creation,
|
|
742
|
-
* e.g. `?type=folder`.) The write tool's generic shape rule requires exactly
|
|
743
|
-
* one payload form; a route answers `true` here when a payloadless write is
|
|
744
|
-
* meaningful FOR THAT ROUTE, and the rule then admits the call.
|
|
745
|
-
*
|
|
746
|
-
* This exists because an empty body is not always sendable: on some
|
|
747
|
-
* model/provider paths a top-level empty-string argument (`content: ""`)
|
|
748
|
-
* never reaches the host — the key arrives absent, indistinguishable from an
|
|
749
|
-
* omitted argument (kay#7684). A contract that can only be invoked with an
|
|
750
|
-
* empty string is unreachable on those paths, so a route whose write is
|
|
751
|
-
* meaningful with no body must declare it and let the caller omit the
|
|
752
|
-
* payload instead.
|
|
753
|
-
*
|
|
754
|
-
* Pure and side-effect-free like {@link validateOperation}: route-parse
|
|
755
|
-
* only, no I/O. A throw NEVER admits the write, but the two consult paths
|
|
756
|
-
* disagree on purpose about what happens next: pre-ask (permission
|
|
757
|
-
* resolution, which must never crash the gate) answers no and records a
|
|
758
|
-
* module-attributed diagnostic; at execute time the write tool asks only
|
|
759
|
-
* when the call genuinely carries no payload, and a throw there is the
|
|
760
|
-
* module's own bug surfacing as the call's error — louder than a misleading
|
|
761
|
-
* \"provide exactly one of content or source\" the model could never
|
|
762
|
-
* satisfy. Absent means no route of this module accepts a payloadless
|
|
763
|
-
* write.
|
|
764
|
-
*/
|
|
765
|
-
acceptsPayloadlessWrite?(request: {
|
|
766
|
-
readonly uri: string;
|
|
767
|
-
}): boolean;
|
|
768
|
-
}
|
|
769
|
-
|
|
770
772
|
declare interface UriParameter {
|
|
771
773
|
readonly name: string;
|
|
772
774
|
readonly in: "uri" | "query" | "selector";
|
|
@@ -776,29 +778,60 @@ declare interface UriParameter {
|
|
|
776
778
|
readonly examples?: readonly unknown[];
|
|
777
779
|
}
|
|
778
780
|
|
|
781
|
+
/**
|
|
782
|
+
* A claim on a module's own custom-scheme addresses. The pattern matches with or without an
|
|
783
|
+
* account prefix: `gcal://@work/events/x` is matched as `gcal://events/x`, and the prefix is put
|
|
784
|
+
* back on the official spelling, so one claim covers both spellings.
|
|
785
|
+
*/
|
|
779
786
|
declare interface UriPatternClaim {
|
|
780
787
|
readonly kind: "uriPattern";
|
|
781
788
|
readonly pattern: UriPatternInit;
|
|
782
789
|
/**
|
|
783
|
-
* Canonical spelling rebuilt from the captures. When the template
|
|
784
|
-
* input's scheme (the module's own addressing), the input's query string is
|
|
790
|
+
* Canonical spelling rebuilt from the captures (see {@link UriClaimTemplate}). When the template
|
|
791
|
+
* keeps the input's scheme (the module's own addressing), the input's query string is
|
|
785
792
|
* carried over verbatim so a route flag such as `?permanent=true` survives
|
|
786
793
|
* canonicalization (kay#7859); a template that re-targets to another scheme
|
|
787
794
|
* (a projection to a web link) drops it, as does a pattern that consumed the
|
|
788
795
|
* query itself or a template that spells its own.
|
|
789
796
|
*/
|
|
790
|
-
readonly normalizeTo?:
|
|
797
|
+
readonly normalizeTo?: UriClaimTemplate;
|
|
798
|
+
/**
|
|
799
|
+
* Names the route this claim matches, so data keyed by route (a module's sign-in action rules)
|
|
800
|
+
* can say which addresses it means. Several claims may name the same route.
|
|
801
|
+
*/
|
|
802
|
+
readonly route?: string;
|
|
803
|
+
/**
|
|
804
|
+
* The web page a matched address opens, filled from the captures (see
|
|
805
|
+
* {@link UriClaimTemplate}). The host matches an address's official spelling and paints its
|
|
806
|
+
* reference with the source URL of the first matching claim that declares one.
|
|
807
|
+
*/
|
|
808
|
+
readonly sourceUrl?: UriClaimTemplate;
|
|
809
|
+
/**
|
|
810
|
+
* The name a matched address's reference shows: literal text, with each `:name` replaced by
|
|
811
|
+
* that capture as decoded (`"Flow :flow"`, or a fixed `"BFS"`). The first matching claim that
|
|
812
|
+
* declares one names the address.
|
|
813
|
+
*/
|
|
814
|
+
readonly title?: string;
|
|
791
815
|
readonly examples?: readonly string[];
|
|
792
816
|
}
|
|
793
817
|
|
|
794
818
|
declare interface UriPatternInit {
|
|
795
819
|
readonly protocol?: string;
|
|
820
|
+
/**
|
|
821
|
+
* Dot-delimited host pattern. A pattern that is one capture (`:owner`) takes the whole host,
|
|
822
|
+
* dots included, as a `github://some.org/repo` owner must.
|
|
823
|
+
*/
|
|
796
824
|
readonly hostname?: string;
|
|
797
825
|
/**
|
|
798
826
|
* Slash-delimited path pattern. A final capture may use `:name*` to consume
|
|
799
|
-
* the remaining path segments, preserving `/` in the captured value.
|
|
827
|
+
* the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
|
|
828
|
+
* ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
|
|
829
|
+
* `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
|
|
830
|
+
* host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
|
|
831
|
+
* no host (`bfs:///`).
|
|
800
832
|
*/
|
|
801
833
|
readonly pathname?: string;
|
|
834
|
+
/** `&`-delimited query pattern; `""` matches only an address with no query. */
|
|
802
835
|
readonly search?: string;
|
|
803
836
|
}
|
|
804
837
|
|
|
@@ -817,7 +850,7 @@ declare interface UriPayloadContract {
|
|
|
817
850
|
|
|
818
851
|
/**
|
|
819
852
|
* The three-state permission vocabulary a plugin declares for its default permissions.
|
|
820
|
-
* Maps to `PermissionRule.effect`: `allow`
|
|
853
|
+
* Maps to `PermissionRule.effect`: `allow` -> allow, `ask` -> ask, `never` -> deny.
|
|
821
854
|
*/
|
|
822
855
|
declare type UriPermissionDefault = "allow" | "ask" | "never";
|
|
823
856
|
|
|
@@ -835,19 +868,6 @@ declare interface UriPermissionDefaults {
|
|
|
835
868
|
readonly delete?: UriPermissionDefault;
|
|
836
869
|
}
|
|
837
870
|
|
|
838
|
-
/**
|
|
839
|
-
* One change a person made to an `editable` field of a call's action preview ("Allow with
|
|
840
|
-
* edits"): the field's `key` and the value they want it to hold. Values are message content, so
|
|
841
|
-
* a module must not log or persist them.
|
|
842
|
-
*/
|
|
843
|
-
declare interface UriPreviewEdit {
|
|
844
|
-
readonly key: string;
|
|
845
|
-
readonly value: string;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
/** The read shape a caller may request via {@link UriResolveContext.format}. */
|
|
849
|
-
declare type UriReadFormat = "observation";
|
|
850
|
-
|
|
851
871
|
declare interface UriResolveContext {
|
|
852
872
|
readonly cwd: string;
|
|
853
873
|
readonly signal?: AbortSignal;
|
|
@@ -856,8 +876,8 @@ declare interface UriResolveContext {
|
|
|
856
876
|
readonly auth?: UriResolvedAuth;
|
|
857
877
|
/**
|
|
858
878
|
* Id of the session dispatching this call, stamped by the host at the dispatch site.
|
|
859
|
-
* It never originates from anything the caller can influence
|
|
860
|
-
* body
|
|
879
|
+
* It never originates from anything the caller can influence - no verb argument, no write
|
|
880
|
+
* body - so a module may treat it as trustworthy caller identity and stamp it onto writes.
|
|
861
881
|
*
|
|
862
882
|
* Absent when no session owns the dispatch: registry matching and permission pre-checks
|
|
863
883
|
* resolve a URI outside any verb call.
|
|
@@ -865,14 +885,14 @@ declare interface UriResolveContext {
|
|
|
865
885
|
readonly sessionId?: string;
|
|
866
886
|
/**
|
|
867
887
|
* WHO the dispatching session acts as, stamped by the host at the same dispatch site as
|
|
868
|
-
* {@link UriResolveContext.sessionId} and just as un-influenceable by the caller
|
|
888
|
+
* {@link UriResolveContext.sessionId} and just as un-influenceable by the caller - so a module
|
|
869
889
|
* writing to a store it owns can record the actor without the agent being able to choose one.
|
|
870
890
|
*
|
|
871
891
|
* Free text minted by the host's own runtime (Bonsai's form is `user`, `subagent`,
|
|
872
892
|
* `system/<surface>`, `followup/<surface>`) rather than a closed union: the surface half is the
|
|
873
893
|
* host's vocabulary, and a second enumeration of it here would drift from the first.
|
|
874
894
|
*
|
|
875
|
-
* Absent whenever the host has nothing to say
|
|
895
|
+
* Absent whenever the host has nothing to say - no session owns the dispatch, or the session
|
|
876
896
|
* predates the host recording an origin. A module must then omit the actor rather than assume
|
|
877
897
|
* one; an invented actor written into a durable artifact can never be walked back.
|
|
878
898
|
*/
|
|
@@ -888,7 +908,7 @@ declare interface UriResolveContext {
|
|
|
888
908
|
readonly origin: "model" | "host";
|
|
889
909
|
/**
|
|
890
910
|
* The daemon-assigned id of the run driving this invocation, when the host's own execution
|
|
891
|
-
* frame carried one. Absent means the frame carried none
|
|
911
|
+
* frame carried one. Absent means the frame carried none - never a reason to guess one: a
|
|
892
912
|
* module recording this onto a durable artifact must treat absence as unresolved provenance,
|
|
893
913
|
* not as "no run was active".
|
|
894
914
|
*/
|
|
@@ -897,39 +917,33 @@ declare interface UriResolveContext {
|
|
|
897
917
|
readonly toolName?: string;
|
|
898
918
|
};
|
|
899
919
|
/**
|
|
900
|
-
* An OPAQUE, host-captured context for the mutation this dispatch is about to make
|
|
920
|
+
* An OPAQUE, host-captured context for the mutation this dispatch is about to make -
|
|
901
921
|
* the artifact-provenance counterpart of `sessionId`/`actor`, and stamped at the same
|
|
902
922
|
* un-influenceable dispatch site.
|
|
903
923
|
*
|
|
904
924
|
* The host composes it from facts a caller cannot supply: which session is acting, the
|
|
905
925
|
* run driving it, the tool invocation, and whatever the host resolved about how that
|
|
906
|
-
* session came to exist. The kernel treats it as an uninterpreted JSON value
|
|
926
|
+
* session came to exist. The kernel treats it as an uninterpreted JSON value - it never
|
|
907
927
|
* reads a field, only checks that the value is lossless JSON before it crosses the
|
|
908
|
-
* dispatch boundary
|
|
928
|
+
* dispatch boundary - so this layer stays ignorant of any one product's provenance
|
|
909
929
|
* semantics. A module that owns a durable artifact carries it to its store and validates
|
|
910
930
|
* it against its OWN schema at the point it persists, where the target revision is known.
|
|
911
931
|
*
|
|
912
932
|
* Absent means the host captured nothing for this dispatch (a read, a host with no
|
|
913
|
-
* capture resolver, or a capture that failed)
|
|
933
|
+
* capture resolver, or a capture that failed) - never a claim that there was nothing to
|
|
914
934
|
* capture. Present only on mutating dispatches (`write`/`edit`/`delete`); reads never pay
|
|
915
935
|
* for it.
|
|
916
936
|
*/
|
|
917
937
|
readonly captureContext?: Readonly<Record<string, unknown>>;
|
|
918
938
|
/**
|
|
919
|
-
*
|
|
920
|
-
* it means returning an `ObservationMaterial` via `observationResource(...)` instead.
|
|
921
|
-
* Opt-in only — there is no advertisement surface or capability flag.
|
|
922
|
-
*/
|
|
923
|
-
readonly format?: UriReadFormat;
|
|
924
|
-
/**
|
|
925
|
-
* Host-provided writable data root for the OWNING extension of the module handling this call —
|
|
939
|
+
* Host-provided writable data root for the OWNING extension of the module handling this call -
|
|
926
940
|
* structurally identical to the per-extension `paths` a tool/handler context already receives, so
|
|
927
941
|
* a module authored against both surfaces reads `ctx.paths?.dataDir` uniformly. Lets a URI module
|
|
928
942
|
* own durable local state (a JSON store, a small file tree) instead of the host constructing and
|
|
929
943
|
* injecting it. Host-populated after dispatch selects a module and keyed to that module's owner;
|
|
930
944
|
* always absent during matching, and absent for modules with no owning extension (builtins) or a
|
|
931
945
|
* host that wires no per-module data dir. Unlike a tool context, the host only NAMES this path for
|
|
932
|
-
* a URI module and does NOT pre-create the directory
|
|
946
|
+
* a URI module and does NOT pre-create the directory - create it on first write and tolerate its
|
|
933
947
|
* absence on read.
|
|
934
948
|
*/
|
|
935
949
|
readonly paths?: {
|
|
@@ -944,6 +958,15 @@ declare interface UriResolveContext {
|
|
|
944
958
|
* proceeds as before.
|
|
945
959
|
*/
|
|
946
960
|
readonly expectedRevision?: string;
|
|
961
|
+
/**
|
|
962
|
+
* The revision this session already holds for the address a `read` is about to fetch: the
|
|
963
|
+
* `RawResourceMetadata.revision` its last read reported. Set only on a repeat `read`, never
|
|
964
|
+
* on a mutation (`expectedRevision` is the mutation witness). A module with a cheap
|
|
965
|
+
* current-revision check (a metadata request, a `stat`) may compare first and, when it has
|
|
966
|
+
* verified the two are equal, answer {@link RawResource.unchanged} with no body. A module
|
|
967
|
+
* with no such check ignores it and reads in full, which is always correct.
|
|
968
|
+
*/
|
|
969
|
+
readonly knownRevision?: string;
|
|
947
970
|
/** Host marks a mediated session that enforces its private revision witness ledger. */
|
|
948
971
|
readonly requiresRevisionWitness?: boolean;
|
|
949
972
|
/** Host-derived descriptor for a top-level copied resource; absent for inline writes. */
|
|
@@ -953,26 +976,13 @@ declare interface UriResolveContext {
|
|
|
953
976
|
declare interface UriResolvedAuth {
|
|
954
977
|
readonly connection?: UriConnection;
|
|
955
978
|
/** Present only for verb handlers of a module declaring `requiresAuth`; absent during matching. */
|
|
956
|
-
readonly credential?:
|
|
979
|
+
readonly credential?: ResolvedCredential;
|
|
957
980
|
/** Present for handlers gated by a non-injectable external-CLI readiness scheme. */
|
|
958
981
|
readonly externalCli?: UriExternalCliRunner;
|
|
959
982
|
/** Opaque host metadata; not a credential channel. */
|
|
960
983
|
readonly metadata?: Record<string, unknown>;
|
|
961
984
|
}
|
|
962
985
|
|
|
963
|
-
declare interface UriResolvedCredential {
|
|
964
|
-
/** Bearer for OAuth schemes, apiKey for api-key schemes. Host-resolved and refreshed. */
|
|
965
|
-
readonly accessToken: string;
|
|
966
|
-
readonly accountId: string;
|
|
967
|
-
readonly schemeId: string;
|
|
968
|
-
readonly scopes?: readonly string[];
|
|
969
|
-
/**
|
|
970
|
-
* Every value of a multi-field api-key credential, keyed by the scheme's declared field id
|
|
971
|
-
* (`accessToken` mirrors the primary field). Absent for single-secret schemes.
|
|
972
|
-
*/
|
|
973
|
-
readonly fields?: Readonly<Record<string, string>>;
|
|
974
|
-
}
|
|
975
|
-
|
|
976
986
|
declare interface UriResourceDescription {
|
|
977
987
|
readonly uri: string;
|
|
978
988
|
/** Absent when the caller should retain its existing label. */
|
|
@@ -992,13 +1002,6 @@ declare interface UriResourceLabel {
|
|
|
992
1002
|
readonly section?: string;
|
|
993
1003
|
}
|
|
994
1004
|
|
|
995
|
-
/** The call a module is asked to label. */
|
|
996
|
-
declare interface UriResourceLabelRequest {
|
|
997
|
-
readonly operation: UriOperation;
|
|
998
|
-
/** The dispatch address: selector-stripped, the exact form the module's verb handler received. */
|
|
999
|
-
readonly uri: string;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
1005
|
declare interface UriSchemeClaim {
|
|
1003
1006
|
readonly kind: "scheme";
|
|
1004
1007
|
readonly scheme: string;
|
|
@@ -1032,15 +1035,21 @@ declare interface UriSearchResult {
|
|
|
1032
1035
|
* so the caller knows the matches may be partial.
|
|
1033
1036
|
*/
|
|
1034
1037
|
readonly metadata?: UriListMetadata;
|
|
1038
|
+
/** How long the host may cache this result; see {@link UriCachePolicy.ttlMs}. */
|
|
1039
|
+
readonly cachePolicy?: Pick<UriCachePolicy, "ttlMs">;
|
|
1040
|
+
/** The module's own markdown for this result, shown instead of the host's default rendering. */
|
|
1041
|
+
readonly markdown?: string;
|
|
1042
|
+
/** The touched resource's name for the transcript row, as on `RawResource.label`. */
|
|
1043
|
+
readonly label?: UriResourceLabel;
|
|
1035
1044
|
}
|
|
1036
1045
|
|
|
1037
1046
|
/**
|
|
1038
1047
|
* What a copied resource IS, minus its bytes: the identity half of a mediated
|
|
1039
1048
|
* source. The host derives it once (filename inferred from the source address,
|
|
1040
1049
|
* `mimeType` carried from the source module's own `RawResource.mimeType`) and
|
|
1041
|
-
* delivers it
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1050
|
+
* delivers it inside each `UriWriteSource`, and on `ctx.writeSource` for a
|
|
1051
|
+
* `source` copy - so a remote sink can name and type what it stores without
|
|
1052
|
+
* re-deriving either from raw bytes.
|
|
1044
1053
|
*/
|
|
1045
1054
|
declare interface UriSourceDescriptor {
|
|
1046
1055
|
readonly uri: string;
|
|
@@ -1055,11 +1064,11 @@ declare interface UriTemplate {
|
|
|
1055
1064
|
/**
|
|
1056
1065
|
* Per-operation effect docs for this route, keyed by operation. A route
|
|
1057
1066
|
* whose shared {@link description} spans several verbs ("Read, edit, or
|
|
1058
|
-
* trash a thread") is ambiguous for any surface that groups by verb
|
|
1067
|
+
* trash a thread") is ambiguous for any surface that groups by verb - a
|
|
1059
1068
|
* permission view must not describe `read` with a sentence that mentions
|
|
1060
1069
|
* trashing. Each entry says what THAT operation concretely does at THIS
|
|
1061
1070
|
* route; operations without an entry fall back to the shared description.
|
|
1062
|
-
* Additive and optional
|
|
1071
|
+
* Additive and optional - existing templates are unaffected.
|
|
1063
1072
|
*/
|
|
1064
1073
|
readonly operationDocs?: Partial<Record<UriOperation, string>>;
|
|
1065
1074
|
/**
|
|
@@ -1099,13 +1108,13 @@ declare interface UriValidationMessage {
|
|
|
1099
1108
|
|
|
1100
1109
|
/**
|
|
1101
1110
|
* Author-declared, human-facing documentation of what each supported verb
|
|
1102
|
-
* CONCRETELY does against the provider
|
|
1111
|
+
* CONCRETELY does against the provider - the capability half of a module's
|
|
1103
1112
|
* boolean verb-support declaration. Written for a permission/capability
|
|
1104
1113
|
* surface ("what am I allowing?"), not for the model: one plain sentence per
|
|
1105
1114
|
* verb naming the real-world effect ("Sends mail, creates/updates drafts,
|
|
1106
1115
|
* applies label changes"), never wire mechanics or URI shapes. Verbs the
|
|
1107
1116
|
* module does not support are omitted; at runtime a supported verb with no
|
|
1108
|
-
* entry simply renders undocumented (fail-open metadata)
|
|
1117
|
+
* entry simply renders undocumented (fail-open metadata) - but for a plugin's
|
|
1109
1118
|
* `kay.agent` URI modules, `auditPluginDisclosure` (`@bonsai/plugin-sdk/
|
|
1110
1119
|
* disclosure`) enforces coverage of every supported verb at authoring/load
|
|
1111
1120
|
* time.
|
|
@@ -1113,7 +1122,7 @@ declare interface UriValidationMessage {
|
|
|
1113
1122
|
* Lives here in the protocol layer (beside {@link UriTemplate.operationDocs},
|
|
1114
1123
|
* its per-route sibling) so both `@herd/uri-extensions`' `UriExtensionModule`
|
|
1115
1124
|
* and herd-agent's kernel `UriModule` can carry it without inverting the
|
|
1116
|
-
* `@herd/uri`
|
|
1125
|
+
* `@herd/uri` <- `@herd/uri-extensions` dependency.
|
|
1117
1126
|
*/
|
|
1118
1127
|
declare interface UriVerbDocs {
|
|
1119
1128
|
/** What a `read` of this address space returns (also covers `help`). */
|
|
@@ -1136,6 +1145,7 @@ declare interface UriVerbSupport {
|
|
|
1136
1145
|
readonly editable: boolean;
|
|
1137
1146
|
readonly deletable?: boolean;
|
|
1138
1147
|
readonly listable: boolean;
|
|
1148
|
+
readonly searchable?: boolean;
|
|
1139
1149
|
}
|
|
1140
1150
|
|
|
1141
1151
|
/** A mediated resource supplied beside structured write content without entering model context. */
|
|
@@ -1143,10 +1153,12 @@ declare interface UriWriteSource extends UriSourceDescriptor {
|
|
|
1143
1153
|
readonly content: string | Uint8Array;
|
|
1144
1154
|
}
|
|
1145
1155
|
|
|
1156
|
+
/** A claim on a public web link (`http` or `https`), usually folded onto the module's own scheme. */
|
|
1146
1157
|
declare interface UrlPatternClaim {
|
|
1147
1158
|
readonly kind: "urlPattern";
|
|
1148
1159
|
readonly pattern: UriPatternInit;
|
|
1149
|
-
readonly normalizeTo?:
|
|
1160
|
+
readonly normalizeTo?: UriClaimTemplate;
|
|
1161
|
+
readonly route?: string;
|
|
1150
1162
|
readonly examples?: readonly string[];
|
|
1151
1163
|
}
|
|
1152
1164
|
|
|
@@ -1157,7 +1169,7 @@ export declare type VendoredMcpClaim = NonNullable<UriExtensionModule["claims"]>
|
|
|
1157
1169
|
* Everything a vendored-MCP plugin's URI module is, expressed as data.
|
|
1158
1170
|
*
|
|
1159
1171
|
* The plugin package supplies one of these and gets back a conformant {@link UriExtensionModule};
|
|
1160
|
-
* it writes no read projection, no help document, and no route parsing. That is deliberate
|
|
1172
|
+
* it writes no read projection, no help document, and no route parsing. That is deliberate - this
|
|
1161
1173
|
* kit exists because five pilot plugins were about to become five copies of one 460-line module,
|
|
1162
1174
|
* and ~40 more are queued behind them.
|
|
1163
1175
|
*/
|
|
@@ -1193,11 +1205,89 @@ export declare interface VendoredMcpDescriptor {
|
|
|
1193
1205
|
readonly skills: readonly string[];
|
|
1194
1206
|
}
|
|
1195
1207
|
|
|
1208
|
+
/** The claim shapes a vendored plugin declares, with plain mutable arrays so a manifest can spread them. */
|
|
1209
|
+
declare type VendoredMcpFactClaim = {
|
|
1210
|
+
kind: "scheme";
|
|
1211
|
+
scheme: string;
|
|
1212
|
+
} | {
|
|
1213
|
+
kind: "uriPattern";
|
|
1214
|
+
pattern: FactPattern;
|
|
1215
|
+
normalizeTo: string;
|
|
1216
|
+
route: string;
|
|
1217
|
+
sourceUrl: string;
|
|
1218
|
+
} | {
|
|
1219
|
+
kind: "urlPattern";
|
|
1220
|
+
pattern: FactPattern;
|
|
1221
|
+
normalizeTo?: string;
|
|
1222
|
+
route?: string;
|
|
1223
|
+
examples?: string[];
|
|
1224
|
+
};
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* ---
|
|
1228
|
+
* responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
|
|
1229
|
+
* own vendored MCP server, so every read-through plugin and the daemon that implements the port
|
|
1230
|
+
* agree on the same shape by construction.
|
|
1231
|
+
* owns:
|
|
1232
|
+
* - {@link VendoredMcpPort} - what a plugin's URI module and tools call.
|
|
1233
|
+
* - {@link VendoredMcpOutcome} - the typed result a plugin decodes, including every failure it
|
|
1234
|
+
* must surface to the agent rather than swallow.
|
|
1235
|
+
* does_not_own:
|
|
1236
|
+
* - The implementation. A plugin never dials MCP itself: it takes the port from
|
|
1237
|
+
* `api.vendoredMcp.port(server)` (`@bonsai/plugin-sdk/kay-agent`), which the daemon binds to the
|
|
1238
|
+
* plugin's own hosted server over its MCP host. Plugin source stays host-free, and a plugin
|
|
1239
|
+
* under test substitutes a fake port.
|
|
1240
|
+
* - Which tool names exist. `TTool` is the plugin's own union of the vendor tools it calls; the
|
|
1241
|
+
* port is generic so a typo in a tool name fails typecheck inside the plugin.
|
|
1242
|
+
* ---
|
|
1243
|
+
*/
|
|
1244
|
+
/**
|
|
1245
|
+
* Why a call failed, as the plugin must tell the agent. `needs-auth` carries the exact service to
|
|
1246
|
+
* reconnect (`serviceId`) so a plugin can name it in its error instead of returning an empty
|
|
1247
|
+
* result; today's plugins name their statically declared `requiresAuth` service instead, which is
|
|
1248
|
+
* the same service for a single-service plugin. `unknown-server` and `unknown-tool` are wiring
|
|
1249
|
+
* faults (a server Bonsai does not host for this plugin, or a tool name the server does not have)
|
|
1250
|
+
* and stay loud for the same reason: an unreachable host must never decode as "no data".
|
|
1251
|
+
*/
|
|
1252
|
+
declare type VendoredMcpFailureReason = "needs-auth" | "unknown-server" | "unknown-tool" | "failed";
|
|
1253
|
+
|
|
1254
|
+
export declare type VendoredMcpOutcome =
|
|
1255
|
+
/**
|
|
1256
|
+
* `value` is the tool's `structuredContent` when it sent one, else its text content parsed as
|
|
1257
|
+
* JSON, else that text as a string: a vendor tool that answers in prose (a transcript, a
|
|
1258
|
+
* markdown summary) is a result, not a failure. A route that needs a record rejects a string
|
|
1259
|
+
* itself, with its own message.
|
|
1260
|
+
*/
|
|
1261
|
+
{
|
|
1262
|
+
readonly ok: true;
|
|
1263
|
+
readonly value: unknown;
|
|
1264
|
+
} | {
|
|
1265
|
+
readonly ok: false;
|
|
1266
|
+
readonly reason: VendoredMcpFailureReason;
|
|
1267
|
+
readonly message: string;
|
|
1268
|
+
/** Exact reconnect target supplied by the MCP host for an auth failure. */
|
|
1269
|
+
readonly serviceId?: string;
|
|
1270
|
+
};
|
|
1271
|
+
|
|
1272
|
+
/**
|
|
1273
|
+
* One vendored MCP server, as the plugin that declares it calls it. `invoke` calls any tool the
|
|
1274
|
+
* server has, whether it reads or writes. The port checks no permission of its own: a call is as
|
|
1275
|
+
* permitted as the plugin tool or URI verb that makes it.
|
|
1276
|
+
*/
|
|
1277
|
+
export declare interface VendoredMcpPort<TTool extends string = string> {
|
|
1278
|
+
invoke(input: {
|
|
1279
|
+
/** The session's working directory; the host resolves the server binding per cwd. */
|
|
1280
|
+
readonly cwd: string;
|
|
1281
|
+
readonly tool: TTool;
|
|
1282
|
+
readonly args: Readonly<Record<string, unknown>>;
|
|
1283
|
+
}): Promise<VendoredMcpOutcome>;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1196
1286
|
/**
|
|
1197
1287
|
* One addressable resource shape, as the PAIR that makes the whole pattern work: the canonical
|
|
1198
|
-
* `<ns
|
|
1288
|
+
* `<ns>://...` URI Bonsai stores, and the public web URL that URI came from and opens back to.
|
|
1199
1289
|
*
|
|
1200
|
-
* Both templates use the same `:name` capture syntax and MUST name exactly the same captures
|
|
1290
|
+
* Both templates use the same `:name` capture syntax and MUST name exactly the same captures -
|
|
1201
1291
|
* {@link createVendoredMcpUriModule} throws otherwise. That symmetry is the point: a canonical
|
|
1202
1292
|
* URI carrying an id the web URL drops is a pill that cannot be opened, and a web URL naming a
|
|
1203
1293
|
* capture the canonical URI never captured renders a literal `:pageId` into the user's browser.
|
|
@@ -1214,4 +1304,43 @@ export declare interface VendoredMcpRoute {
|
|
|
1214
1304
|
readonly example: string;
|
|
1215
1305
|
}
|
|
1216
1306
|
|
|
1307
|
+
/** What a vendored-MCP plugin's manifest declares for its URI module. */
|
|
1308
|
+
export declare interface VendoredMcpUriModuleFacts {
|
|
1309
|
+
description: string;
|
|
1310
|
+
agentHint: {
|
|
1311
|
+
summary: string;
|
|
1312
|
+
commonFlows: {
|
|
1313
|
+
label: string;
|
|
1314
|
+
example: string;
|
|
1315
|
+
}[];
|
|
1316
|
+
triggers: {
|
|
1317
|
+
keywords: string[];
|
|
1318
|
+
};
|
|
1319
|
+
helpUri: string;
|
|
1320
|
+
skills: string[];
|
|
1321
|
+
};
|
|
1322
|
+
verbs: {
|
|
1323
|
+
readable: true;
|
|
1324
|
+
writable: false;
|
|
1325
|
+
editable: false;
|
|
1326
|
+
listable: false;
|
|
1327
|
+
};
|
|
1328
|
+
verbDocs: {
|
|
1329
|
+
read: string;
|
|
1330
|
+
};
|
|
1331
|
+
templates: {
|
|
1332
|
+
uri: string;
|
|
1333
|
+
description: string;
|
|
1334
|
+
operations: ["read"];
|
|
1335
|
+
}[];
|
|
1336
|
+
claims: VendoredMcpFactClaim[];
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/**
|
|
1340
|
+
* The facts for one descriptor. Each route becomes a `uriPattern` claim whose `normalizeTo` is the
|
|
1341
|
+
* route's canonical URI and whose `sourceUrl` is the route's web URL, so a pasted or stored address
|
|
1342
|
+
* resolves to its canonical spelling and a pill that opens the vendor's page.
|
|
1343
|
+
*/
|
|
1344
|
+
export declare function vendoredMcpUriModuleFacts(descriptor: VendoredMcpDescriptor): VendoredMcpUriModuleFacts;
|
|
1345
|
+
|
|
1217
1346
|
export { }
|