@nylorun/agents 0.9.0-beta → 0.11.0-beta

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 (52) hide show
  1. package/CHANGELOG.md +165 -0
  2. package/README.md +296 -77
  3. package/dist/a2a/handler.d.ts +59 -0
  4. package/dist/a2a/handler.js +178 -0
  5. package/dist/a2a/index.d.ts +8 -0
  6. package/dist/a2a/index.js +7 -0
  7. package/dist/access.d.ts +101 -0
  8. package/dist/access.js +111 -0
  9. package/dist/action-handler.d.ts +63 -0
  10. package/dist/action-handler.js +279 -0
  11. package/dist/ag-ui/handler.d.ts +12 -4
  12. package/dist/ag-ui/handler.js +87 -281
  13. package/dist/ag-ui/index.d.ts +2 -1
  14. package/dist/ag-ui/index.js +2 -1
  15. package/dist/browser.d.ts +97 -0
  16. package/dist/browser.js +277 -0
  17. package/dist/client.d.ts +3 -230
  18. package/dist/client.js +3 -361
  19. package/dist/connection.d.ts +4 -4
  20. package/dist/connection.js +16 -25
  21. package/dist/delivery-token.d.ts +62 -0
  22. package/dist/delivery-token.js +159 -0
  23. package/dist/execute-action.d.ts +6 -0
  24. package/dist/execute-action.js +24 -0
  25. package/dist/http.d.ts +34 -3
  26. package/dist/http.js +68 -16
  27. package/dist/index.d.ts +10 -8
  28. package/dist/index.js +4 -4
  29. package/dist/sandbox/client.d.ts +4 -5
  30. package/dist/sandbox/client.js +4 -8
  31. package/dist/sandbox/index.d.ts +0 -2
  32. package/dist/sandbox/index.js +0 -1
  33. package/dist/served-definitions.d.ts +20 -0
  34. package/dist/served-definitions.js +100 -0
  35. package/dist/session-client.d.ts +282 -0
  36. package/dist/session-client.js +375 -0
  37. package/dist/sse.js +12 -0
  38. package/dist/studio-embed.d.ts +9 -0
  39. package/dist/studio-embed.js +8 -0
  40. package/dist/token-endpoint.d.ts +23 -0
  41. package/dist/token-endpoint.js +30 -0
  42. package/package.json +15 -8
  43. package/dist/ag-ui/history.d.ts +0 -7
  44. package/dist/ag-ui/history.js +0 -60
  45. package/dist/ag-ui/sse.d.ts +0 -9
  46. package/dist/ag-ui/sse.js +0 -7
  47. package/dist/ag-ui/translate.d.ts +0 -38
  48. package/dist/ag-ui/translate.js +0 -222
  49. package/dist/derived-credentials.d.ts +0 -5
  50. package/dist/derived-credentials.js +0 -17
  51. package/dist/executor.d.ts +0 -20
  52. package/dist/executor.js +0 -417
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Verifies the delivery token on a request the Runtime sends to an Action endpoint: an ES256
3
+ * JWT signed with the Tenant's current signing key (design: Action endpoints §8.1). WebCrypto
4
+ * only, so the SDK takes no JWT dependency: a JWS ES256 signature is the raw `r || s` pair
5
+ * WebCrypto's ECDSA verifies.
6
+ */
7
+ import { PROTOCOL_HEADER, PROTOCOL_VERSION, isTenantId } from "@nylorun/core/compatibility";
8
+ import { DELIVERY_TOKEN_TYPE, subjectTokenIssuer } from "@nylorun/core/contracts";
9
+ /** The issuer prefix of a Tenant's tokens: `urn:nylorun:tenant:<tenantId>`. */
10
+ const ISSUER_PREFIX = subjectTokenIssuer("");
11
+ /** Why a delivery was refused; `code` is sent back to the Runtime. */
12
+ export class DeliveryVerificationError extends Error {
13
+ code;
14
+ name = "DeliveryVerificationError";
15
+ constructor(code, message) {
16
+ super(message);
17
+ this.code = code;
18
+ }
19
+ }
20
+ /** Clock skew tolerated on `iat` and `exp`, in seconds. */
21
+ const SKEW_SECONDS = 30;
22
+ const FORBIDDEN_HEADERS = ["jku", "jwk", "x5u", "x5c", "x5t", "x5t#S256", "crit"];
23
+ /** The largest token accepted: well above a real one, well below a request limit. */
24
+ const MAX_TOKEN_LENGTH = 4096;
25
+ /**
26
+ * Verifies `token` against `body`. The keys are the installation's, so a valid signature already
27
+ * binds the issuer to its one Tenant: any `urn:nylorun:tenant:<id>` issuer is accepted (and
28
+ * returned in `iss`) unless `tenantId` names the one expected.
29
+ */
30
+ export async function verifyDeliveryToken(token, options) {
31
+ if (!token)
32
+ throw new DeliveryVerificationError("signature_missing", "No delivery token");
33
+ const parts = token.length <= MAX_TOKEN_LENGTH ? token.split(".") : [];
34
+ if (parts.length !== 3)
35
+ throw invalid("Not a compact JWS");
36
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
37
+ const header = json(encodedHeader);
38
+ if (header.alg !== "ES256" ||
39
+ header.typ !== DELIVERY_TOKEN_TYPE ||
40
+ typeof header.kid !== "string" ||
41
+ FORBIDDEN_HEADERS.some((name) => name in header))
42
+ throw invalid("Unexpected token header");
43
+ const key = await options.keys(header.kid);
44
+ if (!key)
45
+ throw new DeliveryVerificationError("key_unknown", `Unknown signing key ${header.kid}`);
46
+ const signed = await crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, bytes(base64url(encodedSignature)), new TextEncoder().encode(`${encodedHeader}.${encodedPayload}`));
47
+ if (!signed)
48
+ throw invalid("Bad signature");
49
+ const claims = json(encodedPayload);
50
+ if (typeof claims.iss !== "string" ||
51
+ typeof claims.aud !== "string" ||
52
+ typeof claims.sub !== "string" ||
53
+ typeof claims.agt !== "string" ||
54
+ !Number.isInteger(claims.gen) ||
55
+ typeof claims.bdy !== "string" ||
56
+ typeof claims.iat !== "number" ||
57
+ typeof claims.exp !== "number" ||
58
+ typeof claims.jti !== "string")
59
+ throw invalid("Missing claims");
60
+ if (!claims.iss.startsWith(ISSUER_PREFIX) ||
61
+ !isTenantId(claims.iss.slice(ISSUER_PREFIX.length)))
62
+ throw invalid("The token was not issued by a Tenant");
63
+ if (options.tenantId !== undefined && claims.iss !== subjectTokenIssuer(options.tenantId))
64
+ throw invalid("The token is for another Tenant");
65
+ if (options.audience !== undefined && claims.aud !== options.audience)
66
+ throw invalid(`The token is for ${claims.aud}, not ${options.audience}`);
67
+ const now = (options.now ?? Date.now()) / 1000;
68
+ if (claims.exp < now - SKEW_SECONDS || claims.iat > now + SKEW_SECONDS)
69
+ throw new DeliveryVerificationError("token_expired", "The delivery token has expired");
70
+ if (claims.bdy !== (await bodyHash(options.body)))
71
+ throw invalid("The body does not match the token");
72
+ return claims;
73
+ }
74
+ /** base64url SHA-256 of `body`: the token's `bdy` claim. */
75
+ export async function bodyHash(body) {
76
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes(body)));
77
+ return Buffer.from(digest).toString("base64url");
78
+ }
79
+ /**
80
+ * The Tenant's public keys, fetched from `GET /v1/access/jwks` and cached by `kid`. An
81
+ * unknown `kid` refetches once, at most every `refetchMs`, so forged tokens cannot make the
82
+ * endpoint call the Runtime on every request. Concurrent lookups share one in-flight fetch.
83
+ */
84
+ export class JwksCache {
85
+ source;
86
+ refetchMs;
87
+ keys = new Map();
88
+ lastFetch = 0;
89
+ pending;
90
+ constructor(source, refetchMs = 5000) {
91
+ this.source = source;
92
+ this.refetchMs = refetchMs;
93
+ }
94
+ lookup = async (kid) => {
95
+ const known = this.keys.get(kid);
96
+ if (known)
97
+ return known;
98
+ // Wait for an in-flight fetch: stamping the cooldown at the start of `load` used
99
+ // to make a concurrent ping (register + smoke, or tsx watch restart) answer
100
+ // `key_unknown` before the keys arrived.
101
+ if (this.pending) {
102
+ await this.pending;
103
+ return this.keys.get(kid);
104
+ }
105
+ if (Date.now() - this.lastFetch < this.refetchMs && this.lastFetch > 0)
106
+ return undefined;
107
+ await (this.pending ??= this.load().finally(() => (this.pending = undefined)));
108
+ return this.keys.get(kid);
109
+ };
110
+ async load() {
111
+ const keys = "keys" in this.source ? this.source.keys : await this.fetchKeys(this.source);
112
+ this.lastFetch = Date.now();
113
+ for (const jwk of keys) {
114
+ const kid = jwk.kid;
115
+ if (typeof kid !== "string" || jwk.kty !== "EC" || jwk.crv !== "P-256")
116
+ continue;
117
+ if (this.keys.has(kid))
118
+ continue;
119
+ this.keys.set(kid, await crypto.subtle.importKey("jwk", { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y }, { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"]));
120
+ }
121
+ }
122
+ async fetchKeys(source) {
123
+ const headers = {
124
+ [PROTOCOL_HEADER]: String(PROTOCOL_VERSION),
125
+ };
126
+ if (source.key)
127
+ headers.Authorization = `Bearer ${source.key}`;
128
+ const response = await (source.fetch ?? globalThis.fetch)(`${source.url.replace(/\/$/, "")}/v1/access/jwks`, { headers, redirect: "error", signal: AbortSignal.timeout(10_000) });
129
+ if (!response.ok) {
130
+ await response.body?.cancel();
131
+ throw new Error(`The Runtime answered ${response.status} for its public keys (GET /v1/access/jwks)`);
132
+ }
133
+ const body = (await response.json());
134
+ return Array.isArray(body.keys) ? body.keys : [];
135
+ }
136
+ }
137
+ function invalid(message) {
138
+ return new DeliveryVerificationError("signature_invalid", message);
139
+ }
140
+ function base64url(value) {
141
+ return new Uint8Array(Buffer.from(value, "base64url"));
142
+ }
143
+ /** A copy backed by a plain `ArrayBuffer`, which WebCrypto's types require. */
144
+ function bytes(value) {
145
+ const copy = new Uint8Array(value.byteLength);
146
+ copy.set(value);
147
+ return copy;
148
+ }
149
+ function json(segment) {
150
+ try {
151
+ const value = JSON.parse(Buffer.from(segment, "base64url").toString("utf8"));
152
+ if (value && typeof value === "object" && !Array.isArray(value))
153
+ return value;
154
+ }
155
+ catch {
156
+ /* fall through */
157
+ }
158
+ throw invalid("Malformed token");
159
+ }
@@ -8,3 +8,9 @@ export type ExecuteActionOptions = {
8
8
  };
9
9
  /** Executes code only after a host-issued claim. No engine dependency. */
10
10
  export declare function executeAction(action: Action, root: ExecutableDefinition, signal: AbortSignal, options?: ExecuteActionOptions): Promise<ActionOutcome>;
11
+ /**
12
+ * True when `action` runs a tool marked `background` (`ToolDefinition.background`): an Action
13
+ * endpoint answers its delivery at once and posts the outcome later. False for anything it
14
+ * cannot find; `executeAction` reports those.
15
+ */
16
+ export declare function runsInBackground(action: Action, root: ExecutableDefinition): boolean;
@@ -42,6 +42,30 @@ export async function executeAction(action, root, signal, options = {}) {
42
42
  const tool = normalizeToolDefinition(raw);
43
43
  return runTool(action, tool, ref, signal, sandbox);
44
44
  }
45
+ /**
46
+ * True when `action` runs a tool marked `background` (`ToolDefinition.background`): an Action
47
+ * endpoint answers its delivery at once and posts the outcome later. False for anything it
48
+ * cannot find; `executeAction` reports those.
49
+ */
50
+ export function runsInBackground(action, root) {
51
+ if (action.kind !== "tool")
52
+ return false;
53
+ try {
54
+ if (isBuiltWorkflow(root)) {
55
+ const key = action.key;
56
+ const impl = typeof key === "string" ? root.getBinding().nodes[key] : undefined;
57
+ return impl?.kind === "tool" && impl.tool.background === true;
58
+ }
59
+ if (!("capabilityId" in action))
60
+ return false;
61
+ const agent = action.agent ? delegatedAgent(root, action.agent.id) : root;
62
+ const raw = implementationsFor(agent)[action.capabilityId]?.tools?.[action.toolName];
63
+ return raw !== undefined && normalizeToolDefinition(raw).background === true;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
45
69
  async function executeWorkflowTool(action, binding, signal, sandbox) {
46
70
  const impl = binding.nodes[action.key];
47
71
  if (!impl || impl.kind !== "tool")
package/dist/http.d.ts CHANGED
@@ -1,9 +1,25 @@
1
1
  import { type Compatibility, type ProtocolRange } from "@nylorun/core/compatibility";
2
+ /**
3
+ * Subject tokens for a client that holds no Tenant key (a browser or an app; Host feature
4
+ * `subject-tokens`). `get` returns a current token and may fetch a new one; `invalidate`
5
+ * drops the cached one after the Runtime answered `401 token_expired`.
6
+ */
7
+ export interface TokenSource {
8
+ get(signal?: AbortSignal): Promise<string>;
9
+ invalidate(): void;
10
+ }
11
+ /**
12
+ * Where a client sends its requests. Nothing names a Tenant: the Runtime at `url` serves one
13
+ * (protocol 5).
14
+ */
2
15
  export interface Destination {
3
16
  url?: string;
4
17
  key?: string;
5
- tenant?: string;
6
18
  fetch?: typeof fetch;
19
+ /** Instead of `key`: subject tokens. The client then skips the `/health` check. */
20
+ token?: TokenSource;
21
+ /** A publishable key (Host feature `browser-access`): names the app and its origins. */
22
+ publishableKey?: string;
7
23
  }
8
24
  export declare function env(name: string): string | undefined;
9
25
  export declare class RuntimeError extends Error {
@@ -23,27 +39,42 @@ export declare class IncompatibleRuntimeError extends Error {
23
39
  }
24
40
  export declare class Transport {
25
41
  readonly url: string;
42
+ /** The Tenant key; empty for a client that uses subject tokens. */
26
43
  readonly key: string;
27
- readonly tenant: string;
44
+ readonly token: TokenSource | undefined;
45
+ readonly publishableKey: string | undefined;
28
46
  readonly fetcher: typeof fetch;
29
47
  /** Sent on every request, e.g. `Nylorun-Subject` and `Nylorun-Scopes` (`withHeaders`). */
30
48
  readonly headers: Readonly<Record<string, string>>;
31
49
  private readonly check;
32
- constructor(options?: Destination, role?: "server" | "executor");
50
+ constructor(options?: Destination);
33
51
  /**
34
52
  * The same destination with `headers` added to every request. The copy shares this
35
53
  * transport's compatibility check, so a copy made per request does not repeat `/health`.
36
54
  */
37
55
  withHeaders(headers: Readonly<Record<string, string>>): Transport;
56
+ /**
57
+ * The same destination with another bearer (a delivery token for an Action endpoint's
58
+ * callbacks). Like `withHeaders`, the copy shares this transport's compatibility check.
59
+ */
60
+ withKey(key: string): Transport;
38
61
  /** Clears the cached Host compatibility result (used after a 426). */
39
62
  clearCompatibilityCache(): void;
40
63
  private ensureCompatible;
64
+ /** Throws `IncompatibleRuntimeError` before anything is sent when the Host lacks `feature`. */
65
+ requireFeature(feature: string, signal?: AbortSignal): Promise<void>;
41
66
  /** The Host's protocol features, including optional ones, from its `/health`. */
42
67
  hostFeatures(signal?: AbortSignal): Promise<readonly string[]>;
43
68
  private authHeaders;
44
69
  request(path: string, init?: RequestInit, options?: {
45
70
  retried426?: boolean;
71
+ retried401?: boolean;
46
72
  }): Promise<Response>;
73
+ /**
74
+ * Sends a request with this client's credentials and returns the Runtime's response as it
75
+ * is, errors included (an app server passing a response through, e.g. the AG-UI handler).
76
+ */
77
+ forward(path: string, init?: RequestInit): Promise<Response>;
47
78
  json<T>(path: string, method?: string, body?: unknown, signal?: AbortSignal): Promise<T>;
48
79
  }
49
80
  export declare const id: () => `${string}-${string}-${string}-${string}-${string}`;
package/dist/http.js CHANGED
@@ -1,4 +1,4 @@
1
- import { PROTOCOL_FEATURES, PROTOCOL_HEADER, PROTOCOL_VERSION, TENANT_HEADER, checkCompatibility, } from "@nylorun/core/compatibility";
1
+ import { PROTOCOL_FEATURES, PROTOCOL_HEADER, PROTOCOL_VERSION, PUBLISHABLE_KEY_HEADER, checkCompatibility, } from "@nylorun/core/compatibility";
2
2
  export function env(name) {
3
3
  return typeof process !== "undefined" ? process.env[name] : undefined;
4
4
  }
@@ -54,28 +54,35 @@ function parseProtocolRange(value) {
54
54
  }
55
55
  export class Transport {
56
56
  url;
57
+ /** The Tenant key; empty for a client that uses subject tokens. */
57
58
  key;
58
- tenant;
59
+ token;
60
+ publishableKey;
59
61
  fetcher;
60
62
  /** Sent on every request, e.g. `Nylorun-Subject` and `Nylorun-Scopes` (`withHeaders`). */
61
63
  headers = {};
62
64
  check = { compatible: false, features: [] };
63
- constructor(options = {}, role = "server") {
65
+ constructor(options = {}) {
64
66
  const url = options.url ?? env("NYLORUN_RUNTIME_URL");
65
- const key = options.key ??
66
- env(role === "server" ? "NYLORUN_SERVER_KEY" : "NYLORUN_EXECUTOR_KEY");
67
- const tenant = options.tenant ?? env("NYLORUN_TENANT");
68
- if (!url || !key)
69
- throw new Error(`Set Runtime url and ${role} key explicitly or via NYLORUN_RUNTIME_URL / NYLORUN_${role.toUpperCase()}_KEY`);
70
- if (!tenant)
71
- throw new Error("Set tenant explicitly or via NYLORUN_TENANT");
67
+ const token = options.token;
68
+ const key = token ? "" : options.key ?? env("NYLORUN_SERVER_KEY");
69
+ if (!url || (!token && !key))
70
+ throw new Error("Set Runtime url and server key explicitly or via NYLORUN_RUNTIME_URL / NYLORUN_SERVER_KEY");
71
+ if (token && options.key)
72
+ throw new Error("Use a Tenant key or subject tokens, not both");
72
73
  const parsed = new URL(url);
73
74
  if (!["http:", "https:"].includes(parsed.protocol))
74
75
  throw new Error("Runtime requires an HTTP(S) URL");
75
76
  this.url = url.replace(/\/$/, "");
76
77
  this.key = key;
77
- this.tenant = tenant;
78
- this.fetcher = options.fetch ?? globalThis.fetch;
78
+ this.token = token;
79
+ this.publishableKey = options.publishableKey;
80
+ // Browsers may not call `/health` (it refuses `Origin`); token clients rely on `426`.
81
+ if (token)
82
+ this.check.compatible = true;
83
+ // Called as a method on a page's window would otherwise lose `this`.
84
+ const fetcher = options.fetch ?? globalThis.fetch;
85
+ this.fetcher = options.fetch ? fetcher : (input, init) => fetcher(input, init);
79
86
  }
80
87
  /**
81
88
  * The same destination with `headers` added to every request. The copy shares this
@@ -87,6 +94,14 @@ export class Transport {
87
94
  headers: Object.freeze({ ...this.headers, ...headers }),
88
95
  });
89
96
  }
97
+ /**
98
+ * The same destination with another bearer (a delivery token for an Action endpoint's
99
+ * callbacks). Like `withHeaders`, the copy shares this transport's compatibility check.
100
+ */
101
+ withKey(key) {
102
+ const copy = Object.create(Transport.prototype);
103
+ return Object.assign(copy, this, { key });
104
+ }
90
105
  /** Clears the cached Host compatibility result (used after a 426). */
91
106
  clearCompatibilityCache() {
92
107
  this.check.compatible = false;
@@ -123,19 +138,35 @@ export class Transport {
123
138
  if (!result.ok)
124
139
  throw new IncompatibleRuntimeError(result);
125
140
  this.check.features = [...protocol.features];
141
+ this.check.range = protocol;
126
142
  this.check.compatible = true;
127
143
  }
144
+ /** Throws `IncompatibleRuntimeError` before anything is sent when the Host lacks `feature`. */
145
+ async requireFeature(feature, signal) {
146
+ const features = await this.hostFeatures(signal);
147
+ if (!features.includes(feature))
148
+ throw new IncompatibleRuntimeError({
149
+ ok: false,
150
+ reason: "feature",
151
+ missing: [feature],
152
+ host: this.check.range ?? { min: 0, max: 0, features },
153
+ });
154
+ }
128
155
  /** The Host's protocol features, including optional ones, from its `/health`. */
129
156
  async hostFeatures(signal) {
130
157
  await this.ensureCompatible(signal);
131
158
  return this.check.features;
132
159
  }
133
- authHeaders(init = {}) {
160
+ async authHeaders(init = {}) {
134
161
  const headers = new Headers(init.headers);
135
162
  for (const [name, value] of Object.entries(this.headers))
136
163
  headers.set(name, value);
137
- headers.set("Authorization", `Bearer ${this.key}`);
138
- headers.set(TENANT_HEADER, this.tenant);
164
+ const bearer = this.token
165
+ ? await this.token.get(init.signal ?? undefined)
166
+ : this.key;
167
+ headers.set("Authorization", `Bearer ${bearer}`);
168
+ if (this.publishableKey)
169
+ headers.set(PUBLISHABLE_KEY_HEADER, this.publishableKey);
139
170
  headers.set(PROTOCOL_HEADER, String(PROTOCOL_VERSION));
140
171
  if (init.body)
141
172
  headers.set("Content-Type", "application/json");
@@ -145,9 +176,18 @@ export class Transport {
145
176
  await this.ensureCompatible(init.signal === null ? undefined : init.signal);
146
177
  const response = await this.fetcher(this.url + path, {
147
178
  ...init,
148
- headers: this.authHeaders(init),
179
+ headers: await this.authHeaders(init),
149
180
  redirect: "error",
150
181
  });
182
+ // An expired or revoked subject token: get a new one and try once more.
183
+ if (response.status === 401 && this.token && !options.retried401) {
184
+ const body = (await response.clone().json().catch(() => undefined));
185
+ if (body?.code === "token_expired") {
186
+ await response.body?.cancel().catch(() => { });
187
+ this.token.invalidate();
188
+ return this.request(path, init, { ...options, retried401: true });
189
+ }
190
+ }
151
191
  if (response.status === 426) {
152
192
  this.clearCompatibilityCache();
153
193
  if (!options.retried426) {
@@ -185,6 +225,18 @@ export class Transport {
185
225
  }
186
226
  return response;
187
227
  }
228
+ /**
229
+ * Sends a request with this client's credentials and returns the Runtime's response as it
230
+ * is, errors included (an app server passing a response through, e.g. the AG-UI handler).
231
+ */
232
+ async forward(path, init = {}) {
233
+ await this.ensureCompatible(init.signal === null ? undefined : init.signal);
234
+ return this.fetcher(this.url + path, {
235
+ ...init,
236
+ headers: await this.authHeaders(init),
237
+ redirect: "error",
238
+ });
239
+ }
188
240
  async json(path, method = "GET", body, signal) {
189
241
  const response = await this.request(path, {
190
242
  method,
package/dist/index.d.ts CHANGED
@@ -1,21 +1,24 @@
1
- export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION, TENANT_HEADER, PROTOCOL_HEADER, SUBJECT_HEADER, SCOPES_HEADER, TENANT_ID_PATTERN, isTenantId, newTenantId, newPrincipalId, checkCompatibility, compareVersions, ERROR_CODES, } from "@nylorun/core/compatibility";
1
+ export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION, PROTOCOL_HEADER, SUBJECT_HEADER, SCOPES_HEADER, TENANT_ID_PATTERN, isTenantId, newTenantId, newPrincipalId, checkCompatibility, compareVersions, ERROR_CODES, } from "@nylorun/core/compatibility";
2
2
  export type { ProtocolFeature, ProtocolRange, Compatibility, ErrorCode, } from "@nylorun/core/compatibility";
3
3
  export { Agent, AgentBuilder } from "./builder.js";
4
4
  export { AgentBuildError, AgentLifecycleError, Loop, Chain, Switch, Parallel, Map, VerdictSchema, isVerdict, withInstructions, withoutTools, WorkflowBuildError, isBuiltWorkflow, capability, CapabilityBuilder, flow, tool, defineSchema, ToolError, } from "@nylorun/core/define";
5
5
  export type { FlowAgentBuilder, Flow, Named, StageArgs, NestedStageArgs, CapabilityIdentity, } from "@nylorun/core/define";
6
6
  export type { AgentOptions, AgentManifest, BuiltAgent, BuiltWorkflow, LoopOptions, LoopDecideArgs, LoopVerifyArgs, LoopDecision, ChainOptions, SwitchOptions, ParallelOptions, MapOptions, Verdict, WorkflowBinding, WorkflowManifest, ToolDefinition, ToolExecutionContext, ToolOutcome, Patch, Decision, TurnDecision, HookScope, BeforeHook, AfterHook, JsonValue, JsonObject, } from "@nylorun/core/define";
7
- export type { LiveEvent, SessionCommand, Action, ActionOutcome, CredentialInfo, CredentialSelection, VaultInfo, SubjectScope, } from "@nylorun/core/contracts";
7
+ export type { LiveEvent, SessionEvent, SessionEventOf, EventType, SessionCommand, Action, ActionOutcome, CredentialInfo, CredentialSelection, VaultInfo, SubjectScope, } from "@nylorun/core/contracts";
8
8
  export { SUBJECT_SCOPES } from "@nylorun/core/contracts";
9
9
  export { AgentsClient, SessionClient, createClient } from "./client.js";
10
10
  export type { ActAsOptions, AgentSource, SessionView, CommandOptions, SessionSandbox, } from "./client.js";
11
- export { connectAgents } from "./executor.js";
12
- export type { ConnectOptions, AgentConnection } from "./executor.js";
11
+ export { AccessClient, PublishableKeysClient, SigningKeysClient, TokensClient, } from "./access.js";
12
+ export type { CreateTokenOptions } from "./access.js";
13
+ export { createTokenEndpoint } from "./token-endpoint.js";
14
+ export type { TokenEndpointOptions } from "./token-endpoint.js";
15
+ export { createActionHandler } from "./action-handler.js";
16
+ export type { ActionHandler, ActionHandlerOptions, RegisterOptions, } from "./action-handler.js";
13
17
  export type { ExecuteActionOptions, ExecutableDefinition, } from "./execute-action.js";
14
18
  export { resolveConnection, ConnectionError } from "./connection.js";
15
19
  export type { ResolvedConnection } from "./connection.js";
16
- export { deriveExecutorToken } from "./derived-credentials.js";
17
20
  export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
18
- export type { Destination, IncompatibleReason } from "./http.js";
21
+ export type { Destination, IncompatibleReason, TokenSource } from "./http.js";
19
22
  export { plugin } from "./plugins/plugin.js";
20
23
  export type { PluginCapability } from "./plugins/plugin.js";
21
24
  export { loadPlugin, PluginError } from "./plugins/load.js";
@@ -26,6 +29,5 @@ export { skills, loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsE
26
29
  export type { SkillsCapability, SkillsOptions, SkillDiagnostic, } from "./skills/index.js";
27
30
  export { mcp, McpError } from "./mcp/index.js";
28
31
  export type { McpCapability, McpOptions, McpServerSpec } from "./mcp/index.js";
29
- export { sandbox, SandboxError } from "./sandbox/index.js";
30
- export type { SandboxCapability, SandboxCapabilityOptions, SandboxOptions, ActionSandbox, ActionSandboxToolResult, CreateActionSandboxOptions, } from "./sandbox/index.js";
32
+ export type { ActionSandbox, ActionSandboxToolResult, CreateActionSandboxOptions, } from "./sandbox/index.js";
31
33
  export { createActionSandbox, definitionDeclaresSandbox, isActionSandboxTool, } from "./sandbox/index.js";
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  // Definition authoring and wire contracts are the only harness runtime imports.
2
- export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION, TENANT_HEADER, PROTOCOL_HEADER, SUBJECT_HEADER, SCOPES_HEADER, TENANT_ID_PATTERN, isTenantId, newTenantId, newPrincipalId, checkCompatibility, compareVersions, ERROR_CODES, } from "@nylorun/core/compatibility";
2
+ export { hashManifest, PROTOCOL_VERSION, PROTOCOL_FEATURES, HOST_PROTOCOL, DEFINITION_SCHEMA_VERSION, PROTOCOL_HEADER, SUBJECT_HEADER, SCOPES_HEADER, TENANT_ID_PATTERN, isTenantId, newTenantId, newPrincipalId, checkCompatibility, compareVersions, ERROR_CODES, } from "@nylorun/core/compatibility";
3
3
  export { Agent, AgentBuilder } from "./builder.js";
4
4
  export { AgentBuildError, AgentLifecycleError, Loop, Chain, Switch, Parallel, Map, VerdictSchema, isVerdict, withInstructions, withoutTools, WorkflowBuildError, isBuiltWorkflow, capability, CapabilityBuilder, flow, tool, defineSchema, ToolError, } from "@nylorun/core/define";
5
5
  export { SUBJECT_SCOPES } from "@nylorun/core/contracts";
6
6
  export { AgentsClient, SessionClient, createClient } from "./client.js";
7
- export { connectAgents } from "./executor.js";
7
+ export { AccessClient, PublishableKeysClient, SigningKeysClient, TokensClient, } from "./access.js";
8
+ export { createTokenEndpoint } from "./token-endpoint.js";
9
+ export { createActionHandler } from "./action-handler.js";
8
10
  export { resolveConnection, ConnectionError } from "./connection.js";
9
- export { deriveExecutorToken } from "./derived-credentials.js";
10
11
  export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
11
12
  export { plugin } from "./plugins/plugin.js";
12
13
  export { loadPlugin, PluginError } from "./plugins/load.js";
13
14
  export { prepareStdioLaunch, expandPluginPlaceholders } from "./plugins/launch.js";
14
15
  export { skills, loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, formatSkillCatalog, SKILLS_USAGE, } from "./skills/index.js";
15
16
  export { mcp, McpError } from "./mcp/index.js";
16
- export { sandbox, SandboxError } from "./sandbox/index.js";
17
17
  export { createActionSandbox, definitionDeclaresSandbox, isActionSandboxTool, } from "./sandbox/index.js";
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Claim-scoped sandbox client for executor actions (`ctx.sandbox`).
3
- * Calls `POST /v1/actions/:id/sandbox/:tool` with the live claim.
2
+ * Action-scoped sandbox client (`ctx.sandbox`). Calls `POST /v1/actions/:id/sandbox/:tool`
3
+ * over a transport whose credential is the Action's delivery token.
4
4
  */
5
5
  import { type SandboxToolName } from "@nylorun/core/define";
6
6
  import { type Transport } from "../http.js";
@@ -45,13 +45,12 @@ export type ActionSandbox = {
45
45
  }) => Promise<ActionSandboxToolResult>;
46
46
  };
47
47
  export type CreateActionSandboxOptions = {
48
+ /** The transport's key is the delivery token, which names the Action and its generation. */
48
49
  readonly transport: Transport;
49
50
  readonly actionId: string;
50
- readonly claimId: string;
51
- readonly generation: number;
52
51
  readonly signal?: AbortSignal;
53
52
  };
54
- /** Build `ctx.sandbox` for one claimed action. Undefined callers skip when the session has none. */
53
+ /** Build `ctx.sandbox` for one delivered action. Callers skip it when the session has none. */
55
54
  export declare function createActionSandbox(options: CreateActionSandboxOptions): ActionSandbox;
56
55
  export declare function isActionSandboxTool(name: string): name is SandboxToolName;
57
56
  /** True when the executable declares a sandbox the Runtime can share. */
@@ -1,16 +1,12 @@
1
1
  /**
2
- * Claim-scoped sandbox client for executor actions (`ctx.sandbox`).
3
- * Calls `POST /v1/actions/:id/sandbox/:tool` with the live claim.
2
+ * Action-scoped sandbox client (`ctx.sandbox`). Calls `POST /v1/actions/:id/sandbox/:tool`
3
+ * over a transport whose credential is the Action's delivery token.
4
4
  */
5
5
  import { SANDBOX_TOOL_NAMES, } from "@nylorun/core/define";
6
6
  import { segment } from "../http.js";
7
- /** Build `ctx.sandbox` for one claimed action. Undefined callers skip when the session has none. */
7
+ /** Build `ctx.sandbox` for one delivered action. Callers skip it when the session has none. */
8
8
  export function createActionSandbox(options) {
9
- const call = (tool, input) => options.transport.json(`/v1/actions/${segment(options.actionId)}/sandbox/${tool}`, "POST", {
10
- claimId: options.claimId,
11
- generation: options.generation,
12
- ...input,
13
- }, options.signal);
9
+ const call = (tool, input) => options.transport.json(`/v1/actions/${segment(options.actionId)}/sandbox/${tool}`, "POST", input, options.signal);
14
10
  const sandbox = {
15
11
  bash: (input) => call("bash", input),
16
12
  read: (input) => call("read", input),
@@ -1,4 +1,2 @@
1
- export { sandbox, SandboxError } from "@nylorun/core/define";
2
- export type { SandboxCapability, SandboxCapabilityOptions, SandboxOptions, } from "@nylorun/core/define";
3
1
  export { createActionSandbox, definitionDeclaresSandbox, isActionSandboxTool, } from "./client.js";
4
2
  export type { ActionSandbox, ActionSandboxToolResult, CreateActionSandboxOptions, } from "./client.js";
@@ -1,2 +1 @@
1
- export { sandbox, SandboxError } from "@nylorun/core/define";
2
1
  export { createActionSandbox, definitionDeclaresSandbox, isActionSandboxTool, } from "./client.js";
@@ -0,0 +1,20 @@
1
+ import { type BuiltWorkflow } from "@nylorun/core/define";
2
+ import { type AgentSource } from "./client.js";
3
+ import type { ExecutableDefinition } from "./execute-action.js";
4
+ /** The implementation version to register: the option, `NYLORUN_IMPLEMENTATION_VERSION`, or `dev`. */
5
+ export declare function implementationVersionOf(options: {
6
+ implementationVersion?: string;
7
+ }): string;
8
+ /** The ids among `agents` that are saved only as part of another definition. */
9
+ export declare function embeddedIn(agents: Map<string, ExecutableDefinition>): ReadonlySet<string>;
10
+ /**
11
+ * Every definition `sources` serves, by id: the agents and workflows passed in, the agents
12
+ * a v2 workflow embeds, and flow agents used as tools. `owner` names the caller in errors.
13
+ */
14
+ export declare function buildAgents(sources: readonly (AgentSource | BuiltWorkflow)[], owner: string): Map<string, ExecutableDefinition>;
15
+ /**
16
+ * The manifest hash served for a workflow's flow actions. A run is pinned to one workflow
17
+ * manifest, and its stage keys may shift between deploys, so flow actions for another hash
18
+ * are left for whoever serves it.
19
+ */
20
+ export declare function flowManifestHash(agent: ExecutableDefinition): string | undefined;