@nylorun/agents 0.14.0-beta → 0.16.1-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.
@@ -3,10 +3,12 @@
3
3
  * which resolves the connection from the environment or the Project link.
4
4
  */
5
5
  import type { AgentManifest, BuiltAgent, BuiltWorkflow, JsonValue, SandboxToolName, WorkflowManifest } from "@nylorun/core/define";
6
- import { type SubjectScope, type CredentialInfo, type CredentialSelection, type MessagePart, type SandboxRequest, type SessionCommand, type VaultInfo } from "@nylorun/core/contracts";
6
+ import { type SessionItemsResponse, type SessionSummary, type ListAgentsResponse, type ListPublicAgentsResponse, type SubjectScope, type CredentialSelection, type MessagePart, type SandboxRequest, type SessionCommand } from "@nylorun/core/contracts";
7
+ import { SessionsReadClient } from "./reads.js";
7
8
  import { AccessClient } from "./access.js";
8
9
  import { SandboxesClient } from "./sandboxes.js";
9
10
  import { ArtifactsClient } from "./artifacts.js";
11
+ import { FilesClient } from "./files.js";
10
12
  import { Transport, type Destination } from "./http.js";
11
13
  /** Application-principal access to a session's sandbox built-ins (workflows.md §8). */
12
14
  export type SessionSandbox = {
@@ -63,7 +65,7 @@ export declare class AgentsClient {
63
65
  * themselves and hold the key; nothing is minted, cached or refreshed.
64
66
  */
65
67
  as(subject: string, options?: ActAsOptions): AgentsClient;
66
- /** The signing keys and the public keys that verify delivery tokens. Application key only. */
68
+ /** The public keys that verify the tokens the Tenant signs. */
67
69
  get access(): AccessClient;
68
70
  /**
69
71
  * Sandboxes as a resource (Host feature `sandboxes`): `ensure` one by id, `list` them by
@@ -72,101 +74,38 @@ export declare class AgentsClient {
72
74
  get sandboxes(): SandboxesClient;
73
75
  /** File artifacts: upload, list, download with Range, capability links (protocol 6). */
74
76
  get artifacts(): ArtifactsClient;
77
+ /** Definition files: the skill files a definition names, by content hash. */
78
+ get files(): FilesClient;
75
79
  /** The Runtime's protocol features, including optional ones such as `transcript-events`. */
76
80
  hostFeatures(options?: {
77
81
  signal?: AbortSignal;
78
82
  }): Promise<readonly string[]>;
83
+ get sessions(): SessionsReadClient;
79
84
  listAgents(options?: {
80
85
  signal?: AbortSignal;
81
- }): Promise<{
82
- agents: {
83
- manifest: AgentManifest;
84
- }[];
86
+ }): Promise<ListAgentsResponse | {
87
+ agents: (ListPublicAgentsResponse["agents"][number] & {
88
+ manifest?: never;
89
+ })[];
85
90
  }>;
86
91
  listSessions(options?: {
87
92
  agentId?: string;
88
93
  signal?: AbortSignal;
89
94
  }): Promise<{
90
- sessions: SessionView[];
95
+ sessions: SessionSummary[];
91
96
  }>;
92
- saveAgent(agent: AgentSource | BuiltWorkflow, options: {
93
- implementationVersion: string;
94
- requestId?: string;
95
- }): Promise<unknown>;
96
- createSession(options: CreateSessionOptions): Promise<SessionClient>;
97
97
  /**
98
- * Creates a vault: the installation's own (`scope: "installation"`), which any session may
99
- * attach, or one person's (`ownerUserId`), which only that person's sessions attach. Vault
100
- * routes take the application key acting for no one (protocol 7): not a client made with `as`.
98
+ * Registers the agent's definition (`PUT /v1/agents/{id}`), first uploading the skill files
99
+ * it names that the Runtime does not hold. A definition with a tool that runs your code
100
+ * (`tool({ run })`, a flow's tool stage) is refused before anything is sent: the Runtime runs
101
+ * no code of yours during a session. `implementationVersion` defaults to
102
+ * `NYLORUN_IMPLEMENTATION_VERSION`, else `dev`.
101
103
  */
102
- createVault(options: {
103
- name: string;
104
- metadata?: Record<string, string>;
105
- idempotencyKey: string;
104
+ saveAgent(agent: AgentSource | BuiltWorkflow, options?: {
105
+ implementationVersion?: string;
106
106
  requestId?: string;
107
- } & ({
108
- scope: "installation";
109
- ownerUserId?: undefined;
110
- } | {
111
- scope?: "user";
112
- ownerUserId: string;
113
- })): Promise<VaultInfo>;
114
- /** The installation vaults, after the vaults of `ownerUserId` when it is given. */
115
- listVaults(ownerUserId?: string, signal?: AbortSignal): Promise<{
116
- vaults: VaultInfo[];
117
- }>;
118
- getVault(vaultId: string, signal?: AbortSignal): Promise<VaultInfo>;
119
- deleteVault(vaultId: string): Promise<{
120
- id: string;
121
- }>;
122
- createCredential(vaultId: string, options: {
123
- name: string;
124
- idempotencyKey: string;
125
- requestId?: string;
126
- auth: {
127
- type: "bearer";
128
- url: string;
129
- token: string;
130
- } | {
131
- type: "oauth";
132
- url: string;
133
- accessToken: string;
134
- expiresAt?: string | null;
135
- refresh?: {
136
- tokenEndpoint: string;
137
- clientId: string;
138
- refreshToken: string;
139
- tokenEndpointAuth: {
140
- type: "none";
141
- } | {
142
- type: "client_secret_basic";
143
- clientSecret: string;
144
- } | {
145
- type: "client_secret_post";
146
- clientSecret: string;
147
- };
148
- };
149
- };
150
- }): Promise<CredentialInfo>;
151
- listCredentials(vaultId: string, signal?: AbortSignal): Promise<{
152
- credentials: CredentialInfo[];
153
- }>;
154
- getCredential(vaultId: string, credentialId: string, signal?: AbortSignal): Promise<CredentialInfo>;
155
- rotateCredential(vaultId: string, credentialId: string, options: {
156
- idempotencyKey: string;
157
- requestId?: string;
158
- auth: {
159
- type: "bearer";
160
- token: string;
161
- } | {
162
- type: "oauth";
163
- accessToken: string;
164
- expiresAt?: string | null;
165
- };
166
- }): Promise<CredentialInfo>;
167
- deleteCredential(vaultId: string, credentialId: string): Promise<{
168
- id: string;
169
- }>;
107
+ }): Promise<unknown>;
108
+ createSession(options: CreateSessionOptions): Promise<SessionClient>;
170
109
  session(sessionId: string): SessionClient;
171
110
  }
