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.
Files changed (41) hide show
  1. package/dist/authoring/index.d.ts +222 -34
  2. package/dist/authoring/index.js +11 -1
  3. package/dist/{chunk-NFLNA2SC.js → chunk-4OZFMCTT.js} +7 -1
  4. package/dist/{chunk-LWKQDDLZ.js → chunk-A3H32P2J.js} +46 -1
  5. package/dist/chunk-F7GZYEAC.js +41 -0
  6. package/dist/{chunk-OGCPVWAZ.js → chunk-MUFMJRXR.js} +130 -13
  7. package/dist/chunk-S5KFP4JQ.js +20 -0
  8. package/dist/{chunk-646MS7DD.js → chunk-Y6LLTN7W.js} +7 -7
  9. package/dist/chunk-YUZ4TXOY.js +27 -0
  10. package/dist/http/index.d.ts +9 -0
  11. package/dist/http/index.js +6 -0
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.js +23 -1
  14. package/dist/manifest/contract.d.ts +8 -0
  15. package/dist/manifest/index.js +3 -3
  16. package/dist/mcp/client.d.ts +9 -0
  17. package/dist/mcp/index.d.ts +11 -0
  18. package/dist/mcp/index.js +7 -0
  19. package/dist/openapi/index.d.ts +14 -0
  20. package/dist/openapi/index.js +7 -0
  21. package/dist/openapi/mapper.d.ts +7 -0
  22. package/dist/runner/index.js +29 -15
  23. package/dist/runner/protocol.d.ts +18 -5
  24. package/dist/runner/protocol.js +5 -3
  25. package/dist/runtime/index.d.ts +42 -5
  26. package/dist/runtime/index.js +3 -1
  27. package/dist/workerd/index.d.ts +1 -1
  28. package/dist/workerd/index.js +1 -1
  29. package/package.json +13 -6
  30. package/src/authoring/index.ts +362 -44
  31. package/src/http/index.ts +26 -0
  32. package/src/index.ts +3 -0
  33. package/src/manifest/contract.ts +9 -0
  34. package/src/mcp/client.ts +59 -0
  35. package/src/mcp/index.ts +42 -0
  36. package/src/openapi/index.ts +70 -0
  37. package/src/openapi/mapper.ts +25 -0
  38. package/src/runner/index.ts +35 -12
  39. package/src/runner/protocol.ts +32 -7
  40. package/src/runtime/index.ts +209 -22
  41. package/src/workerd/index.ts +2 -0
@@ -1,5 +1,9 @@
1
1
  // src/runtime/index.ts
2
- var failure = (reason) => ({ ok: false, reason });
2
+ var failure = (kind, reason) => ({
3
+ ok: false,
4
+ kind,
5
+ reason
6
+ });
3
7
  var errorMessage = (error) => error instanceof Error ? error.message : String(error);
