apps 1.0.0-beta.2 → 1.0.0-beta.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/dist/authoring/index.d.ts +222 -34
- package/dist/authoring/index.js +11 -1
- package/dist/{chunk-NFLNA2SC.js → chunk-4OZFMCTT.js} +7 -1
- package/dist/{chunk-LWKQDDLZ.js → chunk-A3H32P2J.js} +46 -1
- package/dist/chunk-F7GZYEAC.js +41 -0
- package/dist/{chunk-OGCPVWAZ.js → chunk-MUFMJRXR.js} +130 -13
- package/dist/chunk-S5KFP4JQ.js +20 -0
- package/dist/{chunk-646MS7DD.js → chunk-Y6LLTN7W.js} +7 -7
- package/dist/chunk-YUZ4TXOY.js +27 -0
- package/dist/http/index.d.ts +9 -0
- package/dist/http/index.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +23 -1
- package/dist/manifest/contract.d.ts +8 -0
- package/dist/manifest/index.js +3 -3
- package/dist/mcp/client.d.ts +9 -0
- package/dist/mcp/index.d.ts +11 -0
- package/dist/mcp/index.js +7 -0
- package/dist/openapi/index.d.ts +14 -0
- package/dist/openapi/index.js +7 -0
- package/dist/openapi/mapper.d.ts +7 -0
- package/dist/runner/index.js +29 -15
- package/dist/runner/protocol.d.ts +18 -5
- package/dist/runner/protocol.js +5 -3
- package/dist/runtime/index.d.ts +42 -5
- package/dist/runtime/index.js +3 -1
- package/dist/workerd/index.d.ts +1 -1
- package/dist/workerd/index.js +1 -1
- package/package.json +13 -6
- package/src/authoring/index.ts +362 -44
- package/src/http/index.ts +26 -0
- package/src/index.ts +3 -0
- package/src/manifest/contract.ts +9 -0
- package/src/mcp/client.ts +59 -0
- package/src/mcp/index.ts +42 -0
- package/src/openapi/index.ts +70 -0
- package/src/openapi/mapper.ts +25 -0
- package/src/runner/index.ts +35 -12
- package/src/runner/protocol.ts +32 -7
- package/src/runtime/index.ts +209 -22
- package/src/workerd/index.ts +2 -0
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
* Authored modules record plain claims without I/O or user context; the
|
|
4
4
|
* manifest loader owns execution, validation, and effects.
|
|
5
5
|
*/
|
|
6
|
+
/** A single opaque credential with RFC 6750 bearer semantics. */
|
|
7
|
+
export interface BearerMethod {
|
|
8
|
+
readonly kind: "bearer";
|
|
9
|
+
readonly label: string;
|
|
10
|
+
readonly help?: string;
|
|
11
|
+
}
|
|
12
|
+
/** An RFC 7617 username/password pair. */
|
|
13
|
+
export interface BasicMethod {
|
|
14
|
+
readonly kind: "basic";
|
|
15
|
+
readonly label: string;
|
|
16
|
+
readonly help?: string;
|
|
17
|
+
}
|
|
6
18
|
export interface SecretsMethod<F extends Readonly<Record<string, SecretField>> = Readonly<Record<string, SecretField>>> {
|
|
7
19
|
readonly kind: "secrets";
|
|
8
20
|
readonly label: string;
|
|
@@ -17,7 +29,7 @@ export interface SecretField {
|
|
|
17
29
|
readonly secret: boolean;
|
|
18
30
|
}
|
|
19
31
|
/**
|
|
20
|
-
* An oauth auth method is a
|
|
32
|
+
* An oauth auth method is a bearer method with acquisition strategies
|
|
21
33
|
* layered on: the material contract is always {token, refresh_token?,
|
|
22
34
|
* expires_at?}, and the host fills it by the best strategy it can offer
|
|
23
35
|
* — authorization-code ceremony, device-code ceremony, or paste. Paste
|
|
@@ -41,7 +53,15 @@ export interface OAuthMethod {
|
|
|
41
53
|
* (audience-bound tokens, DPoP). Stated, never inferred. */
|
|
42
54
|
readonly paste?: false;
|
|
43
55
|
}
|
|
44
|
-
export type AuthMethod = SecretsMethod | OAuthMethod;
|
|
56
|
+
export type AuthMethod = BearerMethod | BasicMethod | SecretsMethod | OAuthMethod;
|
|
57
|
+
export declare const bearer: (opts: {
|
|
58
|
+
readonly label: string;
|
|
59
|
+
readonly help?: string;
|
|
60
|
+
}) => BearerMethod;
|
|
61
|
+
export declare const basic: (opts: {
|
|
62
|
+
readonly label: string;
|
|
63
|
+
readonly help?: string;
|
|
64
|
+
}) => BasicMethod;
|
|
45
65
|
export declare const secrets: <const F extends Readonly<Record<string, SecretField>>>(opts: {
|
|
46
66
|
readonly label: string;
|
|
47
67
|
/** Markdown shown under this auth method on the connect page, for example:
|
|
@@ -82,55 +102,171 @@ export interface RequirementSpec {
|
|
|
82
102
|
readonly description?: string;
|
|
83
103
|
}
|
|
84
104
|
declare const RequirementKey: unique symbol;
|
|
105
|
+
declare const RequirementPhantom: unique symbol;
|
|
106
|
+
/** Requirement arity, tracked at the type level so handler contexts
|
|
107
|
+
* know whether a role arrives as one entry, maybe-one, or a list. */
|
|
108
|
+
export type RequirementArity = "one" | "optional" | "many";
|
|
85
109
|
/**
|
|
86
110
|
* A requirement value in a tool's `requirements` record. A Service IS
|
|
87
111
|
* a requirement (bare value = arity "one"); .optional()/.array()
|
|
88
112
|
* return terminal Requirements so nonsense chains do not typecheck.
|
|
113
|
+
* The phantom property is never assigned — it exists so auth-compose
|
|
114
|
+
* callbacks and handler contexts can recover the service's grants, a
|
|
115
|
+
* .grant() pin, and the arity at the type level.
|
|
89
116
|
*/
|
|
90
|
-
export interface Requirement<D extends ServiceDecl = ServiceDecl> {
|
|
117
|
+
export interface Requirement<D extends ServiceDecl = ServiceDecl, G extends string | undefined = string | undefined, A extends RequirementArity = RequirementArity> {
|
|
91
118
|
readonly [RequirementKey]: RequirementSpec;
|
|
92
|
-
|
|
119
|
+
readonly [RequirementPhantom]?: {
|
|
120
|
+
readonly decl: D;
|
|
121
|
+
readonly pinned: G;
|
|
122
|
+
readonly arity: A;
|
|
123
|
+
};
|
|
124
|
+
describe(text: string): Requirement<D, G, A>;
|
|
93
125
|
}
|
|
94
|
-
export interface Service<D extends ServiceDecl = ServiceDecl> extends Requirement<D> {
|
|
126
|
+
export interface Service<D extends ServiceDecl = ServiceDecl, G extends (keyof NonNullable<D["auth"]> & string) | undefined = undefined> extends Requirement<D, G, "one"> {
|
|
95
127
|
readonly decl: D;
|
|
96
|
-
optional(): Requirement<D>;
|
|
97
|
-
array(): Requirement<D>;
|
|
128
|
+
optional(): Requirement<D, G, "optional">;
|
|
129
|
+
array(): Requirement<D, G, "many">;
|
|
98
130
|
/** Pin one auth method: this tool supports only the named grant. */
|
|
99
|
-
grant
|
|
100
|
-
describe(text: string): Service<D>;
|
|
131
|
+
grant<N extends keyof NonNullable<D["auth"]> & string>(name: N): Service<D, N>;
|
|
132
|
+
describe(text: string): Service<D, G>;
|
|
101
133
|
}
|
|
102
134
|
/** A publish-time authoring problem accumulated without interrupting defines. */
|
|
103
135
|
export interface Problem {
|
|
104
136
|
readonly message: string;
|
|
105
137
|
}
|
|
106
|
-
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
138
|
+
/** One connected role, discriminated by the declared auth method kind. */
|
|
139
|
+
export type AuthRoleEntry<D extends ServiceDecl> = {
|
|
140
|
+
[N in keyof NonNullable<D["auth"]> & string]: NonNullable<D["auth"]>[N] extends SecretsMethod<infer F> ? {
|
|
141
|
+
readonly grant: N;
|
|
142
|
+
readonly kind: "secrets";
|
|
143
|
+
readonly secrets: {
|
|
144
|
+
readonly [K in keyof F & string]: string;
|
|
145
|
+
};
|
|
146
|
+
} : NonNullable<D["auth"]>[N] extends BasicMethod ? {
|
|
147
|
+
readonly grant: N;
|
|
148
|
+
readonly kind: "basic";
|
|
149
|
+
readonly username: string;
|
|
150
|
+
readonly password: string;
|
|
151
|
+
} : {
|
|
152
|
+
readonly grant: N;
|
|
153
|
+
readonly kind: "bearer" | "oauth";
|
|
154
|
+
readonly token: string;
|
|
155
|
+
};
|
|
156
|
+
}[keyof NonNullable<D["auth"]> & string];
|
|
157
|
+
/** Kind-discriminated credential material accepted by surface helpers. */
|
|
158
|
+
export type RoleMaterial = {
|
|
159
|
+
readonly kind: "bearer" | "oauth";
|
|
160
|
+
readonly token: string;
|
|
118
161
|
} | {
|
|
119
|
-
readonly kind: "
|
|
120
|
-
readonly
|
|
121
|
-
|
|
122
|
-
|
|
162
|
+
readonly kind: "basic";
|
|
163
|
+
readonly username: string;
|
|
164
|
+
readonly password: string;
|
|
165
|
+
} | {
|
|
166
|
+
readonly kind: "secrets";
|
|
167
|
+
readonly secrets: Readonly<Record<string, string>>;
|
|
168
|
+
};
|
|
169
|
+
/** Recover the connected role type produced by a service requirement. */
|
|
170
|
+
export type RoleOf<S, G extends string | undefined = undefined> = S extends Requirement<infer D, infer Pin> ? [G] extends [string] ? Extract<AuthRoleEntry<D>, {
|
|
171
|
+
grant: G;
|
|
172
|
+
}> : Pin extends string ? Extract<AuthRoleEntry<D>, {
|
|
173
|
+
grant: Pin;
|
|
174
|
+
}> : AuthRoleEntry<D> : never;
|
|
175
|
+
/** Role record received by an authored authentication placement callback. */
|
|
176
|
+
export type AuthRoles<Reqs extends Readonly<Record<string, Requirement>>> = {
|
|
177
|
+
readonly [K in keyof Reqs]: NonNullable<Reqs[K][typeof RequirementPhantom]> extends {
|
|
178
|
+
readonly decl: infer D extends ServiceDecl;
|
|
179
|
+
readonly pinned: infer G;
|
|
180
|
+
} ? G extends string ? Extract<AuthRoleEntry<D>, {
|
|
181
|
+
grant: G;
|
|
182
|
+
}> : AuthRoleEntry<D> : never;
|
|
183
|
+
};
|
|
184
|
+
/** Request placement returned by an authored dynamic auth callback. */
|
|
185
|
+
export interface AuthPlacement {
|
|
186
|
+
readonly headers?: HeadersInit;
|
|
187
|
+
readonly searchParams?: URLSearchParams | Readonly<Record<string, string>>;
|
|
188
|
+
}
|
|
189
|
+
export type AuthComposeFn<Reqs extends Readonly<Record<string, Requirement>> = never> = (roles: AuthRoles<Reqs>) => AuthPlacement | undefined | void;
|
|
190
|
+
export type HasSecretsGrant<D extends ServiceDecl> = true extends (NonNullable<D["auth"]>[keyof NonNullable<D["auth"]>] extends infer M ? M extends SecretsMethod ? true : false : never) ? true : false;
|
|
191
|
+
/** Whether an OpenAPI wrapper must state credential placement explicitly. */
|
|
192
|
+
export type RequiresAuthCompose<Reqs extends Readonly<Record<string, Requirement>>> = true extends {
|
|
193
|
+
[K in keyof Reqs]: NonNullable<Reqs[K][typeof RequirementPhantom]> extends {
|
|
194
|
+
readonly decl: infer D extends ServiceDecl;
|
|
195
|
+
readonly pinned: infer G;
|
|
196
|
+
} ? G extends keyof NonNullable<D["auth"]> & string ? NonNullable<D["auth"]>[G] extends SecretsMethod ? true : false : HasSecretsGrant<D> : never;
|
|
197
|
+
}[keyof Reqs] ? true : false;
|
|
198
|
+
/** Record a wrapper-specific publish problem on the active authored file. @internal */
|
|
199
|
+
export declare const recordAuthoringProblem: (message: string) => void;
|
|
200
|
+
/** Operation curation for a dynamic tool set. Exactly one of allow/block. */
|
|
201
|
+
export type OperationSelection = {
|
|
202
|
+
readonly allow: readonly string[];
|
|
203
|
+
readonly block?: undefined;
|
|
204
|
+
} | {
|
|
205
|
+
readonly block: readonly string[];
|
|
206
|
+
readonly allow?: undefined;
|
|
123
207
|
};
|
|
208
|
+
/** One tool emitted by a dynamic discovery pass. */
|
|
209
|
+
export interface DiscoveredToolSpec {
|
|
210
|
+
readonly name: string;
|
|
211
|
+
readonly description: string;
|
|
212
|
+
readonly input: SchemaLike;
|
|
213
|
+
readonly annotations?: ToolAnnotations;
|
|
214
|
+
readonly detail?: unknown;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The generic authored shape of a dynamic pair: ctx is inferred from
|
|
218
|
+
* the requirements record exactly as for static tools. Discovered
|
|
219
|
+
* inputs are runtime data (the schema arrives from the upstream at
|
|
220
|
+
* discover time), so `call`'s input is honestly `unknown` — the
|
|
221
|
+
* runtime validates against the discovered descriptor before calling.
|
|
222
|
+
*/
|
|
223
|
+
export interface DynamicToolsDecl<Reqs extends Readonly<Record<string, Requirement>> | undefined = Readonly<Record<string, Requirement>> | undefined> {
|
|
224
|
+
readonly description: string;
|
|
225
|
+
readonly requirements?: Reqs;
|
|
226
|
+
discover(ctx: HandlerCtx<Reqs>): Promise<readonly DiscoveredToolSpec[]>;
|
|
227
|
+
call(tool: {
|
|
228
|
+
readonly name: string;
|
|
229
|
+
readonly detail: unknown;
|
|
230
|
+
}, input: unknown, ctx: HandlerCtx<Reqs>): Promise<unknown>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The erased registry row of a dynamic pair — same storage boundary
|
|
234
|
+
* as ToolSpec. App code: runs where handlers run (in-process locally,
|
|
235
|
+
* inside the isolate on workerd) and places credentials itself from
|
|
236
|
+
* ctx, like any handler. `discover` interrogates the tool source;
|
|
237
|
+
* `call` executes one discovered tool from the identity and detail
|
|
238
|
+
* discover emitted.
|
|
239
|
+
*/
|
|
240
|
+
export interface DynamicToolsSpec {
|
|
241
|
+
readonly description: string;
|
|
242
|
+
readonly requirements?: Readonly<Record<string, Requirement>>;
|
|
243
|
+
discover(ctx: never): Promise<readonly DiscoveredToolSpec[]>;
|
|
244
|
+
call(tool: {
|
|
245
|
+
readonly name: string;
|
|
246
|
+
readonly detail: unknown;
|
|
247
|
+
}, input: never, ctx: never): Promise<unknown>;
|
|
248
|
+
}
|
|
124
249
|
declare const DynamicKey: unique symbol;
|
|
125
|
-
/** The value
|
|
126
|
-
*
|
|
250
|
+
/** The value defineDynamicTools returns: an opaque handle a tool file
|
|
251
|
+
* default-exports. The spec is undefined when the definition was
|
|
127
252
|
* invalid (a problem was recorded instead). */
|
|
128
253
|
export interface DynamicToolSet {
|
|
129
|
-
readonly [DynamicKey]:
|
|
254
|
+
readonly [DynamicKey]: DynamicToolsSpec | undefined;
|
|
130
255
|
}
|
|
131
|
-
/**
|
|
132
|
-
export
|
|
133
|
-
|
|
256
|
+
/** Reads a dynamic spec from a tool file's default export. @internal */
|
|
257
|
+
export declare const dynamicSpecOf: (value: unknown) => DynamicToolsSpec | undefined;
|
|
258
|
+
/**
|
|
259
|
+
* The dynamic-tools primitive: an author-written discover/call pair
|
|
260
|
+
* whose tool list is interrogated at runtime, per connection, instead
|
|
261
|
+
* of authored one file at a time. The file's name becomes the address
|
|
262
|
+
* segment (appKey/<stem>/<toolName>); tools land in the catalog after
|
|
263
|
+
* discovery and never block a save. fromMCP/fromOpenAPI are shipped
|
|
264
|
+
* pairs over this same primitive.
|
|
265
|
+
*/
|
|
266
|
+
export declare const defineDynamicTools: <const Reqs extends Readonly<Record<string, Requirement>> | undefined = undefined>(decl: DynamicToolsDecl<Reqs>) => DynamicToolSet;
|
|
267
|
+
/** A registered dynamic tool set and its source attribution. @internal */
|
|
268
|
+
export interface DynamicRegistration {
|
|
269
|
+
readonly spec: DynamicToolsSpec;
|
|
134
270
|
readonly file: string;
|
|
135
271
|
}
|
|
136
272
|
/** A registered service declaration and its source attribution. @internal */
|
|
@@ -148,7 +284,7 @@ export interface Registry {
|
|
|
148
284
|
app: AppManifest | undefined;
|
|
149
285
|
readonly services: Map<string, RegisteredService>;
|
|
150
286
|
readonly tools: Map<string, RegisteredTool>;
|
|
151
|
-
readonly dynamic: Map<string,
|
|
287
|
+
readonly dynamic: Map<string, DynamicRegistration>;
|
|
152
288
|
readonly problems: Problem[];
|
|
153
289
|
readonly toolFiles: Map<string, {
|
|
154
290
|
definitions: number;
|
|
@@ -178,14 +314,66 @@ export declare const defineApp: (manifest: {
|
|
|
178
314
|
}) => AppManifest;
|
|
179
315
|
/** Any Standard Schema (zod preferred) or a raw JSON-schema object. */
|
|
180
316
|
export type SchemaLike = object;
|
|
317
|
+
/**
|
|
318
|
+
* The validated value a Standard Schema produces, recovered from its
|
|
319
|
+
* phantom types (zod 4 and effect Schema both publish them). A raw
|
|
320
|
+
* JSON-schema object carries no phantom, so its input is `unknown` —
|
|
321
|
+
* stated weakness, not silent weakness.
|
|
322
|
+
*/
|
|
323
|
+
export type InferSchema<S> = S extends {
|
|
324
|
+
readonly "~standard": {
|
|
325
|
+
readonly types?: infer T;
|
|
326
|
+
};
|
|
327
|
+
} ? NonNullable<T> extends {
|
|
328
|
+
readonly output: infer O;
|
|
329
|
+
} ? O : unknown : unknown;
|
|
330
|
+
/**
|
|
331
|
+
* The capability a handler receives for one connected requirement
|
|
332
|
+
* role: the grant's kind-discriminated material (narrowed by any
|
|
333
|
+
* .grant() pin) plus the spending fetch. Arity shapes the value —
|
|
334
|
+
* `.optional()` may be absent, `.array()` is every connected account.
|
|
335
|
+
*/
|
|
336
|
+
export type HandlerRole<R> = R extends Requirement<infer D, infer G, infer A> ? [A] extends ["many"] ? ReadonlyArray<HandlerRoleEntry<D, G>> : [A] extends ["optional"] ? HandlerRoleEntry<D, G> | undefined : HandlerRoleEntry<D, G> : never;
|
|
337
|
+
/** One connected role entry: declared-auth material + capability fetch. */
|
|
338
|
+
export type HandlerRoleEntry<D extends ServiceDecl, G extends string | undefined> = ([G] extends [string] ? Extract<AuthRoleEntry<D>, {
|
|
339
|
+
grant: G;
|
|
340
|
+
}> : AuthRoleEntry<D>) & {
|
|
341
|
+
fetch(path: string, init?: RequestInit): Promise<Response>;
|
|
342
|
+
};
|
|
343
|
+
/** The ctx record a handler receives, keyed by requirement role. */
|
|
344
|
+
export type HandlerCtx<Reqs> = [Reqs] extends [Readonly<Record<string, Requirement>>] ? {
|
|
345
|
+
readonly [K in keyof Reqs]: HandlerRole<Reqs[K]>;
|
|
346
|
+
} : Readonly<Record<never, never>>;
|
|
181
347
|
export interface ToolAnnotations {
|
|
182
348
|
readonly readOnly?: boolean;
|
|
183
349
|
readonly destructive?: boolean;
|
|
184
350
|
/** Facts, not flow: shortfall surfaces as the scope challenge. */
|
|
185
351
|
readonly scopes?: readonly string[];
|
|
186
352
|
}
|
|
187
|
-
|
|
353
|
+
/**
|
|
354
|
+
* The generic authored shape: input/ctx/output are all inferred — the
|
|
355
|
+
* handler's input from the Standard Schema, ctx from the requirements
|
|
356
|
+
* record (grants, pins, arity), and the return type checked against
|
|
357
|
+
* the output schema when one is stated.
|
|
358
|
+
*/
|
|
359
|
+
export interface ToolDecl<Input extends SchemaLike = SchemaLike, Reqs extends Readonly<Record<string, Requirement>> | undefined = Readonly<Record<string, Requirement>> | undefined, Output extends SchemaLike | undefined = SchemaLike | undefined> {
|
|
188
360
|
/** Address segment. Single-tool files may omit it (filename). */
|
|
361
|
+
readonly name?: string;
|
|
362
|
+
readonly description: string;
|
|
363
|
+
readonly requirements?: Reqs;
|
|
364
|
+
readonly input: Input;
|
|
365
|
+
readonly output?: Output;
|
|
366
|
+
readonly annotations?: ToolAnnotations;
|
|
367
|
+
handler(input: InferSchema<Input>, ctx: HandlerCtx<Reqs>): Promise<Output extends SchemaLike ? InferSchema<Output> : unknown>;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* The erased registry row. Registration drops the generics — storage
|
|
371
|
+
* is untyped by design, the same boundary every schema library draws
|
|
372
|
+
* between its typed builders and its runtime representation. The
|
|
373
|
+
* runtime re-establishes safety by validating input before the
|
|
374
|
+
* handler runs and shaping ctx from resolved connections.
|
|
375
|
+
*/
|
|
376
|
+
export interface ToolSpec {
|
|
189
377
|
readonly name?: string;
|
|
190
378
|
readonly description: string;
|
|
191
379
|
readonly requirements?: Readonly<Record<string, Requirement>>;
|
|
@@ -198,7 +386,7 @@ declare const ToolKey: unique symbol;
|
|
|
198
386
|
export interface Tool {
|
|
199
387
|
readonly [ToolKey]: ToolSpec;
|
|
200
388
|
}
|
|
201
|
-
export declare const defineTool: (
|
|
389
|
+
export declare const defineTool: <const Input extends SchemaLike, const Reqs extends Readonly<Record<string, Requirement>> | undefined = undefined, const Output extends SchemaLike | undefined = undefined>(decl: ToolDecl<Input, Reqs, Output>) => Tool;
|
|
202
390
|
export declare const toolSpecOf: (value: unknown) => ToolSpec | undefined;
|
|
203
391
|
/** A tool file's default export. */
|
|
204
392
|
export type ToolExport = Tool | ReadonlyArray<Tool>;
|
package/dist/authoring/index.js
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__enterFile,
|
|
3
3
|
__leaveFile,
|
|
4
|
+
basic,
|
|
5
|
+
bearer,
|
|
4
6
|
defineApp,
|
|
7
|
+
defineDynamicTools,
|
|
5
8
|
defineTool,
|
|
9
|
+
dynamicSpecOf,
|
|
6
10
|
newRegistry,
|
|
7
11
|
oauth,
|
|
12
|
+
recordAuthoringProblem,
|
|
8
13
|
requirementSpecOf,
|
|
9
14
|
secrets,
|
|
10
15
|
service,
|
|
11
16
|
setActiveRegistry,
|
|
12
17
|
toolSpecOf
|
|
13
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-A3H32P2J.js";
|
|
14
19
|
export {
|
|
15
20
|
__enterFile,
|
|
16
21
|
__leaveFile,
|
|
22
|
+
basic,
|
|
23
|
+
bearer,
|
|
17
24
|
defineApp,
|
|
25
|
+
defineDynamicTools,
|
|
18
26
|
defineTool,
|
|
27
|
+
dynamicSpecOf,
|
|
19
28
|
newRegistry,
|
|
20
29
|
oauth,
|
|
30
|
+
recordAuthoringProblem,
|
|
21
31
|
requirementSpecOf,
|
|
22
32
|
secrets,
|
|
23
33
|
service,
|
|
@@ -5,7 +5,13 @@ var CallError = class extends Data.TaggedError("CallError") {
|
|
|
5
5
|
return `${this.target}: ${this.reason}`;
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
|
+
var DiscoverError = class extends Data.TaggedError("DiscoverError") {
|
|
9
|
+
get message() {
|
|
10
|
+
return `${this.segment}: ${this.reason}`;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
8
13
|
|
|
9
14
|
export {
|
|
10
|
-
CallError
|
|
15
|
+
CallError,
|
|
16
|
+
DiscoverError
|
|
11
17
|
};
|
|
@@ -1,8 +1,44 @@
|
|
|
1
1
|
// src/authoring/index.ts
|
|
2
|
+
var bearer = (opts) => ({ kind: "bearer", ...opts });
|
|
3
|
+
var basic = (opts) => ({ kind: "basic", ...opts });
|
|
2
4
|
var secrets = (opts) => ({ kind: "secrets", ...opts });
|
|
3
5
|
var oauth = (opts) => ({ kind: "oauth", ...opts });
|
|
4
6
|
var RequirementKey = Symbol.for("executor/apps/requirement");
|
|
7
|
+
var recordAuthoringProblem = (message) => {
|
|
8
|
+
const file = sourceFileFor("wrapper");
|
|
9
|
+
activeRegistry.problems.push({ message: `${file}: ${message}` });
|
|
10
|
+
};
|
|
5
11
|
var DynamicKey = Symbol.for("executor/apps/dynamic");
|
|
12
|
+
var dynamicSpecOf = (value) => typeof value === "object" && value !== null && DynamicKey in value ? value[DynamicKey] : void 0;
|
|
13
|
+
var defineDynamicTools = (decl) => {
|
|
14
|
+
const spec = decl;
|
|
15
|
+
const file = sourceFileFor("defineDynamicTools(...)");
|
|
16
|
+
const problems = [];
|
|
17
|
+
if (typeof spec.description !== "string" || spec.description.trim().length === 0)
|
|
18
|
+
problems.push("dynamic tool set description must not be empty");
|
|
19
|
+
const roles = Object.entries(spec.requirements ?? {});
|
|
20
|
+
if (roles.length > 1) problems.push("a dynamic tool set takes exactly one requirement role");
|
|
21
|
+
else if (roles.length === 1) {
|
|
22
|
+
const [role, value] = roles[0];
|
|
23
|
+
const requirementSpec = requirementSpecOf(value);
|
|
24
|
+
if (requirementSpec === void 0)
|
|
25
|
+
problems.push(`requirement '${role}' is not a service/requirement value`);
|
|
26
|
+
else if (requirementSpec.arity === "many")
|
|
27
|
+
problems.push(
|
|
28
|
+
`requirement '${role}' cannot be .array() \u2014 multiple accounts expand the catalog per connection, never merge one list`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
if (problems.length > 0) {
|
|
32
|
+
activeRegistry.problems.push(...problems.map((message) => ({ message: `${file}: ${message}` })));
|
|
33
|
+
return { [DynamicKey]: void 0 };
|
|
34
|
+
}
|
|
35
|
+
if (activeRegistry.dynamic.has(file))
|
|
36
|
+
activeRegistry.problems.push({
|
|
37
|
+
message: `${file}: one dynamic tool set per file \u2014 its address segment is the file's name`
|
|
38
|
+
});
|
|
39
|
+
else activeRegistry.dynamic.set(file, { spec, file });
|
|
40
|
+
return { [DynamicKey]: spec };
|
|
41
|
+
};
|
|
6
42
|
var newRegistry = () => ({
|
|
7
43
|
app: void 0,
|
|
8
44
|
services: /* @__PURE__ */ new Map(),
|
|
@@ -61,7 +97,11 @@ var defineApp = (manifest) => {
|
|
|
61
97
|
return value;
|
|
62
98
|
};
|
|
63
99
|
var ToolKey = Symbol.for("executor/apps/tool");
|
|
64
|
-
var defineTool = (
|
|
100
|
+
var defineTool = (decl) => {
|
|
101
|
+
const spec = decl;
|
|
102
|
+
return registerTool(spec);
|
|
103
|
+
};
|
|
104
|
+
var registerTool = (spec) => {
|
|
65
105
|
const file = sourceFileFor("defineTool(...)");
|
|
66
106
|
const value = { [ToolKey]: spec };
|
|
67
107
|
const fileName = file.slice(file.lastIndexOf("/") + 1);
|
|
@@ -84,8 +124,13 @@ var isTool = (value) => typeof value === "object" && value !== null && ToolKey i
|
|
|
84
124
|
var toolSpecOf = (value) => isTool(value) ? value[ToolKey] : void 0;
|
|
85
125
|
|
|
86
126
|
export {
|
|
127
|
+
bearer,
|
|
128
|
+
basic,
|
|
87
129
|
secrets,
|
|
88
130
|
oauth,
|
|
131
|
+
recordAuthoringProblem,
|
|
132
|
+
dynamicSpecOf,
|
|
133
|
+
defineDynamicTools,
|
|
89
134
|
newRegistry,
|
|
90
135
|
setActiveRegistry,
|
|
91
136
|
__enterFile,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineDynamicTools,
|
|
3
|
+
recordAuthoringProblem,
|
|
4
|
+
requirementSpecOf
|
|
5
|
+
} from "./chunk-A3H32P2J.js";
|
|
6
|
+
|
|
7
|
+
// src/openapi/mapper.ts
|
|
8
|
+
var openapiDiscover = async (_spec, _ctx, _auth, _operations) => {
|
|
9
|
+
throw new Error("openapi mapper not built yet");
|
|
10
|
+
};
|
|
11
|
+
var openapiCall = async (_tool, _input, _ctx, _auth) => {
|
|
12
|
+
throw new Error("openapi mapper not built yet");
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/openapi/index.ts
|
|
16
|
+
var enforceSecretsPlacement = (requirements, auth) => {
|
|
17
|
+
if (auth !== void 0) return;
|
|
18
|
+
for (const value of Object.values(requirements ?? {})) {
|
|
19
|
+
const spec = requirementSpecOf(value);
|
|
20
|
+
const methods = spec?.grant === void 0 ? Object.values(spec?.service.auth ?? {}) : [spec.service.auth?.[spec.grant]].filter((method) => method !== void 0);
|
|
21
|
+
if (methods.some((method) => method.kind === "secrets"))
|
|
22
|
+
recordAuthoringProblem(
|
|
23
|
+
"fromOpenAPI: the service offers a secrets() auth method, so 'auth' must state how the credential rides"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function fromOpenAPI(spec, options) {
|
|
28
|
+
enforceSecretsPlacement(options?.requirements, options?.auth);
|
|
29
|
+
const auth = options?.auth;
|
|
30
|
+
const operations = options?.operations;
|
|
31
|
+
return defineDynamicTools({
|
|
32
|
+
description: typeof spec === "string" && spec.startsWith("https://") ? `Operations from the OpenAPI document at ${spec}.` : "Operations from an OpenAPI document shipped with the app.",
|
|
33
|
+
...options?.requirements === void 0 ? {} : { requirements: options.requirements },
|
|
34
|
+
discover: (ctx) => openapiDiscover(spec, ctx, auth, operations),
|
|
35
|
+
call: (tool, input, ctx) => openapiCall(tool, input, ctx, auth)
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
fromOpenAPI
|
|
41
|
+
};
|