172
111
  export type CommandOptions = {
@@ -230,42 +169,80 @@ export declare class SessionClient {
230
169
  cursor: string | null;
231
170
  requestId: string;
232
171
  }>;
233
- /** `agent` narrows to one agent used as a tool: its delegationId or its path. */
234
- history(options?: {
172
+ manifest(options?: {
173
+ signal?: AbortSignal;
174
+ }): Promise<{
175
+ sessionId: string;
176
+ agentId: string;
177
+ manifestHash: string;
178
+ implementationVersion: string;
179
+ manifest: Record<string, unknown>;
180
+ }>;
181
+ usage(options?: {
182
+ turnId?: string;
183
+ signal?: AbortSignal;
184
+ }): Promise<{
185
+ inputTokens: number;
186
+ outputTokens: number;
187
+ totalTokens: number;
188
+ cachedTokens: number;
189
+ cacheWriteTokens: number;
190
+ reasoningTokens: number;
191
+ costUsd: number;
192
+ sessionId: string;
193
+ turnId: string | null;
194
+ asOf: string;
195
+ calls: number;
196
+ duplicates: number;
197
+ unpricedCalls: number;
198
+ unreportedCalls: number;
199
+ unknownQualityCalls: number;
200
+ }>;
201
+ modelCalls(options?: {
202
+ turnId?: string;
203
+ limit?: number;
235
204
  cursor?: string;
236
- agent?: string;
237
205
  signal?: AbortSignal;
238
206
  }): Promise<{
239
- items: ({
240
- schema: "nylorun.event/2";
241
- eventId: string;
242
- tenantId: string;
207
+ calls: {
208
+ id: string;
243
209
  sessionId: string;
244
- runId: string | null;
245
- turnId: string | null;
246
- incarnation: number;
247
- epoch: number;
248
- seq: number;
249
- cursor: string;
250
- time: string;
251
- schemaVersion: number;
252
- source: {
253
- kind: "api" | "controller" | "edge" | "egress-gate" | "evidence" | "harness" | "human" | "init" | "loop" | "model-gate" | "operator" | "sandboxd" | "supervisor" | "tool-gate";
254
- id: string;
255
- };
256
- evidence: "asserted" | "attested" | "claimed" | "measured" | "observed";
257
- trace?: {
258
- traceId: string;
259
- spanId: string;
260
- parentSpanId?: string | undefined;
261
- } | undefined;
262
- visibility: "internal" | "public" | "restricted";
263
- retention: "full" | "metadata";
264
- type: string;
265
- payload: unknown;
266
- } | import("@nylorun/core/contracts").SessionEvent)[];
267
- cursor: string | null;
210
+ turnId: string;
211
+ agentId: string;
212
+ provider: string | null;
213
+ model: string | null;
214
+ at: string;
215
+ outcome: "completed" | "failed";
216
+ usage: {
217
+ inputTokens: number;
218
+ outputTokens: number;
219
+ totalTokens: number;
220
+ cachedTokens: number;
221
+ cacheWriteTokens: number;
222
+ reasoningTokens: number;
223
+ costUsd: number;
224
+ duplicate: boolean;
225
+ tokensReported: boolean | null;
226
+ costKnown: boolean | null;
227
+ } | null;
228
+ }[];
229
+ nextCursor: string | null;
230
+ asOf: string;
231
+ }>;
232
+ /** `agent` narrows to one agent used as a tool: its delegationId or its path. */
233
+ history(options: {
234
+ cursor?: string;
235
+ agent?: string;
236
+ signal?: AbortSignal;
237
+ limit: number;
238
+ }): Promise<SessionItemsResponse & {
239
+ tail: boolean;
268
240
  }>;
241
+ history(options?: {
242
+ cursor?: string;
243
+ agent?: string;
244
+ signal?: AbortSignal;
245
+ }): Promise<SessionItemsResponse>;
269
246
  observe(options?: {
270
247
  cursor?: string;
271
248
  signal?: AbortSignal;
@@ -308,6 +285,6 @@ export declare class SessionClient {
308
285
  export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
309
286
  export type { Destination, IncompatibleReason } from "./http.js";
310
287
  export type { LiveEvent } from "@nylorun/core/contracts";
311
- export { AccessClient, SigningKeysClient } from "./access.js";
288
+ export { AccessClient } from "./access.js";
312
289
  export { SandboxesClient } from "./sandboxes.js";
313
290
  export type { ForSessionOptions, SandboxSpec, SessionSandboxHandle } from "./sandboxes.js";
@@ -1,11 +1,13 @@
1
- import { SANDBOX_TOOL_NAMES, delegateOf, isBuiltWorkflow, isSandboxToolName, } from "@nylorun/core/define";
1
+ import { SANDBOX_TOOL_NAMES, codeToolRefusal, delegateOf, isBuiltWorkflow, isSandboxToolName, } from "@nylorun/core/define";
2
2
  import { z } from "zod";
3
3
  import { SCOPES_HEADER, SUBJECT_HEADER } from "@nylorun/core/compatibility";
4
- import { parseSessionEvent, parseSubjectHeaders, } from "@nylorun/core/contracts";
4
+ import { SessionManifestViewSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, parseSessionEvent, parseSubjectHeaders, } from "@nylorun/core/contracts";
5
+ import { SessionsReadClient } from "./reads.js";
5
6
  import { AccessClient } from "./access.js";
6
7
  import { SandboxesClient } from "./sandboxes.js";
7
8
  import { ArtifactsClient } from "./artifacts.js";
8
- import { Transport, id, segment } from "./http.js";
9
+ import { FilesClient } from "./files.js";
10
+ import { Transport, env, id, segment } from "./http.js";
9
11
  import { observeSSE } from "./sse.js";
10
12
  function sessionSandboxOf(transport, sessionId) {
11
13
  const call = (tool, args) => transport.json(`/v1/sessions/${segment(sessionId)}/sandbox/${segment(tool)}`, "POST", args);
@@ -28,8 +30,8 @@ function linkedSessionId(event) {
28
30
  ? sessionId
29
31
  : undefined;
30
32
  }
31
- const middlewareClosure = "Hosted definitions support declarative capabilities and before/after hooks, not middleware closures";
32
- /** The agent's declarations, then those of each agent it uses as a tool, keyed `<child>/<capability>`. */
33
+ const middlewareClosure = "Hosted definitions support declarative capabilities, not middleware closures";
34
+ /** The agent's declarations, then those of each agent it uses as a tool. */
33
35
  function declarationsOf(agent) {
34
36
  if (isBuiltWorkflow(agent) || agent.manifest.kind === "workflow")
35
37
  return [];
@@ -39,30 +41,26 @@ function declarationsOf(agent) {
39
41
  const binding = built.getBinding?.();
40
42
  if (!binding || !("declarations" in binding))
41
43
  return [];
42
- const found = (binding.declarations ?? []).map((item) => ({ key: item.id, item }));
44
+ const found = [...(binding.declarations ?? [])];
43
45
  for (const tool of binding.tools ?? []) {
44
46
  const delegate = delegateOf(tool);
45
- const child = delegate?.agent;
46
- for (const item of child?.getBinding().declarations ?? [])
47
- found.push({ key: `${child.id}/${item.id}`, item });
48
- // A flow agent used as a tool: its agents' declarations, keyed `<flow>/<agent>/<capability>`.
49
- const flow = delegate?.workflow;
50
- for (const leaf of Object.values(flow?.getBinding().agents ?? {}))
51
- for (const item of leaf.declarations ?? [])
52
- found.push({ key: `${flow.id}/${leaf.manifest.id}/${item.id}`, item });
47
+ found.push(...(delegate?.agent?.getBinding().declarations ?? []));
48
+ // A flow agent used as a tool: its agents' declarations.
49
+ for (const leaf of Object.values(delegate?.workflow?.getBinding().agents ?? {}))
50
+ found.push(...(leaf.declarations ?? []));
53
51
  }
54
52
  return found;
55
53
  }
56
- function pluginRootsOf(agent) {
57
- const roots = {};
58
- for (const { key, item } of declarationsOf(agent))
59
- if (item.pluginRoot)
60
- roots[key] = item.pluginRoot;
61
- return Object.keys(roots).length === 0 ? undefined : roots;
54
+ /** The bytes of every skill file the agent's definition names, by `sha256:<hex>`. */
55
+ function skillFilesOf(agent, into = new Map()) {
56
+ for (const item of declarationsOf(agent))
57
+ for (const [sha256, source] of Object.entries(item.skillFiles ?? {}))
58
+ into.set(sha256, source);
59
+ return into;
62
60
  }
63
61
  /** Closures stay on the live binding. The published manifest cannot name them. */
64
62
  export function assertNoMiddlewareClosures(agent) {
65
- if (declarationsOf(agent).some(({ item }) => item.hasMiddleware))
63
+ if (declarationsOf(agent).some((item) => item.hasMiddleware))
66
64
  throw new Error(middlewareClosure);
67
65
  }
68
66
  export class AgentsClient {
@@ -95,7 +93,7 @@ export class AgentsClient {
95
93
  subject,
96
94
  });
97
95
  }
98
- /** The signing keys and the public keys that verify delivery tokens. Application key only. */
96
+ /** The public keys that verify the tokens the Tenant signs. */
99
97
  get access() {
100
98
  return new AccessClient(this.transport);
101
99
  }
@@ -110,10 +108,17 @@ export class AgentsClient {
110
108
  get artifacts() {
111
109
  return new ArtifactsClient(this.transport);
112
110
  }
111
+ /** Definition files: the skill files a definition names, by content hash. */
112
+ get files() {
113
+ return new FilesClient(this.transport);
114
+ }
113
115
  /** The Runtime's protocol features, including optional ones such as `transcript-events`. */
114
116
  hostFeatures(options = {}) {
115
117
  return this.transport.hostFeatures(options.signal);
116
118
  }
119
+ get sessions() {
120
+ return new SessionsReadClient(this.transport);
121
+ }
117
122
  listAgents(options = {}) {
118
123
  return this.transport.json("/v1/agents", "GET", undefined, options.signal);
119
124
  }
@@ -123,44 +128,35 @@ export class AgentsClient {
123
128
  : "";
124
129
  return this.transport.json(`/v1/sessions${query}`, "GET", undefined, options.signal);
125
130
  }
126
- async saveAgent(agent, options) {
127
- if (isBuiltWorkflow(agent) && agent.manifest.workflowSchemaVersion === 2) {
128
- // A v2 workflow embeds its agents: one document, carrying their plugin roots.
129
- const pluginRoots = {};
131
+ /**
132
+ * Registers the agent's definition (`PUT /v1/agents/{id}`), first uploading the skill files
133
+ * it names that the Runtime does not hold. A definition with a tool that runs your code
134
+ * (`tool({ run })`, a flow's tool stage) is refused before anything is sent: the Runtime runs
135
+ * no code of yours during a session. `implementationVersion` defaults to
136
+ * `NYLORUN_IMPLEMENTATION_VERSION`, else `dev`.
137
+ */
138
+ async saveAgent(agent, options = {}) {
139
+ const files = new Map();
140
+ if (isBuiltWorkflow(agent)) {
141
+ // A flow agent embeds its agents: one document, carrying their files.
130
142
  for (const binding of Object.values(agent.getBinding().agents)) {
131
143
  const leaf = { id: binding.manifest.id, manifest: binding.manifest, getBinding: () => binding };
132
144
  assertNoMiddlewareClosures(leaf);
133
- for (const [key, root] of Object.entries(pluginRootsOf(leaf) ?? {}))
134
- pluginRoots[`${leaf.id}/${key}`] = root;
145
+ skillFilesOf(leaf, files);
135
146
  }
136
- return this.transport.json(`/v1/agents/${segment(agent.id)}`, "PUT", {
137
- requestId: options.requestId ?? id(),
138
- manifest: agent.manifest,
139
- implementationVersion: options.implementationVersion,
140
- ...(Object.keys(pluginRoots).length === 0 ? {} : { pluginRoots }),
141
- });
142
147
  }
143
- if (isBuiltWorkflow(agent)) {
144
- for (const binding of Object.values(agent.getBinding().agents)) {
145
- await this.saveAgent({
146
- id: binding.manifest.id,
147
- manifest: binding.manifest,
148
- getBinding: () => binding,
149
- }, options);
150
- }
151
- return this.transport.json(`/v1/agents/${segment(agent.id)}`, "PUT", {
152
- requestId: options.requestId ?? id(),
153
- manifest: agent.manifest,
154
- implementationVersion: options.implementationVersion,
155
- });
148
+ else {
149
+ assertNoMiddlewareClosures(agent);
150
+ skillFilesOf(agent, files);
156
151
  }
157
- assertNoMiddlewareClosures(agent);
158
- const pluginRoots = pluginRootsOf(agent);
152
+ const refusal = codeToolRefusal(agent.manifest);
153
+ if (refusal)
154
+ throw new Error(refusal);
155
+ await this.files.ensure(files);
159
156
  return this.transport.json(`/v1/agents/${segment(agent.id)}`, "PUT", {
160
157
  requestId: options.requestId ?? id(),
161
158
  manifest: agent.manifest,
162
- implementationVersion: options.implementationVersion,
163
- ...(pluginRoots === undefined ? {} : { pluginRoots }),
159
+ implementationVersion: options.implementationVersion ?? env("NYLORUN_IMPLEMENTATION_VERSION") ?? "dev",
164
160
  });
165
161
  }
166
162
  async createSession(options) {
@@ -178,58 +174,6 @@ export class AgentsClient {
178
174
  });
179
175
  return this.session(sessionId);
180
176
  }
181
- /**
182
- * Creates a vault: the installation's own (`scope: "installation"`), which any session may
183
- * attach, or one person's (`ownerUserId`), which only that person's sessions attach. Vault
184
- * routes take the application key acting for no one (protocol 7): not a client made with `as`.
185
- */
186
- createVault(options) {
187
- return this.transport.json("/v1/vaults", "POST", {
188
- requestId: options.requestId ?? id(),
189
- idempotencyKey: options.idempotencyKey,
190
- name: options.name,
191
- ...(options.scope === "installation"
192
- ? { scope: "installation" }
193
- : { ownerUserId: options.ownerUserId }),
194
- ...(options.metadata ? { metadata: options.metadata } : {}),
195
- });
196
- }
197
- /** The installation vaults, after the vaults of `ownerUserId` when it is given. */
198
- listVaults(ownerUserId, signal) {
199
- return this.transport.json(ownerUserId === undefined
200
- ? "/v1/vaults"
201
- : `/v1/vaults?ownerUserId=${encodeURIComponent(ownerUserId)}`, "GET", undefined, signal);
202
- }
203
- getVault(vaultId, signal) {
204
- return this.transport.json(`/v1/vaults/${segment(vaultId)}`, "GET", undefined, signal);
205
- }
206
- deleteVault(vaultId) {
207
- return this.transport.json(`/v1/vaults/${segment(vaultId)}`, "DELETE");
208
- }
209
- createCredential(vaultId, options) {
210
- return this.transport.json(`/v1/vaults/${segment(vaultId)}/credentials`, "POST", {
211
- requestId: options.requestId ?? id(),
212
- idempotencyKey: options.idempotencyKey,
213
- name: options.name,
214
- auth: options.auth,
215
- });
216
- }
217
- listCredentials(vaultId, signal) {
218
- return this.transport.json(`/v1/vaults/${segment(vaultId)}/credentials`, "GET", undefined, signal);
219
- }
220
- getCredential(vaultId, credentialId, signal) {
221
- return this.transport.json(`/v1/vaults/${segment(vaultId)}/credentials/${segment(credentialId)}`, "GET", undefined, signal);
222
- }
223
- rotateCredential(vaultId, credentialId, options) {
224
- return this.transport.json(`/v1/vaults/${segment(vaultId)}/credentials/${segment(credentialId)}`, "POST", {
225
- requestId: options.requestId ?? id(),
226
- idempotencyKey: options.idempotencyKey,
227
- auth: options.auth,
228
- });
229
- }
230
- deleteCredential(vaultId, credentialId) {
231
- return this.transport.json(`/v1/vaults/${segment(vaultId)}/credentials/${segment(credentialId)}`, "DELETE");
232
- }
233
177
  session(sessionId) {
234
178
  return new SessionClient(this.transport, sessionId);
235
179
  }
@@ -310,19 +254,45 @@ export class SessionClient {
310
254
  ...(options.reason ? { reason: options.reason } : {}),
311
255
  }, options.signal);
312
256
  }
313
- /** `agent` narrows to one agent used as a tool: its delegationId or its path. */
257
+ async manifest(options = {}) {
258
+ await this.transport.requireFeature("session-reads", options.signal);
259
+ return SessionManifestViewSchema.parse(await this.transport.json(`${this.path}/manifest`, "GET", undefined, options.signal));
260
+ }
261
+ async usage(options = {}) {
262
+ await this.transport.requireFeature("session-reads", options.signal);
263
+ const query = new URLSearchParams();
264
+ if (options.turnId !== undefined)
265
+ query.set("turnId", options.turnId);
266
+ return SessionUsageTotalsSchema.parse(await this.transport.json(`${this.path}/usage${query.size ? `?${query}` : ""}`, "GET", undefined, options.signal));
267
+ }
268
+ async modelCalls(options = {}) {
269
+ await this.transport.requireFeature("session-reads", options.signal);
270
+ const query = new URLSearchParams({ limit: String(options.limit ?? 50) });
271
+ if (options.turnId !== undefined)
272
+ query.set("turnId", options.turnId);
273
+ if (options.cursor !== undefined)
274
+ query.set("cursor", options.cursor);
275
+ return ModelCallsPageSchema.parse(await this.transport.json(`${this.path}/calls/model?${query}`, "GET", undefined, options.signal));
276
+ }
314
277
  async history(options = {}) {
315
278
  const query = new URLSearchParams();
316
279
  if (options.cursor)
317
280
  query.set("cursor", options.cursor);
318
281
  if (options.agent)
319
282
  query.set("agent", options.agent);
283
+ if (options.limit !== undefined) {
284
+ await this.transport.requireFeature("session-reads", options.signal);
285
+ query.set("limit", String(options.limit));
286
+ }
320
287
  const search = query.toString();
321
- const page = z
322
- .object({ items: z.array(z.unknown()), cursor: z.string().nullable() })
323
- .parse(await this.transport.json(`${this.path}/items${search ? `?${search}` : ""}`, "GET", undefined, options.signal));
288
+ const schema = z.object({ items: z.array(z.unknown()), cursor: z.string().nullable() });
289
+ const page = (options.limit === undefined ? schema : schema.extend({ tail: z.boolean() })).parse(await this.transport.json(`${this.path}/items${search ? `?${search}` : ""}`, "GET", undefined, options.signal));
324
290
  // Typed when the catalog knows the type; a newer Runtime's type stays a bare envelope.
325
- return { items: page.items.map(parseSessionEvent), cursor: page.cursor };
291
+ return {
292
+ items: page.items.map(parseSessionEvent),
293
+ cursor: page.cursor,
294
+ ...("tail" in page ? { tail: page.tail } : {}),
295
+ };
326
296
  }
327
297
  async *observe(options = {}) {
328
298
  if (!options.follow) {
@@ -401,5 +371,5 @@ export class SessionClient {
401
371
  }
402
372
  }
403
373
  export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
404
- export { AccessClient, SigningKeysClient } from "./access.js";
374
+ export { AccessClient } from "./access.js";
405
375
  export { SandboxesClient } from "./sandboxes.js";
@@ -1,5 +1,5 @@
1
1
  export { skills } from "./skills.js";
2
2
  export type { SkillsCapability, SkillsOptions } from "./skills.js";
3
3
  export { loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
4
- export type { SkillDiagnostic } from "./load.js";
4
+ export type { LoadedSkill, SkillDiagnostic } from "./load.js";
5
5
  export { formatSkillCatalog, SKILLS_USAGE } from "./catalog.js";
@@ -1,4 +1,4 @@
1
- import type { SkillRecord } from "@nylorun/core/define";
1
+ import { type SkillFileSource } from "@nylorun/core/define";
2
2
  export interface SkillDiagnostic {
3
3
  readonly severity: "info" | "warning";
4
4
  readonly code: string;
@@ -10,16 +10,27 @@ export declare class SkillsError extends Error {
10
10
  readonly diagnostics: readonly SkillDiagnostic[];
11
11
  constructor(code: string, message: string, diagnostics?: readonly SkillDiagnostic[]);
12
12
  }
13
+ /** One skill read from its folder: what the manifest names, and where each file's bytes are. */
14
+ export interface LoadedSkill {
15
+ readonly name: string;
16
+ readonly description: string;
17
+ /** Every file of the folder by its `/`-separated path, as `sha256:<hex>`. */
18
+ readonly files: Readonly<Record<string, string>>;
19
+ /** Each file's bytes, by `sha256:<hex>`, for the client to upload. */
20
+ readonly sources: Readonly<Record<string, SkillFileSource>>;
21
+ }
13
22
  /** Resolve a skills catalog directory; throws when missing or not a directory. */
14
23
  export declare function resolveSkillsRoot(directory: string): string;
15
24
  /**
16
25
  * Load Agent Skills (agentskills.io) from a catalog directory.
17
- * Each immediate subdirectory with a valid SKILL.md becomes one skill.
26
+ * Each immediate subdirectory with a valid SKILL.md becomes one skill, with every file of its
27
+ * folder (text or binary) hashed. Throws `SkillsError` for a skill the Runtime cannot hold: a
28
+ * file over 10 MiB, more than 500 files, or a path a manifest cannot name.
18
29
  */
19
30
  export declare function loadSkillsFromDirectory(directory: string, diagnostics: SkillDiagnostic[], options?: {
20
31
  readonly boundary?: string;
21
32
  readonly codePrefix?: string;
22
- }): Readonly<Record<string, SkillRecord>>;
33
+ }): Readonly<Record<string, LoadedSkill>>;
23
34
  export declare function parseSkill(text: string, directoryName: string): {
24
35
  name: string;
25
36
  description: string;