@vornrun/connector-sdk 0.7.0-beta.7 → 0.7.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.
- package/README.md +285 -2
- package/dist/check-62s2GvcO.d.ts +1137 -0
- package/dist/chunk-ZKHXHE3O.js +3511 -0
- package/dist/cli.d.ts +14 -1
- package/dist/cli.js +105 -12
- package/dist/index.d.ts +176 -412
- package/dist/index.js +98 -34
- package/package.json +4 -2
- package/dist/chunk-457KOZUU.js +0 -773
package/dist/index.d.ts
CHANGED
|
@@ -1,272 +1,11 @@
|
|
|
1
|
+
import { E as ExtensionPermission, b as ExtensionHostMethod, c as ConnectorDefinition, d as Connector, e as ExtensionDefinition, f as ConnectorConfig, g as ExtensionHost, T as TriggerDefinition, P as PollContext, h as PollOutcome, i as ConnectorItem, N as NormalizedItem, j as PostReceiveOp, A as ActionRequest, B as BundleRequest, a as BundleOutput, C as CheckFinding } from './check-62s2GvcO.js';
|
|
2
|
+
export { k as ActionContext, l as ActionDefinition, m as ActionInputField, n as ActionInputOption, o as ActionInputType, p as ActionOutputField, q as ActivationPredicate, r as AuthRung, s as BrowserSignIn, t as CHECK_OWNERS, u as CheckCode, v as CheckOptions, w as ConformanceRun, x as ConnectionSetup, y as ConnectorAuth, z as ConnectorConfigField, D as ConnectorHarness, F as ConnectorIcon, G as ConnectorKind, H as ConnectorManifest, I as ConnectorVerification, J as DedupeStrategy, K as DefaultWorkflow, L as ExtensionAgent, M as ExtensionContext, O as ExtensionContributions, Q as ExtensionPlatform, R as ExtensionUsage, S as ExtensionUsageWindow, U as FetchContext, V as FooterContribution, W as FooterItem, X as HarnessOptions, Y as LinkContext, Z as LinkHandled, _ as LinkHandlerContribution, $ as MANIFEST_TOOL, a0 as MAX_PACK_BYTES, a1 as MAX_POLL_PAGES, a2 as ManifestContributions, a3 as MockCall, a4 as MockHostAnswers, a5 as MockHostRun, a6 as MockRoute, a7 as MockRouteMissError, a8 as MockRun, a9 as OPTIONS_TOOL, aa as OptionsContext, ab as OptionsLoader, ac as PREFLIGHT_TOOL, ad as PaginationStrategy, ae as PaneContribution, af as PollPage, ag as PreflightResult, ah as ResilientFetchOptions, ai as RetryPolicy, aj as RunActionOptions, ak as RunPollOptions, al as SessionContext, am as StatusSuggestion, an as backoffMs, ao as bundleDependencyFindings, ap as bundledRequireFindings, aq as checkConnector, ar as connectionSetup, as as connectorManifest, at as createConnectorHarness, au as drainPoll, av as esbuildBundle, aw as escapedMockHttp, ax as footerToolName, ay as formatFindings, az as handlerToolName, aA as lifecycleScriptFindings, aB as mockExtensionHost, aC as pollToolName, aD as readNearestPackageJson, aE as resilientFetch, aF as retryAfterMs, aG as runAction, aH as runConformance, aI as runOptions, aJ as runPoll, aK as withMockHttp } from './check-62s2GvcO.js';
|
|
1
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
4
|
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* it is shared as a normal npm package and installed by pointing a Vorn
|
|
8
|
-
* connection at `npx -y <package>`. Nothing about the host app has to change
|
|
9
|
-
* to accept a new connector.
|
|
10
|
-
*/
|
|
11
|
-
/** A raw item as the author's code returns it. Only id and title are required. */
|
|
12
|
-
interface ConnectorItem {
|
|
13
|
-
/** Stable upstream identity. Vorn dedupes on this, so it must not change. */
|
|
14
|
-
externalId: string | number;
|
|
15
|
-
title: string;
|
|
16
|
-
url?: string;
|
|
17
|
-
description?: string;
|
|
18
|
-
/** Raw upstream status (`open`, `Active`, `In Progress`, …). */
|
|
19
|
-
status?: string;
|
|
20
|
-
labels?: string[];
|
|
21
|
-
assignee?: string;
|
|
22
|
-
/**
|
|
23
|
-
* When the item last changed. Vorn advances its poll cursor from this field,
|
|
24
|
-
* so it must be monotonic per item and comparable as an ISO 8601 string.
|
|
25
|
-
* Defaults to poll time when omitted.
|
|
26
|
-
*/
|
|
27
|
-
updatedAt?: string | Date;
|
|
28
|
-
/** Extra fields to expose to workflow templates as `{{trigger.item.<key>}}`. */
|
|
29
|
-
data?: Record<string, unknown>;
|
|
30
|
-
}
|
|
31
|
-
/** A connector item after normalization. This is the exact JSON Vorn sees. */
|
|
32
|
-
interface NormalizedItem extends Record<string, unknown> {
|
|
33
|
-
externalId: string;
|
|
34
|
-
title: string;
|
|
35
|
-
url: string;
|
|
36
|
-
description: string;
|
|
37
|
-
status: string;
|
|
38
|
-
labels: string[];
|
|
39
|
-
updatedAt: string;
|
|
40
|
-
assignee?: string;
|
|
41
|
-
}
|
|
42
|
-
/** Declares a value the connector needs at runtime, read from the environment. */
|
|
43
|
-
interface ConnectorConfigField {
|
|
44
|
-
key: string;
|
|
45
|
-
label: string;
|
|
46
|
-
/** Environment variable the value is read from. Defaults to CONSTANT_CASE(key). */
|
|
47
|
-
env?: string;
|
|
48
|
-
required?: boolean;
|
|
49
|
-
/** Secrets are stored encrypted by Vorn and never printed by the CLI. */
|
|
50
|
-
secret?: boolean;
|
|
51
|
-
description?: string;
|
|
52
|
-
default?: string;
|
|
53
|
-
}
|
|
54
|
-
type ConnectorConfig = Record<string, string | undefined>;
|
|
55
|
-
interface PollContext {
|
|
56
|
-
config: ConnectorConfig;
|
|
57
|
-
/**
|
|
58
|
-
* Lower bound the host asked for, when it was able to supply one. Treat it
|
|
59
|
-
* as a hint: returning older items is safe because Vorn dedupes, but
|
|
60
|
-
* returning fewer than everything after `since` loses events.
|
|
61
|
-
*/
|
|
62
|
-
since?: string;
|
|
63
|
-
/** Opaque cursor previously returned by this trigger, when supplied. */
|
|
64
|
-
cursor?: string;
|
|
65
|
-
/** Upper bound on items to return in one page. */
|
|
66
|
-
limit?: number;
|
|
67
|
-
/** Injectable clock so tests are deterministic. */
|
|
68
|
-
now(): string;
|
|
69
|
-
}
|
|
70
|
-
interface PollOutcome {
|
|
71
|
-
items: ConnectorItem[];
|
|
72
|
-
nextCursor?: string;
|
|
73
|
-
hasMore?: boolean;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* How the SDK decides which fetched items are new.
|
|
77
|
-
*
|
|
78
|
-
* - `timestamp` — for sources that expose a reliable "last changed" field and
|
|
79
|
-
* can filter on it. Handles the boundary case where several items share the
|
|
80
|
-
* newest timestamp, which is the classic source of both duplicates and
|
|
81
|
-
* silently dropped items.
|
|
82
|
-
* - `lastItem` — for feeds that return newest-first with no dependable
|
|
83
|
-
* timestamp. The cursor is the newest id already delivered.
|
|
84
|
-
*/
|
|
85
|
-
type DedupeStrategy = 'timestamp' | 'lastItem';
|
|
86
|
-
/**
|
|
87
|
-
* What a declarative trigger's `fetch` receives. Deliberately smaller than
|
|
88
|
-
* {@link PollContext}: cursor encoding, ordering, windowing and de-duplication
|
|
89
|
-
* are the SDK's job, so the author only has to answer "what is there now?".
|
|
90
|
-
*/
|
|
91
|
-
interface FetchContext {
|
|
92
|
-
config: ConnectorConfig;
|
|
93
|
-
/**
|
|
94
|
-
* With `dedupe: 'timestamp'`, everything changed at or after this instant is
|
|
95
|
-
* worth returning. Absent on the very first poll. Returning a little too
|
|
96
|
-
* much is safe — the SDK drops what was already delivered.
|
|
97
|
-
*/
|
|
98
|
-
since?: string;
|
|
99
|
-
/**
|
|
100
|
-
* With `dedupe: 'lastItem'`, the newest id already delivered. Absent on the
|
|
101
|
-
* very first poll. Return the feed newest-first and the SDK will stop there.
|
|
102
|
-
*/
|
|
103
|
-
lastItemId?: string;
|
|
104
|
-
/** Upper bound on items worth returning in one call. */
|
|
105
|
-
limit?: number;
|
|
106
|
-
/** Injectable clock so tests are deterministic. */
|
|
107
|
-
now(): string;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* What an upstream state should become when an item is imported as a task.
|
|
111
|
-
*
|
|
112
|
-
* A suggestion, not a rule: it seeds the connection form, and the person
|
|
113
|
-
* setting it up can change it. Without any, everything a connector imports
|
|
114
|
-
* lands as `todo` regardless of whether it was closed a year ago.
|
|
115
|
-
*/
|
|
116
|
-
interface StatusSuggestion {
|
|
117
|
-
/** The value the connector reports in `ConnectorItem.status`. */
|
|
118
|
-
upstream: string;
|
|
119
|
-
suggestedLocal: 'todo' | 'in_progress' | 'in_review' | 'done' | 'cancelled';
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* The workflow to create when a connection is made.
|
|
123
|
-
*
|
|
124
|
-
* A connector that fires on a schedule is useless until something polls it, and
|
|
125
|
-
* expecting every person to build that workflow by hand is how a connection
|
|
126
|
-
* ends up configured and silent. Seeded workflows are ordinary, visible and
|
|
127
|
-
* editable — the schedule is a starting point, not a fixed rule.
|
|
128
|
-
*/
|
|
129
|
-
interface DefaultWorkflow {
|
|
130
|
-
name: string;
|
|
131
|
-
defaultCronFromMinutes: number;
|
|
132
|
-
}
|
|
133
|
-
interface TriggerBase {
|
|
134
|
-
/** Event key, e.g. `workItemCreated`. Becomes the `poll_<type>` MCP tool. */
|
|
135
|
-
type: string;
|
|
136
|
-
label: string;
|
|
137
|
-
description?: string;
|
|
138
|
-
/** Seeds the connection's status mapping; the person setting it up owns it. */
|
|
139
|
-
statusMapping?: StatusSuggestion[];
|
|
140
|
-
/** Seeds a polling workflow when a connection is created. */
|
|
141
|
-
defaultWorkflow?: DefaultWorkflow;
|
|
142
|
-
/**
|
|
143
|
-
* Representative items. `vorn-connector check` replays these through the
|
|
144
|
-
* real dedupe pipeline, so a connector can be verified before anyone has
|
|
145
|
-
* credentials for it.
|
|
146
|
-
*/
|
|
147
|
-
sample?: ConnectorItem[];
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* A trigger is either declarative or hand-written, never both — expressed as a
|
|
151
|
-
* union so the invalid combinations are a type error at authoring time rather
|
|
152
|
-
* than a throw when the connector is first loaded.
|
|
153
|
-
*/
|
|
154
|
-
type TriggerDefinition = TriggerBase & ({
|
|
155
|
-
/**
|
|
156
|
-
* Declarative polling: return what the source has and let the SDK
|
|
157
|
-
* handle cursors and de-duplication.
|
|
158
|
-
*/
|
|
159
|
-
dedupe: DedupeStrategy;
|
|
160
|
-
fetch(context: FetchContext): Promise<ConnectorItem[]> | ConnectorItem[];
|
|
161
|
-
poll?: never;
|
|
162
|
-
} | {
|
|
163
|
-
/**
|
|
164
|
-
* Full control over cursors and paging. Use only when the source's
|
|
165
|
-
* paging cannot be expressed as "give me everything since X".
|
|
166
|
-
*/
|
|
167
|
-
poll(context: PollContext): Promise<PollOutcome> | PollOutcome;
|
|
168
|
-
dedupe?: never;
|
|
169
|
-
fetch?: never;
|
|
170
|
-
});
|
|
171
|
-
interface ActionInputField {
|
|
172
|
-
key: string;
|
|
173
|
-
label: string;
|
|
174
|
-
type?: 'string' | 'number' | 'boolean';
|
|
175
|
-
required?: boolean;
|
|
176
|
-
description?: string;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* A field the action is known to return. Declaring these is optional — extra
|
|
180
|
-
* keys always pass through — but declared fields show up in Vorn's variable
|
|
181
|
-
* autocomplete as `{{steps.<action>.<key>}}`.
|
|
182
|
-
*/
|
|
183
|
-
interface ActionOutputField {
|
|
184
|
-
key: string;
|
|
185
|
-
type?: 'string' | 'number' | 'boolean';
|
|
186
|
-
description?: string;
|
|
187
|
-
}
|
|
188
|
-
interface ActionContext {
|
|
189
|
-
config: ConnectorConfig;
|
|
190
|
-
now(): string;
|
|
191
|
-
}
|
|
192
|
-
interface ActionDefinition {
|
|
193
|
-
/** Action key, e.g. `closeWorkItem`. Becomes an MCP tool of the same name. */
|
|
194
|
-
type: string;
|
|
195
|
-
label: string;
|
|
196
|
-
description?: string;
|
|
197
|
-
/**
|
|
198
|
-
* Whether repeating the call with the same arguments is safe. Surfaced in
|
|
199
|
-
* the MCP tool description, because an agent retrying a failed step has no
|
|
200
|
-
* other way to know whether it is about to create a second issue.
|
|
201
|
-
*/
|
|
202
|
-
idempotent?: boolean;
|
|
203
|
-
inputs?: ActionInputField[];
|
|
204
|
-
outputs?: ActionOutputField[];
|
|
205
|
-
run(args: Record<string, unknown>, context: ActionContext): Promise<Record<string, unknown> | void> | Record<string, unknown> | void;
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* A connector's own glyph, so an installed connector is recognizable in a list
|
|
209
|
-
* rather than sharing one generic icon with every other one.
|
|
210
|
-
*
|
|
211
|
-
* Path data only — deliberately not markup. Vorn draws these itself as
|
|
212
|
-
* `<path d="...">` inside an `<svg>` it owns, so a connector cannot inject
|
|
213
|
-
* elements, scripts or external references into the app rendering it.
|
|
214
|
-
*/
|
|
215
|
-
interface ConnectorIcon {
|
|
216
|
-
/** Defaults to `0 0 24 24`. */
|
|
217
|
-
viewBox?: string;
|
|
218
|
-
/** SVG path `d` data, drawn with `fill="currentColor"` so it inherits color. */
|
|
219
|
-
paths: string[];
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* What a connector reports about its own readiness.
|
|
223
|
-
*
|
|
224
|
-
* `message` is shown to the user verbatim, so it should say what to do rather
|
|
225
|
-
* than what went wrong — "run `gh auth login`" beats "not authenticated".
|
|
226
|
-
*/
|
|
227
|
-
interface PreflightResult {
|
|
228
|
-
ok: boolean;
|
|
229
|
-
message?: string;
|
|
230
|
-
}
|
|
231
|
-
interface ConnectorDefinition {
|
|
232
|
-
/** Stable connector id, e.g. `azure-devops`. */
|
|
233
|
-
id: string;
|
|
234
|
-
name: string;
|
|
235
|
-
version?: string;
|
|
236
|
-
description?: string;
|
|
237
|
-
icon?: ConnectorIcon;
|
|
238
|
-
config?: ConnectorConfigField[];
|
|
239
|
-
triggers?: TriggerDefinition[];
|
|
240
|
-
actions?: ActionDefinition[];
|
|
241
|
-
/**
|
|
242
|
-
* Whether this connector could work right now, asked before anyone waits on
|
|
243
|
-
* a poll.
|
|
244
|
-
*
|
|
245
|
-
* A connector whose credentials come from config fields does not need this:
|
|
246
|
-
* a missing field is already a visible, nameable error. One that borrows an
|
|
247
|
-
* external tool's login — `gh auth login`, `az login` — has no field to be
|
|
248
|
-
* missing, so without this the first sign that the tool is absent or signed
|
|
249
|
-
* out is a poll failing some minutes after the connection was saved.
|
|
250
|
-
*
|
|
251
|
-
* Answer `ok: false` with a message saying what to do about it. Throwing is
|
|
252
|
-
* equivalent — the server catches it and reports the same shape with the
|
|
253
|
-
* error's message — so there is one result for a caller to read and no
|
|
254
|
-
* behaviour riding on which you choose. Prefer returning when the state is
|
|
255
|
-
* one you recognise, because then you get to write the sentence.
|
|
256
|
-
*
|
|
257
|
-
* Absent means there is nothing to check, which is not the same answer as a
|
|
258
|
-
* check that passed.
|
|
259
|
-
*/
|
|
260
|
-
preflight?(): Promise<PreflightResult> | PreflightResult;
|
|
261
|
-
}
|
|
262
|
-
/** A validated definition. Every accessor below is guaranteed non-null. */
|
|
263
|
-
interface Connector extends ConnectorDefinition {
|
|
264
|
-
readonly version: string;
|
|
265
|
-
readonly config: ConnectorConfigField[];
|
|
266
|
-
readonly triggers: TriggerDefinition[];
|
|
267
|
-
readonly actions: ActionDefinition[];
|
|
268
|
-
}
|
|
269
|
-
|
|
5
|
+
/** Everything an extension may ask the host for; anything else is not grantable. */
|
|
6
|
+
declare const EXTENSION_PERMISSIONS: ExtensionPermission[];
|
|
7
|
+
/** What each host method costs, read by the bridge that grants it and the check that gates it. */
|
|
8
|
+
declare const HOST_PERMISSIONS: Record<ExtensionHostMethod, ExtensionPermission>;
|
|
270
9
|
/** Environment variable a config field reads from, e.g. `apiToken` → `API_TOKEN`. */
|
|
271
10
|
declare function envNameFor(key: string, explicit?: string): string;
|
|
272
11
|
/**
|
|
@@ -277,6 +16,15 @@ declare function envNameFor(key: string, explicit?: string): string;
|
|
|
277
16
|
* MCP tool once the connector is already installed in someone's app.
|
|
278
17
|
*/
|
|
279
18
|
declare function defineConnector(definition: ConnectorDefinition): Connector;
|
|
19
|
+
/**
|
|
20
|
+
* Validate an extension and fill in its defaults.
|
|
21
|
+
*
|
|
22
|
+
* An extension is a pack like a connector, so it goes through the same
|
|
23
|
+
* manifest, pack, check and catalog; what differs is that it contributes to a
|
|
24
|
+
* session card rather than polling a service. Failing here — at import time —
|
|
25
|
+
* keeps a mistyped permission or an unreachable page from reaching a card.
|
|
26
|
+
*/
|
|
27
|
+
declare function defineExtension(definition: ExtensionDefinition): Connector;
|
|
280
28
|
/**
|
|
281
29
|
* Read the connector's declared config out of the environment. Vorn supplies
|
|
282
30
|
* these through the connection's `env` / `secretEnv` maps, so a missing
|
|
@@ -285,35 +33,63 @@ declare function defineConnector(definition: ConnectorDefinition): Connector;
|
|
|
285
33
|
*/
|
|
286
34
|
declare function resolveConfig(connector: Connector, env?: NodeJS.ProcessEnv): ConnectorConfig;
|
|
287
35
|
|
|
288
|
-
interface CheckFinding {
|
|
289
|
-
/** `error` means the connector will misbehave in Vorn; `warn` is advisory. */
|
|
290
|
-
level: 'error' | 'warn';
|
|
291
|
-
code: string;
|
|
292
|
-
/** Which part of the connector the finding is about. */
|
|
293
|
-
target: string;
|
|
294
|
-
message: string;
|
|
295
|
-
}
|
|
296
|
-
interface CheckOptions {
|
|
297
|
-
/**
|
|
298
|
-
* Poll every trigger against the real source. Off by default, so a check
|
|
299
|
-
* runs on declared `sample` items and the definition alone.
|
|
300
|
-
*/
|
|
301
|
-
live?: boolean;
|
|
302
|
-
/** Credentials, required by `live`. */
|
|
303
|
-
config?: ConnectorConfig;
|
|
304
|
-
now?: () => string;
|
|
305
|
-
}
|
|
306
36
|
/**
|
|
307
|
-
*
|
|
37
|
+
* How an extension asks the host for what it was granted.
|
|
308
38
|
*
|
|
309
|
-
* The
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
39
|
+
* The extension runs as its own process, so the bridge is an HTTP endpoint the
|
|
40
|
+
* host serves and names in the environment, with a token that says which
|
|
41
|
+
* extension is calling. The host grants exactly the permissions the manifest
|
|
42
|
+
* declared, which is why a call outside them comes back refused rather than
|
|
43
|
+
* empty — the same answer the check's stub gives, so an extension meets the
|
|
44
|
+
* rule once rather than twice.
|
|
313
45
|
*/
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
declare
|
|
46
|
+
/** Where the host answers, and the token that says who is asking. */
|
|
47
|
+
declare const HOST_URL_ENV = "VORN_EXTENSION_HOST";
|
|
48
|
+
declare const HOST_TOKEN_ENV = "VORN_EXTENSION_TOKEN";
|
|
49
|
+
/** The host refused a call the extension's manifest never asked for. */
|
|
50
|
+
declare class PermissionDeniedError extends Error {
|
|
51
|
+
constructor(method: string, detail: string);
|
|
52
|
+
}
|
|
53
|
+
interface HostBridgeOptions {
|
|
54
|
+
sessionId: string;
|
|
55
|
+
env?: NodeJS.ProcessEnv;
|
|
56
|
+
/** Replaced in tests so nothing opens a socket. */
|
|
57
|
+
fetchImpl?: typeof fetch;
|
|
58
|
+
}
|
|
59
|
+
/** The host as an extension process reaches it, over the bridge Vorn served it. */
|
|
60
|
+
declare function createExtensionHost(options: HostBridgeOptions): ExtensionHost;
|
|
61
|
+
|
|
62
|
+
/** Where Vorn serves a browser-sign-in connector the window it signed in through. */
|
|
63
|
+
declare const BROWSER_HOST_ENV = "VORN_BROWSER_HOST";
|
|
64
|
+
declare const BROWSER_TOKEN_ENV = "VORN_BROWSER_TOKEN";
|
|
65
|
+
/** The tool call a window request belongs to, so Vorn can tell a step's own requests from another's. */
|
|
66
|
+
declare const SESSION_CALL_META = "vorn/sessionCall";
|
|
67
|
+
declare const SESSION_CALL_HEADER = "x-vorn-session-call";
|
|
68
|
+
/** The signed-in window could not make the call: Vorn is closed, too old, or not the caller. */
|
|
69
|
+
declare class SessionUnavailableError extends Error {
|
|
70
|
+
/** Asking again cannot bring the window back, so the SDK's retries let this through at once. */
|
|
71
|
+
readonly retryable = false;
|
|
72
|
+
constructor(message: string);
|
|
73
|
+
}
|
|
74
|
+
/** Vorn refused the call itself, for instance because it is off the connector's origins. */
|
|
75
|
+
declare class SessionRefusedError extends Error {
|
|
76
|
+
readonly retryable = false;
|
|
77
|
+
constructor(message: string);
|
|
78
|
+
}
|
|
79
|
+
interface SessionFetchOptions {
|
|
80
|
+
env?: NodeJS.ProcessEnv;
|
|
81
|
+
/** Replaced in tests so nothing opens a socket. */
|
|
82
|
+
fetchImpl?: typeof fetch;
|
|
83
|
+
/** The key of the tool call these requests belong to, from its MCP metadata. */
|
|
84
|
+
call?: string;
|
|
85
|
+
}
|
|
86
|
+
/** A fetch whose requests run inside the connection's signed-in Vorn window, so no cookie reaches this process. */
|
|
87
|
+
declare function createSessionFetch(options?: SessionFetchOptions): typeof fetch;
|
|
88
|
+
|
|
89
|
+
/** An origin a connector may act on: `https://host`, or `https://*.host` for every subdomain. */
|
|
90
|
+
declare const ORIGIN_PATTERN: RegExp;
|
|
91
|
+
/** Whether `url` is on one of the declared origins. */
|
|
92
|
+
declare function withinOrigins(origins: readonly string[], url: string): boolean;
|
|
317
93
|
|
|
318
94
|
/**
|
|
319
95
|
* Run a declarative trigger: call the author's `fetch`, then apply the chosen
|
|
@@ -341,119 +117,99 @@ declare function normalizeItem(item: ConnectorItem, polledAt: string): Normalize
|
|
|
341
117
|
*/
|
|
342
118
|
declare function normalizeItems(items: ConnectorItem[], polledAt: string): NormalizedItem[];
|
|
343
119
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
interface
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
cursor?: string;
|
|
353
|
-
limit?: number;
|
|
354
|
-
now?: () => string;
|
|
120
|
+
/** The value at a dotted path, or undefined if any step is missing. */
|
|
121
|
+
declare function valueAt(value: unknown, path: string): unknown;
|
|
122
|
+
/** Run a response through the declared ops, left to right. */
|
|
123
|
+
declare function applyPostReceive(value: unknown, ops: PostReceiveOp[] | undefined): unknown;
|
|
124
|
+
|
|
125
|
+
interface RequestScope {
|
|
126
|
+
args: Record<string, unknown>;
|
|
127
|
+
config: ConnectorConfig;
|
|
355
128
|
}
|
|
356
|
-
/** Longest chain of pages `drainPoll` will follow before calling it a bug. */
|
|
357
|
-
declare const MAX_POLL_PAGES = 1000;
|
|
358
129
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
130
|
+
* How a substituted value is written into its surroundings.
|
|
131
|
+
*
|
|
132
|
+
* A value's meaning depends on where it lands: a path segment has to be
|
|
133
|
+
* escaped, a header has characters it may not contain at all. Passing that
|
|
134
|
+
* decision in means the substitution is made safe once, here, instead of by
|
|
135
|
+
* every author who interpolates an argument.
|
|
361
136
|
*/
|
|
362
|
-
|
|
137
|
+
type Substitution = (value: string, source: 'args' | 'config') => string;
|
|
363
138
|
/**
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
139
|
+
* Resolve `{{args.x}}` and `{{config.y}}` inside a value.
|
|
140
|
+
*
|
|
141
|
+
* A whole-string placeholder keeps the referenced value's own type, so a body
|
|
142
|
+
* can carry a number or an object; a placeholder among other text is rendered
|
|
143
|
+
* into the string. An unset reference resolves to `undefined` on its own and to
|
|
144
|
+
* the empty string when it is part of a larger one, which is what lets an
|
|
145
|
+
* optional argument simply not appear.
|
|
146
|
+
*
|
|
147
|
+
* With a `substitute`, every resolved value passes through it — including a
|
|
148
|
+
* whole-string one, which then arrives as text rather than keeping its type,
|
|
149
|
+
* because a place that needs escaping is a place that holds a string.
|
|
367
150
|
*/
|
|
368
|
-
declare function
|
|
369
|
-
interface
|
|
370
|
-
|
|
371
|
-
|
|
151
|
+
declare function resolveTemplates(value: unknown, scope: RequestScope, substitute?: Substitution): unknown;
|
|
152
|
+
interface ResolvedRequest {
|
|
153
|
+
url: string;
|
|
154
|
+
method: string;
|
|
155
|
+
headers: Record<string, string>;
|
|
156
|
+
body?: string;
|
|
372
157
|
}
|
|
373
|
-
/**
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
*/
|
|
378
|
-
declare function runAction(connector: Connector, actionType: string, args: Record<string, unknown>, options?: RunActionOptions): Promise<Record<string, unknown>>;
|
|
379
|
-
|
|
380
|
-
/** MCP tool name a trigger is served under. */
|
|
381
|
-
declare function pollToolName(triggerType: string): string;
|
|
382
|
-
/** Tool that reports the connector's manifest and setup hints. */
|
|
383
|
-
declare const MANIFEST_TOOL = "vorn_connector_manifest";
|
|
384
|
-
/**
|
|
385
|
-
* Tool that reports whether the connector can run right now. Present only when
|
|
386
|
-
* the connector declares a `preflight`, so its absence means "nothing to
|
|
387
|
-
* check" rather than "check passed".
|
|
388
|
-
*/
|
|
389
|
-
declare const PREFLIGHT_TOOL = "vorn_connector_preflight";
|
|
390
|
-
interface ConnectionSetup {
|
|
391
|
-
connectorId: string;
|
|
392
|
-
triggerType: string;
|
|
393
|
-
/** Values to paste into Vorn's MCP connection form. */
|
|
394
|
-
filters: {
|
|
395
|
-
pollTool: string;
|
|
396
|
-
itemsPath: 'items';
|
|
397
|
-
idField: 'externalId';
|
|
398
|
-
timestampField: 'updatedAt';
|
|
399
|
-
titleField: 'title';
|
|
400
|
-
urlField: 'url';
|
|
401
|
-
cursorArg: 'cursor';
|
|
402
|
-
cursorPath: 'nextCursor';
|
|
403
|
-
};
|
|
404
|
-
/** Environment variable names the connector reads. */
|
|
405
|
-
env: Array<{
|
|
406
|
-
name: string;
|
|
407
|
-
required: boolean;
|
|
408
|
-
secret: boolean;
|
|
409
|
-
description?: string;
|
|
410
|
-
}>;
|
|
158
|
+
/** Build the exact call a declared request makes, with its templates resolved. */
|
|
159
|
+
declare function resolveRequest(request: ActionRequest, scope: RequestScope): ResolvedRequest;
|
|
160
|
+
interface SendOptions {
|
|
161
|
+
fetchImpl: typeof fetch;
|
|
411
162
|
}
|
|
412
163
|
/**
|
|
413
|
-
*
|
|
164
|
+
* The action's result, as Vorn stores it.
|
|
414
165
|
*
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
* connector back its own cursor each poll, which is what lets its dedupe
|
|
419
|
-
* strategy — rather than Vorn's timestamp comparison — decide what is new.
|
|
166
|
+
* A step's output is a record, so a response that is a list becomes `items` —
|
|
167
|
+
* the name the rest of this SDK already uses for one — and any other bare
|
|
168
|
+
* value becomes `result`.
|
|
420
169
|
*/
|
|
421
|
-
declare function
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
170
|
+
declare function asOutput(value: unknown): Record<string, unknown>;
|
|
171
|
+
/** Longest chain of pages a declared request will follow before calling it a bug. */
|
|
172
|
+
declare const MAX_REQUEST_PAGES = 100;
|
|
173
|
+
/** The URL of the next page, as a paged HTTP API states it in its `Link` header. */
|
|
174
|
+
declare function nextLink(header: string | null): string | undefined;
|
|
175
|
+
/** Run a declared request end to end: resolve, send, follow its pages, reshape. */
|
|
176
|
+
declare function executeRequest(request: ActionRequest, postReceive: PostReceiveOp[] | undefined, scope: RequestScope, options: SendOptions): Promise<Record<string, unknown>>;
|
|
177
|
+
|
|
178
|
+
interface PackOptions {
|
|
179
|
+
/** Module specifier the connector was loaded from, bundled as the pack entry. */
|
|
180
|
+
entry: string;
|
|
181
|
+
/** Directory the `.vorn.tgz` is written to; defaults to the working directory. */
|
|
182
|
+
outDir?: string;
|
|
183
|
+
/** Directory module specifiers resolve from; defaults to the working directory. */
|
|
184
|
+
resolveDir?: string;
|
|
185
|
+
/** SDK specifier the generated stdio entry imports; overridden in tests. */
|
|
186
|
+
sdkModule?: string;
|
|
187
|
+
/** Size ceiling for the written archive; defaults to `MAX_PACK_BYTES`. */
|
|
188
|
+
maxBytes?: number;
|
|
189
|
+
/** Size ceiling for what the archive unpacks to; defaults to `MAX_UNPACKED_BYTES`. */
|
|
190
|
+
maxUnpackedBytes?: number;
|
|
191
|
+
/** Replaced in tests so packing does not shell out to a bundler. */
|
|
192
|
+
bundle?(request: BundleRequest): Promise<BundleOutput>;
|
|
193
|
+
/** Replaced in tests whose subject is the archive rather than the launch; defaults to starting it for real. */
|
|
194
|
+
launch?(dir: string): Promise<CheckFinding[]>;
|
|
195
|
+
}
|
|
196
|
+
interface PackResult {
|
|
197
|
+
findings: CheckFinding[];
|
|
198
|
+
/** Absolute path of the written pack; absent when a gate failed. */
|
|
199
|
+
file?: string;
|
|
200
|
+
bytes?: number;
|
|
449
201
|
}
|
|
450
|
-
/**
|
|
451
|
-
declare function
|
|
202
|
+
/** File name Vorn recognizes as a connector pack. */
|
|
203
|
+
declare function packFileName(connector: Connector): string;
|
|
204
|
+
/** The entry is generated, not the author's bin, so every pack launches alike. */
|
|
205
|
+
declare function packConnector(connector: Connector, options: PackOptions): Promise<PackResult>;
|
|
452
206
|
|
|
453
207
|
interface ConnectorServerOptions {
|
|
454
208
|
/** Resolved connector configuration. Defaults to reading `process.env`. */
|
|
455
209
|
config?: ConnectorConfig;
|
|
456
210
|
now?: () => string;
|
|
211
|
+
/** The host an extension's contributions talk to; defaults to the bridge Vorn served. */
|
|
212
|
+
host?(sessionId: string): ExtensionHost;
|
|
457
213
|
}
|
|
458
214
|
/**
|
|
459
215
|
* Expose a connector as an MCP server.
|
|
@@ -467,28 +223,36 @@ declare function createConnectorServer(connector: Connector, options?: Connector
|
|
|
467
223
|
/** Serve a connector on stdio. This is the one line a connector's bin needs. */
|
|
468
224
|
declare function serveConnector(connector: Connector, options?: ConnectorServerOptions): Promise<void>;
|
|
469
225
|
|
|
470
|
-
interface HarnessOptions {
|
|
471
|
-
config?: ConnectorConfig;
|
|
472
|
-
/** Fixed clock, so `updatedAt` defaults and cursors are deterministic. */
|
|
473
|
-
now?: () => string;
|
|
474
|
-
}
|
|
475
|
-
interface ConnectorHarness {
|
|
476
|
-
poll(triggerType: string, options?: RunPollOptions): Promise<PollPage>;
|
|
477
|
-
drain(triggerType: string, options?: RunPollOptions): Promise<NormalizedItem[]>;
|
|
478
|
-
execute(actionType: string, args?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
479
|
-
manifest(): ConnectorManifest;
|
|
480
|
-
/**
|
|
481
|
-
* Poll repeatedly the way Vorn does — carrying the newest `updatedAt`
|
|
482
|
-
* forward as the watermark — and return only items a real installation
|
|
483
|
-
* would treat as new. Catches the classic connector bug where a poll
|
|
484
|
-
* ignores its lower bound and re-delivers the same backlog forever.
|
|
485
|
-
*/
|
|
486
|
-
pollTwice(triggerType: string, options?: RunPollOptions): Promise<NormalizedItem[]>;
|
|
487
|
-
}
|
|
488
226
|
/**
|
|
489
|
-
*
|
|
490
|
-
*
|
|
227
|
+
* The files a new connector starts as.
|
|
228
|
+
*
|
|
229
|
+
* A connector is mostly boilerplate — a package that builds, an entry that
|
|
230
|
+
* serves, a definition, a test that proves it without a network — and getting
|
|
231
|
+
* that boilerplate right is the slowest part of writing the interesting bit.
|
|
232
|
+
* Generating it means every connector starts from the same shape, which is
|
|
233
|
+
* also the shape `check` and `pack` expect to find.
|
|
234
|
+
*
|
|
235
|
+
* The files are returned rather than written so the decision of what to write
|
|
236
|
+
* stays testable, and the writing stays in the CLI.
|
|
491
237
|
*/
|
|
492
|
-
|
|
238
|
+
interface ScaffoldOptions {
|
|
239
|
+
id: string;
|
|
240
|
+
/** Defaults to the id in title case. */
|
|
241
|
+
name?: string;
|
|
242
|
+
description?: string;
|
|
243
|
+
/** Emit the shape the connectors repository expects of a package inside it. */
|
|
244
|
+
repoConventions?: boolean;
|
|
245
|
+
/** What to start: a connector that polls a service, or an extension that contributes to a card. */
|
|
246
|
+
kind?: 'connector' | 'extension';
|
|
247
|
+
}
|
|
248
|
+
interface ScaffoldFile {
|
|
249
|
+
/** Relative to the directory the connector is created in. */
|
|
250
|
+
path: string;
|
|
251
|
+
contents: string;
|
|
252
|
+
}
|
|
253
|
+
/** `acme-tickets` → `Acme Tickets`, so a generated name reads like a name. */
|
|
254
|
+
declare function titleCase(id: string): string;
|
|
255
|
+
/** Every file a new connector or extension starts with, ready to build, check and pack. */
|
|
256
|
+
declare function scaffoldFiles(options: ScaffoldOptions): ScaffoldFile[];
|
|
493
257
|
|
|
494
|
-
export {
|
|
258
|
+
export { ActionRequest, BROWSER_HOST_ENV, BROWSER_TOKEN_ENV, BundleOutput, BundleRequest, CheckFinding, Connector, ConnectorConfig, ConnectorDefinition, ConnectorItem, type ConnectorServerOptions, EXTENSION_PERMISSIONS, ExtensionDefinition, ExtensionHost, ExtensionHostMethod, ExtensionPermission, HOST_PERMISSIONS, HOST_TOKEN_ENV, HOST_URL_ENV, type HostBridgeOptions, MAX_REQUEST_PAGES, NormalizedItem, ORIGIN_PATTERN, type PackOptions, type PackResult, PermissionDeniedError, PollContext, PollOutcome, PostReceiveOp, type RequestScope, type ResolvedRequest, SESSION_CALL_HEADER, SESSION_CALL_META, type ScaffoldFile, type ScaffoldOptions, type SessionFetchOptions, SessionRefusedError, SessionUnavailableError, type Substitution, TriggerDefinition, applyPostReceive, asOutput, createConnectorServer, createExtensionHost, createSessionFetch, defineConnector, defineExtension, envNameFor, executeRequest, nextLink, normalizeItem, normalizeItems, packConnector, packFileName, pollWithDedupe, resolveConfig, resolveRequest, resolveTemplates, scaffoldFiles, serveConnector, titleCase, valueAt, withinOrigins };
|