4
8
  var isJsonValue = (value) => {
5
9
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
@@ -48,6 +52,10 @@ var compileInputSchema = (input, where) => {
48
52
  };
49
53
  var requirementKey = Symbol.for("executor/apps/requirement");
50
54
  var requirementSpecOf = (value) => typeof value === "object" && value !== null && requirementKey in value ? value[requirementKey] : void 0;
55
+ var segmentOf = (file) => {
56
+ const name = file.slice(file.lastIndexOf("/") + 1);
57
+ return name.endsWith(".ts") ? name.slice(0, -3) : name;
58
+ };
51
59
  var canonicalJson = (value) => {
52
60
  const sortKeys = (node) => {
53
61
  if (Array.isArray(node)) return node.map(sortKeys);
@@ -100,6 +108,8 @@ var collectRegistry = (registry) => {
100
108
  for (const [file, summary] of registry.toolFiles) {
101
109
  if (summary.definitions > 1 && summary.hasUnnamedTool)
102
110
  problems.push(`${file}: multi-tool files must name every tool`);
111
+ if (registry.dynamic.has(file))
112
+ problems.push(`${file}: a file claims a dynamic tool set or defines tools, never both`);
103
113
  }
104
114
  const tools = [];
105
115
  if (app !== void 0) {
@@ -128,13 +138,43 @@ var collectRegistry = (registry) => {
128
138
  });
129
139
  }
130
140
  }
141
+ const dynamic = [];
142
+ const seenSegments = /* @__PURE__ */ new Map();
143
+ for (const [file, registered] of registry.dynamic) {
144
+ const segment = segmentOf(file);
145
+ const where = `${file}: dynamic tool set '${segment}'`;
146
+ const existing = seenSegments.get(segment);
147
+ if (existing !== void 0) {
148
+ problems.push(`${where}: segment already claimed by ${existing}`);
149
+ continue;
150
+ }
151
+ seenSegments.set(segment, file);
152
+ const requires = Object.entries(registered.spec.requirements ?? {}).flatMap(([role, requirement]) => {
153
+ const collected = collectRequirement(role, requirement, where);
154
+ return collected === void 0 ? [] : [collected];
155
+ }).sort((left, right) => left.role.localeCompare(right.role));
156
+ dynamic.push({
157
+ segment,
158
+ description: registered.spec.description,
159
+ requires,
160
+ file
161
+ });
162
+ }
131
163
  if (problems.length > 0 || app === void 0) return { problems };
132
164
  const services = [...claims.values()].sort(
133
165
  (left, right) => left.origin.localeCompare(right.origin)
134
166
  );
135
167
  const sortedTools = [...tools].sort((left, right) => left.address.localeCompare(right.address));
168
+ const sortedDynamic = [...dynamic].sort(
169
+ (left, right) => left.segment.localeCompare(right.segment)
170
+ );
136
171
  const appResult = { key: app.key, label: app.label, description: app.description };
137
- const manifest = { app: appResult, services, tools: sortedTools };
172
+ const manifest = {
173
+ app: appResult,
174
+ services,
175
+ tools: sortedTools,
176
+ dynamic: sortedDynamic
177
+ };
138
178
  return { problems: [], manifest, canonical: canonicalJson(manifest) };
139
179
  };
140
180
  var digestOf = async (canonical) => {
@@ -154,8 +194,8 @@ var manifestOf = async (registry) => {
154
194
  };
155
195
  };
156
196
  var standardValidateOf = (input) => "~standard" in input && typeof input["~standard"].validate === "function" ? input["~standard"].validate : void 0;
157
- var parseInput = async (spec, input) => {
158
- const validate = standardValidateOf(spec.input);
197
+ var parseInput = async (schema, input) => {
198
+ const validate = standardValidateOf(schema);
159
199
  if (validate === void 0)
160
200
  return { ok: false, reason: "input schema does not implement Standard Schema validate" };
161
201
  try {
@@ -170,21 +210,98 @@ var parseInput = async (spec, input) => {
170
210
  return { ok: false, reason: `input validation threw (${errorMessage(error)})` };
171
211
  }
172
212
  };
173
- var callTool = async (registry, name, input, ctx) => {
174
- const registered = registry.tools.get(name);
175
- if (registered === void 0) return failure("unknown tool");
176
- const parsed = await parseInput(registered.spec, input);
177
- if (!parsed.ok) return parsed;
213
+ var splitDynamicAddress = (address) => {
214
+ const slash = address.indexOf("/");
215
+ if (slash <= 0 || slash === address.length - 1) return void 0;
216
+ return { segment: address.slice(0, slash), name: address.slice(slash + 1) };
217
+ };
218
+ var dynamicFor = (registry, segment) => {
219
+ for (const [file, registered] of registry.dynamic)
220
+ if (segmentOf(file) === segment) return registered.spec;
221
+ return void 0;
222
+ };
223
+ var discoveredSpecs = /* @__PURE__ */ new WeakMap();
224
+ var callTool = async (registry, address, input, ctx, detail) => {
225
+ const dynamic = splitDynamicAddress(address);
226
+ if (dynamic === void 0) {
227
+ if (detail !== void 0)
228
+ return failure("handler", "a static tool takes no discovery detail");
229
+ const registered = registry.tools.get(address);
230
+ if (registered === void 0) return failure("handler", "unknown tool");
231
+ const parsed2 = await parseInput(registered.spec.input, input);
232
+ if (!parsed2.ok) return failure("input", parsed2.reason);
233
+ try {
234
+ const handler = registered.spec.handler;
235
+ return { ok: true, value: await handler(parsed2.value, ctx) };
236
+ } catch (error) {
237
+ return failure("handler", `handler failed (${errorMessage(error)})`);
238
+ }
239
+ }
240
+ if (detail === void 0)
241
+ return failure("handler", "a dynamic tool requires discovery detail");
242
+ const pair = dynamicFor(registry, dynamic.segment);
243
+ if (pair === void 0)
244
+ return failure("handler", `unknown dynamic tool set '${dynamic.segment}'`);
245
+ const discovered = discoveredSpecs.get(registry)?.get(dynamic.segment)?.get(dynamic.name);
246
+ if (discovered === void 0)
247
+ return failure(
248
+ "input",
249
+ `dynamic tool '${dynamic.name}' has no compiled discovery descriptor`
250
+ );
251
+ const parsed = await parseInput(discovered.input, input);
252
+ if (!parsed.ok) return failure("input", parsed.reason);
178
253
  try {
179
- const handler = registered.spec.handler;
180
- return { ok: true, value: await handler(parsed.value, ctx) };
254
+ const call = pair.call;
255
+ return {
256
+ ok: true,
257
+ value: await call({ name: dynamic.name, detail }, parsed.value, ctx)
258
+ };
259
+ } catch (error) {
260
+ return failure("handler", `dynamic call failed (${errorMessage(error)})`);
261
+ }
262
+ };
263
+ var discoverTool = async (registry, segment, ctx) => {
264
+ const pair = dynamicFor(registry, segment);
265
+ if (pair === void 0)
266
+ return { ok: false, reason: `unknown dynamic tool set '${segment}'` };
267
+ discoveredSpecs.get(registry)?.delete(segment);
268
+ let emitted;
269
+ try {
270
+ const discover = pair.discover;
271
+ emitted = await discover(ctx);
181
272
  } catch (error) {
182
- return failure(`handler failed (${errorMessage(error)})`);
273
+ return { ok: false, reason: `discover failed (${errorMessage(error)})` };
274
+ }
275
+ const tools = [];
276
+ const live = /* @__PURE__ */ new Map();
277
+ for (const tool of emitted) {
278
+ if (live.has(tool.name))
279
+ return { ok: false, reason: `discover emitted duplicate tool '${tool.name}'` };
280
+ const compiled = compileInputSchema(tool.input, `${segment}/${tool.name}`);
281
+ if ("problem" in compiled) return { ok: false, reason: compiled.problem };
282
+ live.set(tool.name, tool);
283
+ tools.push({
284
+ segment,
285
+ name: tool.name,
286
+ descriptor: {
287
+ description: tool.description,
288
+ inputSchema: compiled.value,
289
+ annotations: {
290
+ ...tool.annotations?.readOnly === void 0 ? {} : { readOnly: tool.annotations.readOnly },
291
+ ...tool.annotations?.destructive === void 0 ? {} : { destructive: tool.annotations.destructive }
292
+ }
293
+ },
294
+ detail: tool.detail ?? null
295
+ });
183
296
  }
297
+ const registryDiscoveries = discoveredSpecs.get(registry) ?? /* @__PURE__ */ new Map();
298
+ registryDiscoveries.set(segment, live);
299
+ discoveredSpecs.set(registry, registryDiscoveries);
300
+ return { ok: true, value: tools.sort((left, right) => left.name.localeCompare(right.name)) };
184
301
  };
185
- var discoverTool = async (_registry, _name, _binding) => failure("no dynamic tools yet");
186
302
 
187
303
  export {
304
+ compileInputSchema,
188
305
  manifestOf,
189
306
  callTool,
190
307
  discoverTool
@@ -0,0 +1,20 @@
1
+ // src/http/index.ts
2
+ var authHeaders = (role) => {
3
+ switch (role.kind) {
4
+ case "bearer":
5
+ case "oauth":
6
+ return { authorization: `Bearer ${role.token}` };
7
+ case "basic":
8
+ return { authorization: `Basic ${base64(`${role.username}:${role.password}`)}` };
9
+ }
10
+ };
11
+ var base64 = (value) => {
12
+ const bytes = new TextEncoder().encode(value);
13
+ let binary = "";
14
+ for (const byte of bytes) binary += String.fromCharCode(byte);
15
+ return btoa(binary);
16
+ };
17
+
18
+ export {
19
+ authHeaders
20
+ };
@@ -1,15 +1,15 @@
1
1
  import {
2
- __enterFile,
3
- __leaveFile,
4
- newRegistry,
5
- setActiveRegistry
6
- } from "./chunk-LWKQDDLZ.js";
2
+ manifestOf
3
+ } from "./chunk-MUFMJRXR.js";
7
4
  import {
8
5
  PublishError
9
6
  } from "./chunk-B7NEUIJL.js";
10
7
  import {
11
- manifestOf
12
- } from "./chunk-OGCPVWAZ.js";
8
+ __enterFile,
9
+ __leaveFile,
10
+ newRegistry,
11
+ setActiveRegistry
12
+ } from "./chunk-A3H32P2J.js";
13
13
 
14
14
  // src/manifest/index.ts
15
15
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -0,0 +1,27 @@
1
+ import {
2
+ defineDynamicTools
3
+ } from "./chunk-A3H32P2J.js";
4
+
5
+ // src/mcp/client.ts
6
+ var mcpDiscover = async (_endpoint, _ctx, _auth, _operations) => {
7
+ throw new Error("mcp client not built yet");
8
+ };
9
+ var mcpCall = async (_endpoint, _tool, _input, _ctx, _auth) => {
10
+ throw new Error("mcp client not built yet");
11
+ };
12
+
13
+ // src/mcp/index.ts
14
+ function fromMCP(endpoint, options) {
15
+ const auth = options?.auth;
16
+ const operations = options?.operations;
17
+ return defineDynamicTools({
18
+ description: `Tools served by the MCP server at ${endpoint}.`,
19
+ ...options?.requirements === void 0 ? {} : { requirements: options.requirements },
20
+ discover: (ctx) => mcpDiscover(endpoint, ctx, auth, operations),
21
+ call: (tool, input, ctx) => mcpCall(endpoint, tool.name, input, ctx, auth)
22
+ });
23
+ }
24
+
25
+ export {
26
+ fromMCP
27
+ };
@@ -0,0 +1,9 @@
1
+ /** HTTP credential placement helpers for kind-bearing connected roles. */
2
+ import type { RoleMaterial } from "../authoring/index";
3
+ export type HttpSpendableRole = Extract<RoleMaterial, {
4
+ kind: "bearer" | "oauth" | "basic";
5
+ }>;
6
+ /** Build the protocol-defined Authorization header for a connected role. */
7
+ export declare const authHeaders: (role: HttpSpendableRole) => {
8
+ readonly authorization: string;
9
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ authHeaders
3
+ } from "../chunk-S5KFP4JQ.js";
4
+ export {
5
+ authHeaders
6
+ };
package/dist/index.d.ts CHANGED
@@ -1 +1,4 @@
1
1
  export * from "./authoring/index";
2
+ export * from "./http/index";
3
+ export * from "./mcp/index";
4
+ export * from "./openapi/index";
package/dist/index.js CHANGED
@@ -1,23 +1,45 @@
1
+ import {
2
+ fromOpenAPI
3
+ } from "./chunk-F7GZYEAC.js";
4
+ import {
5
+ authHeaders
6
+ } from "./chunk-S5KFP4JQ.js";
7
+ import {
8
+ fromMCP
9
+ } from "./chunk-YUZ4TXOY.js";
1
10
  import {
2
11
  __enterFile,
3
12
  __leaveFile,
13
+ basic,
14
+ bearer,
4
15
  defineApp,
16
+ defineDynamicTools,
5
17
  defineTool,
18
+ dynamicSpecOf,
6
19
  newRegistry,
7
20
  oauth,
21
+ recordAuthoringProblem,
8
22
  requirementSpecOf,
9
23
  secrets,
10
24
  service,
11
25
  setActiveRegistry,
12
26
  toolSpecOf
13
- } from "./chunk-LWKQDDLZ.js";
27
+ } from "./chunk-A3H32P2J.js";
14
28
  export {
15
29
  __enterFile,
16
30
  __leaveFile,
31
+ authHeaders,
32
+ basic,
33
+ bearer,
17
34
  defineApp,
35
+ defineDynamicTools,
18
36
  defineTool,
37
+ dynamicSpecOf,
38
+ fromMCP,
39
+ fromOpenAPI,
19
40
  newRegistry,
20
41
  oauth,
42
+ recordAuthoringProblem,
21
43
  requirementSpecOf,
22
44
  secrets,
23
45
  service,
@@ -32,6 +32,13 @@ export interface ManifestTool {
32
32
  readonly requires: readonly CollectedRequirement[];
33
33
  readonly file: string;
34
34
  }
35
+ /** A dynamic address segment projected without endpoint or specification data. */
36
+ export interface ManifestDynamic {
37
+ readonly segment: string;
38
+ readonly description: string;
39
+ readonly requires: readonly CollectedRequirement[];
40
+ readonly file: string;
41
+ }
35
42
  /** The deterministic public description of an executor app. */
36
43
  export interface AppManifestResult {
37
44
  readonly digest: string;
@@ -42,6 +49,7 @@ export interface AppManifestResult {
42
49
  };
43
50
  readonly services: readonly CollectedClaim[];
44
51
  readonly tools: readonly ManifestTool[];
52
+ readonly dynamic: readonly ManifestDynamic[];
45
53
  }
46
54
  declare const PublishError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
47
55
  readonly _tag: "PublishError";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  loadApp,
3
3
  manifest
4
- } from "../chunk-646MS7DD.js";
5
- import "../chunk-LWKQDDLZ.js";
4
+ } from "../chunk-Y6LLTN7W.js";
5
+ import "../chunk-MUFMJRXR.js";
6
6
  import {
7
7
  JsonSchemaObject,
8
8
  PublishError
9
9
  } from "../chunk-B7NEUIJL.js";
10
- import "../chunk-OGCPVWAZ.js";
10
+ import "../chunk-A3H32P2J.js";
11
11
  export {
12
12
  JsonSchemaObject,
13
13
  PublishError,
@@ -0,0 +1,9 @@
1
+ /** Stub-contract MCP client used by the fromMCP dynamic pair. */
2
+ import type { AuthComposeFn, DiscoveredToolSpec, OperationSelection } from "../authoring/index";
3
+ /** Normalize authored placement, or apply MCP's bearer default. */
4
+ export declare const composePlacement: (auth: AuthComposeFn<never> | undefined, ctx: unknown) => {
5
+ headers: Headers;
6
+ searchParams: URLSearchParams;
7
+ };
8
+ export declare const mcpDiscover: (_endpoint: string, _ctx: unknown, _auth: AuthComposeFn<never> | undefined, _operations: OperationSelection | undefined) => Promise<readonly DiscoveredToolSpec[]>;
9
+ export declare const mcpCall: (_endpoint: string, _tool: string, _input: unknown, _ctx: unknown, _auth: AuthComposeFn<never> | undefined) => Promise<unknown>;
@@ -0,0 +1,11 @@
1
+ /** fromMCP sugar over the authored dynamic-tools primitive. */
2
+ import { type AuthComposeFn, type DynamicToolSet, type OperationSelection, type Requirement } from "../authoring/index";
3
+ export type FromMCPOptions<Reqs extends Readonly<Record<string, Requirement>>> = {
4
+ readonly requirements: Reqs;
5
+ readonly auth?: AuthComposeFn<NoInfer<Reqs>>;
6
+ readonly operations?: OperationSelection;
7
+ };
8
+ export declare function fromMCP<const Reqs extends Readonly<Record<string, Requirement>>>(endpoint: string, options: FromMCPOptions<Reqs>): DynamicToolSet;
9
+ export declare function fromMCP(endpoint: string, options?: {
10
+ readonly operations?: OperationSelection;
11
+ }): DynamicToolSet;
@@ -0,0 +1,7 @@
1
+ import {
2
+ fromMCP
3
+ } from "../chunk-YUZ4TXOY.js";
4
+ import "../chunk-A3H32P2J.js";
5
+ export {
6
+ fromMCP
7
+ };
@@ -0,0 +1,14 @@
1
+ /** fromOpenAPI sugar over the authored dynamic-tools primitive. */
2
+ import { type AuthComposeFn, type DynamicToolSet, type OperationSelection, type Requirement, type RequiresAuthCompose } from "../authoring/index";
3
+ export type FromOpenAPIOptions<Reqs extends Readonly<Record<string, Requirement>>> = {
4
+ readonly requirements: Reqs;
5
+ readonly auth?: AuthComposeFn<NoInfer<Reqs>>;
6
+ readonly operations?: OperationSelection;
7
+ } & (RequiresAuthCompose<Reqs> extends true ? {
8
+ readonly auth: AuthComposeFn<NoInfer<Reqs>>;
9
+ } : unknown);
10
+ export type OpenAPIDocumentInput = string | Readonly<Record<string, unknown>>;
11
+ export declare function fromOpenAPI<const Reqs extends Readonly<Record<string, Requirement>>>(spec: OpenAPIDocumentInput, options: FromOpenAPIOptions<Reqs>): DynamicToolSet;
12
+ export declare function fromOpenAPI(spec: OpenAPIDocumentInput, options?: {
13
+ readonly operations?: OperationSelection;
14
+ }): DynamicToolSet;
@@ -0,0 +1,7 @@
1
+ import {
2
+ fromOpenAPI
3
+ } from "../chunk-F7GZYEAC.js";
4
+ import "../chunk-A3H32P2J.js";
5
+ export {
6
+ fromOpenAPI
7
+ };
@@ -0,0 +1,7 @@
1
+ /** Stub-contract OpenAPI discovery and call mapper. */
2
+ import type { AuthComposeFn, DiscoveredToolSpec, OperationSelection } from "../authoring/index";
3
+ export declare const openapiDiscover: (_spec: string | Readonly<Record<string, unknown>>, _ctx: unknown, _auth: AuthComposeFn<never> | undefined, _operations: OperationSelection | undefined) => Promise<readonly DiscoveredToolSpec[]>;
4
+ export declare const openapiCall: (_tool: {
5
+ readonly name: string;
6
+ readonly detail: unknown;
7
+ }, _input: unknown, _ctx: unknown, _auth: AuthComposeFn<never> | undefined) => Promise<unknown>;
@@ -1,15 +1,16 @@
1
1
  import {
2
2
  loadApp
3
- } from "../chunk-646MS7DD.js";
4
- import "../chunk-LWKQDDLZ.js";
5
- import "../chunk-B7NEUIJL.js";
6
- import {
7
- CallError
8
- } from "../chunk-NFLNA2SC.js";
3
+ } from "../chunk-Y6LLTN7W.js";
9
4
  import {
10
5
  callTool,
11
6
  discoverTool
12
- } from "../chunk-OGCPVWAZ.js";
7
+ } from "../chunk-MUFMJRXR.js";
8
+ import "../chunk-B7NEUIJL.js";
9
+ import {
10
+ CallError,
11
+ DiscoverError
12
+ } from "../chunk-4OZFMCTT.js";
13
+ import "../chunk-A3H32P2J.js";
13
14
 
14
15
  // src/runner/index.ts
15
16
  import { Effect } from "effect";
@@ -28,25 +29,38 @@ var localRunner = (appDir) => {
28
29
  const registryFor = (target) => loaded().pipe(
29
30
  Effect.map(({ registry }) => registry),
30
31
  Effect.mapError(
31
- (error) => new CallError({ target, reason: `app failed to load (${error.message})` })
32
+ (error) => new CallError({
33
+ target,
34
+ kind: "handler",
35
+ reason: `app failed to load (${error.message})`
36
+ })
32
37
  )
33
38
  );
34
- const settle = (target, outcome) => outcome.ok ? Effect.succeed(outcome.value) : Effect.fail(new CallError({ target, reason: outcome.reason }));
39
+ const settle = (target, outcome) => outcome.ok ? Effect.succeed(outcome.value) : Effect.fail(new CallError({
40
+ target,
41
+ kind: outcome.kind,
42
+ reason: outcome.reason
43
+ }));
44
+ const settleDiscovery = (segment, outcome) => outcome.ok ? Effect.succeed(outcome.value) : Effect.fail(new DiscoverError({ segment, reason: outcome.reason }));
35
45
  return {
36
46
  manifest: () => Effect.map(loaded(), ({ result }) => result),
37
- call: (name, input, ctx) => registryFor(name).pipe(
38
- Effect.flatMap((registry) => Effect.promise(() => callTool(registry, name, input, ctx))),
39
- Effect.flatMap((outcome) => settle(name, outcome))
47
+ call: (address, input, ctx, detail) => registryFor(address).pipe(
48
+ Effect.flatMap(
49
+ (registry) => Effect.promise(() => callTool(registry, address, input, ctx, detail))
50
+ ),
51
+ Effect.flatMap((outcome) => settle(address, outcome))
40
52
  ),
41
- discover: (name, binding) => registryFor(name).pipe(
53
+ discover: (segment, ctx) => registryFor(segment).pipe(
54
+ Effect.mapError((error) => new DiscoverError({ segment, reason: error.reason })),
42
55
  Effect.flatMap(
43
- (registry) => Effect.promise(() => discoverTool(registry, name, binding))
56
+ (registry) => Effect.promise(() => discoverTool(registry, segment, ctx))
44
57
  ),
45
- Effect.flatMap((outcome) => settle(name, outcome))
58
+ Effect.flatMap((outcome) => settleDiscovery(segment, outcome))
46
59
  )
47
60
  };
48
61
  };
49
62
  export {
50
63
  CallError,
64
+ DiscoverError,
51
65
  localRunner
52
66
  };
@@ -1,13 +1,26 @@
1
1
  import { type Effect, FileSystem } from "effect";
2
2
  import type { AppManifestResult, PublishError } from "../manifest/contract";
3
- import type { ToolCtx } from "../runtime/index";
4
- export type { ToolCtx, ToolCtxEntry } from "../runtime/index";
3
+ import type { CallFailureKind, DiscoveredTool, ToolCtx } from "../runtime/index";
4
+ export type { DiscoveredTool, ToolCtx, ToolCtxEntry, ToolDescriptor, } from "../runtime/index";
5
+ /** Which invocation phase failed. */
6
+ export type CallErrorKind = CallFailureKind;
5
7
  declare const CallError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
6
8
  readonly _tag: "CallError";
7
9
  } & Readonly<A>;
8
- /** A runner operation failure associated with its target. */
10
+ /** A runner operation failure associated with its target and phase. */
9
11
  export declare class CallError extends CallError_base<{
10
12
  readonly target: string;
13
+ readonly kind: CallErrorKind;
14
+ readonly reason: string;
15
+ }> {
16
+ get message(): string;
17
+ }
18
+ declare const DiscoverError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
19
+ readonly _tag: "DiscoverError";
20
+ } & Readonly<A>;
21
+ /** A discovery failure associated with one dynamic segment. */
22
+ export declare class DiscoverError extends DiscoverError_base<{
23
+ readonly segment: string;
11
24
  readonly reason: string;
12
25
  }> {
13
26
  get message(): string;
@@ -15,6 +28,6 @@ export declare class CallError extends CallError_base<{
15
28
  /** The platform protocol implemented by an app execution environment. */
16
29
  export interface AppRunner {
17
30
  manifest(): Effect.Effect<AppManifestResult, PublishError, FileSystem.FileSystem>;
18
- call(name: string, input: unknown, ctx: ToolCtx): Effect.Effect<unknown, CallError, FileSystem.FileSystem>;
19
- discover(name: string, binding: unknown): Effect.Effect<unknown, CallError, FileSystem.FileSystem>;
31
+ call(address: string, input: unknown, ctx: ToolCtx, detail?: unknown): Effect.Effect<unknown, CallError, FileSystem.FileSystem>;
32
+ discover(segment: string, ctx: ToolCtx): Effect.Effect<readonly DiscoveredTool[], DiscoverError, FileSystem.FileSystem>;
20
33
  }
@@ -1,6 +1,8 @@
1
1
  import {
2
- CallError
3
- } from "../chunk-NFLNA2SC.js";
2
+ CallError,
3
+ DiscoverError
4
+ } from "../chunk-4OZFMCTT.js";
4
5
  export {
5
- CallError
6
+ CallError,
7
+ DiscoverError
6
8
  };
@@ -12,11 +12,14 @@
12
12
  * and workerd all provide.
13
13
  */
14
14
  import type { Registry } from "../authoring/index";
15
- import type { AppManifestResult } from "../manifest/contract";
15
+ import type { AppManifestResult, JsonSchemaObject } from "../manifest/contract";
16
16
  /** The capability exposed to one tool requirement role. */
17
17
  export interface ToolCtxEntry {
18
18
  readonly grant: string;
19
+ readonly kind: "bearer" | "basic" | "secrets" | "oauth";
19
20
  readonly token?: string;
21
+ readonly username?: string;
22
+ readonly password?: string;
20
23
  readonly secrets?: Readonly<Record<string, string>>;
21
24
  fetch(path: string, init?: RequestInit): Promise<Response>;
22
25
  }
@@ -30,17 +33,51 @@ export type ManifestOutcome = {
30
33
  readonly ok: false;
31
34
  readonly problems: readonly string[];
32
35
  };
36
+ /** Which invocation phase failed. */
37
+ export type CallFailureKind = "input" | "handler";
33
38
  /** One tool invocation's result envelope. */
34
39
  export type CallOutcome = {
35
40
  readonly ok: true;
36
41
  readonly value: unknown;
37
42
  } | {
38
43
  readonly ok: false;
44
+ readonly kind: CallFailureKind;
39
45
  readonly reason: string;
40
46
  };
47
+ /** Agent-facing descriptor compiled from one discovery result. */
48
+ export interface ToolDescriptor {
49
+ readonly description: string;
50
+ readonly inputSchema: JsonSchemaObject;
51
+ readonly annotations: {
52
+ readonly readOnly?: boolean;
53
+ readonly destructive?: boolean;
54
+ };
55
+ }
56
+ /** One tool emitted by a dynamic segment discovery. */
57
+ export interface DiscoveredTool {
58
+ readonly segment: string;
59
+ readonly name: string;
60
+ readonly descriptor: ToolDescriptor;
61
+ readonly detail: unknown;
62
+ }
63
+ /** One dynamic discovery result envelope. */
64
+ export type DiscoverOutcome = {
65
+ readonly ok: true;
66
+ readonly value: readonly DiscoveredTool[];
67
+ } | {
68
+ readonly ok: false;
69
+ readonly reason: string;
70
+ };
71
+ type InputSchemaCompilation = {
72
+ readonly value: JsonSchemaObject;
73
+ } | {
74
+ readonly problem: string;
75
+ };
76
+ export declare const compileInputSchema: (input: object, where: string) => InputSchemaCompilation;
41
77
  /** Project a loaded registry into the app's deterministic manifest. */
42
78
  export declare const manifestOf: (registry: Registry) => Promise<ManifestOutcome>;
43
- /** Validate input and run one registered tool's handler. */
44
- export declare const callTool: (registry: Registry, name: string, input: unknown, ctx: ToolCtx) => Promise<CallOutcome>;
45
- /** Discover one dynamic tool set's current segment. Unbuilt: always fails. */
46
- export declare const discoverTool: (_registry: Registry, _name: string, _binding: unknown) => Promise<CallOutcome>;
79
+ /** Validate input and run one static or dynamic tool handler. */
80
+ export declare const callTool: (registry: Registry, address: string, input: unknown, ctx: ToolCtx, detail?: unknown) => Promise<CallOutcome>;
81
+ /** Discover and compile one dynamic segment. */
82
+ export declare const discoverTool: (registry: Registry, segment: string, ctx: ToolCtx) => Promise<DiscoverOutcome>;
83
+ export {};
@@ -1,10 +1,12 @@
1
1
  import {
2
2
  callTool,
3
+ compileInputSchema,
3
4
  discoverTool,
4
5
  manifestOf
5
- } from "../chunk-OGCPVWAZ.js";
6
+ } from "../chunk-MUFMJRXR.js";
6
7
  export {
7
8
  callTool,
9
+ compileInputSchema,
8
10
  discoverTool,
9
11
  manifestOf
10
12
  };
@@ -4,4 +4,4 @@
4
4
  * exposes these verbs over RPC; the logic itself lives in ../runtime
5
5
  * and is identical to what the local runner executes. @internal
6
6
  */
7
- export { callTool, discoverTool, manifestOf, type CallOutcome, type ManifestOutcome, type ToolCtx, type ToolCtxEntry, } from "../runtime/index";
7
+ export { callTool, discoverTool, manifestOf, type CallOutcome, type DiscoverOutcome, type DiscoveredTool, type ManifestOutcome, type ToolCtx, type ToolCtxEntry, } from "../runtime/index";