@nylorun/agents 0.23.0-beta → 0.25.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.
- package/CHANGELOG.md +52 -0
- package/README.md +137 -105
- package/dist/a2a/handler.d.ts +9 -4
- package/dist/a2a/handler.js +9 -0
- package/dist/ag-ui/handler.d.ts +13 -9
- package/dist/ag-ui/handler.js +8 -5
- package/dist/agent-manifests.d.ts +132 -0
- package/dist/agent-manifests.js +229 -0
- package/dist/agents.d.ts +456 -0
- package/dist/agents.js +331 -0
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +1 -1
- package/dist/compose.d.ts +23 -0
- package/dist/compose.js +257 -0
- package/dist/files.d.ts +3 -3
- package/dist/files.js +3 -3
- package/dist/index.d.ts +8 -6
- package/dist/index.js +5 -4
- package/dist/plugins/load.d.ts +10 -0
- package/dist/plugins/load.js +25 -14
- package/dist/plugins/plugin.d.ts +1 -1
- package/dist/plugins/plugin.js +1 -1
- package/dist/reads.d.ts +3 -1
- package/dist/session-client.d.ts +96 -50
- package/dist/session-client.js +24 -74
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.js +1 -1
- package/dist/skills/load.d.ts +20 -2
- package/dist/skills/load.js +37 -11
- package/dist/skills/skills.d.ts +8 -6
- package/dist/skills/skills.js +9 -5
- package/package.json +5 -5
- package/dist/environments.d.ts +0 -413
- package/dist/environments.js +0 -299
package/dist/session-client.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { SANDBOX_TOOL_NAMES,
|
|
1
|
+
import { SANDBOX_TOOL_NAMES, isSandboxToolName } from "@nylorun/core/define";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { SCOPES_HEADER, SUBJECT_HEADER } from "@nylorun/core/compatibility";
|
|
4
4
|
import { SessionManifestViewSchema, SessionUsageTotalsSchema, ModelCallsPageSchema, ToolCallsPageSchema, TurnTraceSchema, parseSessionEvent, parseSubjectHeaders, } from "@nylorun/core/contracts";
|
|
5
5
|
import { SessionsReadClient } from "./reads.js";
|
|
6
6
|
import { AccessClient } from "./access.js";
|
|
7
|
-
import {
|
|
7
|
+
import { AgentInstancesClient } from "./agents.js";
|
|
8
|
+
import { AgentManifestsClient } from "./agent-manifests.js";
|
|
8
9
|
import { ArtifactsClient } from "./artifacts.js";
|
|
9
10
|
import { FilesClient } from "./files.js";
|
|
10
|
-
import { Transport,
|
|
11
|
+
import { Transport, id, segment } from "./http.js";
|
|
11
12
|
import { observeSSE } from "./sse.js";
|
|
12
13
|
function sessionSandboxOf(transport, sessionId) {
|
|
13
14
|
const call = (tool, args) => transport.json(`/v1/sessions/${segment(sessionId)}/sandbox/${segment(tool)}`, "POST", args);
|
|
@@ -30,33 +31,6 @@ function linkedSessionId(event) {
|
|
|
30
31
|
? sessionId
|
|
31
32
|
: undefined;
|
|
32
33
|
}
|
|
33
|
-
/** The agent's declarations, then those of each agent it uses as a tool. */
|
|
34
|
-
function declarationsOf(agent) {
|
|
35
|
-
if (isBuiltWorkflow(agent) || agent.manifest.kind === "workflow")
|
|
36
|
-
return [];
|
|
37
|
-
const built = agent.build?.() ?? agent;
|
|
38
|
-
if (isBuiltWorkflow(built))
|
|
39
|
-
return [];
|
|
40
|
-
const binding = built.getBinding?.();
|
|
41
|
-
if (!binding || !("parts" in binding))
|
|
42
|
-
return [];
|
|
43
|
-
const found = [...(binding.parts ?? [])];
|
|
44
|
-
for (const tool of binding.tools ?? []) {
|
|
45
|
-
const delegate = delegateOf(tool);
|
|
46
|
-
found.push(...(delegate?.agent?.getBinding().parts ?? []));
|
|
47
|
-
// A flow agent used as a tool: its agents' declarations.
|
|
48
|
-
for (const leaf of Object.values(delegate?.workflow?.getBinding().agents ?? {}))
|
|
49
|
-
found.push(...(leaf.parts ?? []));
|
|
50
|
-
}
|
|
51
|
-
return found;
|
|
52
|
-
}
|
|
53
|
-
/** The bytes of every skill file the agent's definition names, by `sha256:<hex>`. */
|
|
54
|
-
function skillFilesOf(agent, into = new Map()) {
|
|
55
|
-
for (const item of declarationsOf(agent))
|
|
56
|
-
for (const [sha256, source] of Object.entries(item.skillFiles ?? {}))
|
|
57
|
-
into.set(sha256, source);
|
|
58
|
-
return into;
|
|
59
|
-
}
|
|
60
34
|
export class AgentsClient {
|
|
61
35
|
transport;
|
|
62
36
|
/** The subject this client acts for (`as`), or `undefined` for the principal itself. */
|
|
@@ -92,12 +66,19 @@ export class AgentsClient {
|
|
|
92
66
|
return new AccessClient(this.transport);
|
|
93
67
|
}
|
|
94
68
|
/**
|
|
95
|
-
*
|
|
96
|
-
* `
|
|
97
|
-
*
|
|
69
|
+
* Agent manifests (protocol 16): `save` a manifest's next version (a v8 document, what
|
|
70
|
+
* `composeManifest` read, or a built agent with its runtime section), `plan` a save, read
|
|
71
|
+
* their versions.
|
|
98
72
|
*/
|
|
99
|
-
get
|
|
100
|
-
return new
|
|
73
|
+
get agentManifests() {
|
|
74
|
+
return new AgentManifestsClient(this.transport);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Agents (protocol 16): `put` one by id from a saved manifest (create or find), write its
|
|
78
|
+
* `secrets`, `list` them, `stop`, `reset`, `fork` or `delete` one. Sessions run on them.
|
|
79
|
+
*/
|
|
80
|
+
get agents() {
|
|
81
|
+
return new AgentInstancesClient(this.transport);
|
|
101
82
|
}
|
|
102
83
|
/** File artifacts: upload, list, download with Range, capability links (protocol 6). */
|
|
103
84
|
get artifacts() {
|
|
@@ -114,54 +95,19 @@ export class AgentsClient {
|
|
|
114
95
|
get sessions() {
|
|
115
96
|
return new SessionsReadClient(this.transport);
|
|
116
97
|
}
|
|
117
|
-
listAgents(options = {}) {
|
|
118
|
-
return this.transport.json("/v1/agents", "GET", undefined, options.signal);
|
|
119
|
-
}
|
|
120
98
|
listSessions(options = {}) {
|
|
121
99
|
const query = options.agentId
|
|
122
100
|
? `?agentId=${encodeURIComponent(options.agentId)}`
|
|
123
101
|
: "";
|
|
124
102
|
return this.transport.json(`/v1/sessions${query}`, "GET", undefined, options.signal);
|
|
125
103
|
}
|
|
126
|
-
/**
|
|
127
|
-
* Registers the agent's definition (`PUT /v1/agents/{id}`), first uploading the skill files
|
|
128
|
-
* it names that the Runtime does not hold. A definition with a tool that runs your code
|
|
129
|
-
* (`tool({ run })`, a flow's tool stage) is refused before anything is sent: the Runtime runs
|
|
130
|
-
* agents from their manifests alone. `implementationVersion` defaults to
|
|
131
|
-
* `NYLORUN_IMPLEMENTATION_VERSION`, else `dev`. `dryRun` (protocol 14) runs every check and
|
|
132
|
-
* saves nothing; the skill files are still uploaded, since they are stored by content.
|
|
133
|
-
*/
|
|
134
|
-
async saveAgent(agent, options = {}) {
|
|
135
|
-
const files = new Map();
|
|
136
|
-
if (isBuiltWorkflow(agent)) {
|
|
137
|
-
// A flow agent embeds its agents: one document, carrying their files.
|
|
138
|
-
for (const binding of Object.values(agent.getBinding().agents)) {
|
|
139
|
-
const leaf = { id: binding.manifest.id, manifest: binding.manifest, getBinding: () => binding };
|
|
140
|
-
skillFilesOf(leaf, files);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
skillFilesOf(agent, files);
|
|
145
|
-
}
|
|
146
|
-
const refusal = codeToolRefusal(agent.manifest) ??
|
|
147
|
-
approvalRefusal(agent.manifest);
|
|
148
|
-
if (refusal)
|
|
149
|
-
throw new Error(refusal);
|
|
150
|
-
await this.files.ensure(files);
|
|
151
|
-
return this.transport.json(`/v1/agents/${segment(agent.id)}${options.dryRun ? "?dryRun=true" : ""}`, "PUT", {
|
|
152
|
-
requestId: options.requestId ?? id(),
|
|
153
|
-
manifest: agent.manifest,
|
|
154
|
-
implementationVersion: options.implementationVersion ?? env("NYLORUN_IMPLEMENTATION_VERSION") ?? "dev",
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
104
|
async createSession(options) {
|
|
158
105
|
const sessionId = options.id ?? id();
|
|
159
106
|
await this.transport.json(`/v1/sessions/${segment(sessionId)}`, "PUT", {
|
|
160
107
|
requestId: options.requestId ?? id(),
|
|
161
|
-
|
|
108
|
+
agent: options.agent,
|
|
162
109
|
ownerUserId: options.ownerUserId,
|
|
163
110
|
...(options.info ? { info: options.info } : {}),
|
|
164
|
-
...(options.environment === undefined ? {} : { environment: options.environment }),
|
|
165
111
|
});
|
|
166
112
|
return this.session(sessionId);
|
|
167
113
|
}
|
|
@@ -189,6 +135,7 @@ export class SessionClient {
|
|
|
189
135
|
const view = await this.inspect(signal);
|
|
190
136
|
return view.waits ?? [];
|
|
191
137
|
}
|
|
138
|
+
/** A message answers `queued` when it waits for the running turn (protocol 17). */
|
|
192
139
|
command(command, signal) {
|
|
193
140
|
return this.transport.json(`${this.path}/commands`, "POST", command, signal);
|
|
194
141
|
}
|
|
@@ -201,6 +148,7 @@ export class SessionClient {
|
|
|
201
148
|
type: "message",
|
|
202
149
|
requestId: options.requestId ?? id(),
|
|
203
150
|
idempotencyKey: options.idempotencyKey,
|
|
151
|
+
...(options.delivery ? { delivery: options.delivery } : {}),
|
|
204
152
|
};
|
|
205
153
|
return this.command(typeof value === "string"
|
|
206
154
|
? { ...base, content: value }
|
|
@@ -217,6 +165,7 @@ export class SessionClient {
|
|
|
217
165
|
requestId: options.requestId ?? id(),
|
|
218
166
|
idempotencyKey: options.idempotencyKey,
|
|
219
167
|
parts: [...parts],
|
|
168
|
+
...(options.delivery ? { delivery: options.delivery } : {}),
|
|
220
169
|
}, options.signal);
|
|
221
170
|
}
|
|
222
171
|
approve(interactionId, approved, options) {
|
|
@@ -266,7 +215,7 @@ export class SessionClient {
|
|
|
266
215
|
return ModelCallsPageSchema.parse(await this.transport.json(`${this.path}/calls/model?${query}`, "GET", undefined, options.signal));
|
|
267
216
|
}
|
|
268
217
|
/**
|
|
269
|
-
* The session's tool calls (
|
|
218
|
+
* The session's tool calls (Host feature `tool-calls`), in the order they were first sent:
|
|
270
219
|
* each one's tool, input, status and sends. `attempts` above 1: a crash re-sent it.
|
|
271
220
|
*/
|
|
272
221
|
async toolCalls(options = {}) {
|
|
@@ -279,7 +228,7 @@ export class SessionClient {
|
|
|
279
228
|
return ToolCallsPageSchema.parse(await this.transport.json(`${this.path}/calls/tool?${query}`, "GET", undefined, options.signal));
|
|
280
229
|
}
|
|
281
230
|
/**
|
|
282
|
-
* A turn's trace (
|
|
231
|
+
* A turn's trace (Host feature `traces`): its spans as OTLP/HTTP JSON (`resourceSpans`), as
|
|
283
232
|
* the Runtime posts them to an OTLP collector. Post it to a collector's `/v1/traces` to backfill
|
|
284
233
|
* one, or read it without one.
|
|
285
234
|
*/
|
|
@@ -385,4 +334,5 @@ export class SessionClient {
|
|
|
385
334
|
}
|
|
386
335
|
export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
|
|
387
336
|
export { AccessClient } from "./access.js";
|
|
388
|
-
export {
|
|
337
|
+
export { AgentInstancesClient, AgentMemoriesClient, AgentSecretsClient, runtimeFiles } from "./agents.js";
|
|
338
|
+
export { AgentManifestsClient, ManifestGapsError, agentManifest, requirementGaps } from "./agent-manifests.js";
|
package/dist/skills/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
|
|
1
|
+
export { hashFolder, loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
|
|
2
2
|
export type { LoadedSkill, SkillDiagnostic } from "./load.js";
|
package/dist/skills/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
|
|
1
|
+
export { hashFolder, loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
|
package/dist/skills/load.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export declare class SkillsError extends Error {
|
|
|
14
14
|
export interface LoadedSkill {
|
|
15
15
|
readonly name: string;
|
|
16
16
|
readonly description: string;
|
|
17
|
+
/**
|
|
18
|
+
* The `runtime.secrets` slots its scripts read (`environment_secret` or `environment_variable`),
|
|
19
|
+
* from its SKILL.md's frontmatter `secrets`: sorted, each once.
|
|
20
|
+
*/
|
|
21
|
+
readonly secrets?: readonly string[];
|
|
17
22
|
/** Every file of the folder by its `/`-separated path, as `sha256:<hex>`. */
|
|
18
23
|
readonly files: Readonly<Record<string, string>>;
|
|
19
24
|
/** Each file's bytes, by `sha256:<hex>`, for the client to upload. */
|
|
@@ -32,8 +37,21 @@ export declare function loadSkillsFromDirectory(directory: string, diagnostics:
|
|
|
32
37
|
readonly boundary?: string;
|
|
33
38
|
readonly codePrefix?: string;
|
|
34
39
|
}): Readonly<Record<string, LoadedSkill>>;
|
|
35
|
-
|
|
40
|
+
/** A SKILL.md's frontmatter and instructions: `secrets` lists the secret slots its scripts read. */
|
|
41
|
+
export interface ParsedSkill {
|
|
36
42
|
name: string;
|
|
37
43
|
description: string;
|
|
44
|
+
secrets?: string[];
|
|
38
45
|
instructions: string;
|
|
39
|
-
}
|
|
46
|
+
}
|
|
47
|
+
export declare function parseSkill(text: string, directoryName: string): ParsedSkill | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Every file of `directory` (a runtime section's `files` entry with `from`), hashed as a skill's
|
|
50
|
+
* folder is: each by its `/`-separated path, with where to read its bytes. Version control, OS
|
|
51
|
+
* and `.env` files are left out; a symbolic link outside `boundary` (default the folder) is
|
|
52
|
+
* skipped with a diagnostic.
|
|
53
|
+
*/
|
|
54
|
+
export declare function hashFolder(directory: string, diagnostics: SkillDiagnostic[], options?: {
|
|
55
|
+
readonly boundary?: string;
|
|
56
|
+
readonly codePrefix?: string;
|
|
57
|
+
}): Pick<LoadedSkill, "files" | "sources">;
|
package/dist/skills/load.js
CHANGED
|
@@ -3,6 +3,7 @@ import { closeSync, existsSync, openSync, readdirSync, readFileSync, readSync, r
|
|
|
3
3
|
import { open } from "node:fs/promises";
|
|
4
4
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { SKILL_ENTRY, skillFilePathIssue, } from "@nylorun/core/define";
|
|
6
|
+
import { ENVIRONMENT_NAME_PATTERN } from "@nylorun/core/contracts";
|
|
6
7
|
import matter from "gray-matter";
|
|
7
8
|
const SKILL_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
8
9
|
/** Version control and operating system files, never part of a skill. */
|
|
@@ -71,12 +72,12 @@ export function loadSkillsFromDirectory(directory, diagnostics, options = {}) {
|
|
|
71
72
|
});
|
|
72
73
|
continue;
|
|
73
74
|
}
|
|
74
|
-
const parsed =
|
|
75
|
-
if (
|
|
75
|
+
const parsed = readSkill(readFileSync(skillReal, "utf8"), entry.name);
|
|
76
|
+
if (typeof parsed === "string") {
|
|
76
77
|
diagnostics.push({
|
|
77
78
|
severity: "warning",
|
|
78
79
|
code: `${prefix}.skill-skipped`,
|
|
79
|
-
message: `Skipped skill '${entry.name}' because SKILL.md
|
|
80
|
+
message: `Skipped skill '${entry.name}' because SKILL.md ${parsed}`,
|
|
80
81
|
path: skillFile,
|
|
81
82
|
});
|
|
82
83
|
continue;
|
|
@@ -93,36 +94,61 @@ export function loadSkillsFromDirectory(directory, diagnostics, options = {}) {
|
|
|
93
94
|
skills[parsed.name] = {
|
|
94
95
|
name: parsed.name,
|
|
95
96
|
description: parsed.description,
|
|
96
|
-
...
|
|
97
|
+
...(parsed.secrets === undefined ? {} : { secrets: parsed.secrets }),
|
|
98
|
+
...readFiles(`skill '${parsed.name}'`, boundary, directoryReal, diagnostics, prefix),
|
|
97
99
|
};
|
|
98
100
|
}
|
|
99
101
|
return skills;
|
|
100
102
|
}
|
|
101
103
|
export function parseSkill(text, directoryName) {
|
|
104
|
+
const parsed = readSkill(text, directoryName);
|
|
105
|
+
return typeof parsed === "string" ? undefined : parsed;
|
|
106
|
+
}
|
|
107
|
+
const INVALID_SKILL = "is not a valid Agent Skill";
|
|
108
|
+
/** The skill a SKILL.md declares, or why it declares none. */
|
|
109
|
+
function readSkill(text, directoryName) {
|
|
102
110
|
let parsed;
|
|
103
111
|
try {
|
|
104
112
|
parsed = matter(text);
|
|
105
113
|
}
|
|
106
114
|
catch {
|
|
107
|
-
return
|
|
115
|
+
return INVALID_SKILL;
|
|
108
116
|
}
|
|
109
117
|
const name = asTrimmedString(parsed.data.name);
|
|
110
118
|
const description = asTrimmedString(parsed.data.description);
|
|
111
119
|
if (!name || !description || description.length > 1024)
|
|
112
|
-
return
|
|
120
|
+
return INVALID_SKILL;
|
|
113
121
|
if (name.length > 64 || !SKILL_NAME.test(name) || name !== directoryName)
|
|
114
|
-
return
|
|
122
|
+
return INVALID_SKILL;
|
|
123
|
+
const secrets = parsed.data.secrets;
|
|
124
|
+
if (secrets !== undefined &&
|
|
125
|
+
(!Array.isArray(secrets) ||
|
|
126
|
+
!secrets.every((item) => typeof item === "string" && ENVIRONMENT_NAME_PATTERN.test(item))))
|
|
127
|
+
return "has secrets that are not a list of environment variable names";
|
|
115
128
|
return {
|
|
116
129
|
name,
|
|
117
130
|
description,
|
|
131
|
+
...(secrets === undefined || secrets.length === 0
|
|
132
|
+
? {}
|
|
133
|
+
: { secrets: [...new Set(secrets)].sort() }),
|
|
118
134
|
instructions: parsed.content.replace(/^\r?\n/, ""),
|
|
119
135
|
};
|
|
120
136
|
}
|
|
121
137
|
function asTrimmedString(value) {
|
|
122
138
|
return typeof value === "string" ? value.trim() : "";
|
|
123
139
|
}
|
|
124
|
-
/**
|
|
125
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Every file of `directory` (a runtime section's `files` entry with `from`), hashed as a skill's
|
|
142
|
+
* folder is: each by its `/`-separated path, with where to read its bytes. Version control, OS
|
|
143
|
+
* and `.env` files are left out; a symbolic link outside `boundary` (default the folder) is
|
|
144
|
+
* skipped with a diagnostic.
|
|
145
|
+
*/
|
|
146
|
+
export function hashFolder(directory, diagnostics, options = {}) {
|
|
147
|
+
const root = resolveSkillsRoot(directory);
|
|
148
|
+
return readFiles(`folder ${directory}`, options.boundary ?? root, root, diagnostics, options.codePrefix ?? "files");
|
|
149
|
+
}
|
|
150
|
+
/** Every file of the folder, hashed, and where to read each one's bytes. */
|
|
151
|
+
function readFiles(label, boundary, directory, diagnostics, prefix) {
|
|
126
152
|
const files = {};
|
|
127
153
|
const sources = {};
|
|
128
154
|
const visited = new Set();
|
|
@@ -138,7 +164,7 @@ function readFiles(name, boundary, directory, diagnostics, prefix) {
|
|
|
138
164
|
diagnostics.push({
|
|
139
165
|
severity: "warning",
|
|
140
166
|
code: `${prefix}.resource-denied`,
|
|
141
|
-
message: `Denied a file of
|
|
167
|
+
message: `Denied a file of ${label} outside the package: ${entry.name}`,
|
|
142
168
|
path: full,
|
|
143
169
|
});
|
|
144
170
|
continue;
|
|
@@ -154,7 +180,7 @@ function readFiles(name, boundary, directory, diagnostics, prefix) {
|
|
|
154
180
|
continue;
|
|
155
181
|
const issue = skillFilePathIssue(path);
|
|
156
182
|
if (issue)
|
|
157
|
-
throw new SkillsError(`${prefix}.invalid-path`,
|
|
183
|
+
throw new SkillsError(`${prefix}.invalid-path`, `${label[0].toUpperCase()}${label.slice(1)} has a file whose path ${issue}: ${path}`);
|
|
158
184
|
const hash = hashFile(real);
|
|
159
185
|
files[path] = hash;
|
|
160
186
|
sources[hash] = { size: stats.size, read: () => readWhole(real, stats.size) };
|
package/dist/skills/skills.d.ts
CHANGED
|
@@ -18,13 +18,15 @@ export interface SkillsPart extends PartDeclaration {
|
|
|
18
18
|
* ```
|
|
19
19
|
*
|
|
20
20
|
* Sets `skills`: each skill's name, description and files (every file of its folder, binary
|
|
21
|
-
* included, by content hash).
|
|
22
|
-
* the
|
|
23
|
-
*
|
|
21
|
+
* included, by content hash). A SKILL.md's frontmatter `secrets` (environment variable names)
|
|
22
|
+
* become the skill's `secrets` in the harness section when the agent's manifest is saved. The
|
|
23
|
+
* client uploads the files the Runtime lacks when it saves the agent's manifest; the Runtime adds
|
|
24
|
+
* the skill catalog and serves `load_skill` / `read_skill_resource` from them.
|
|
24
25
|
*/
|
|
25
26
|
export declare function skills(directory: string): SkillsPart;
|
|
26
27
|
/**
|
|
27
|
-
* The manifest's skills
|
|
28
|
-
*
|
|
28
|
+
* The manifest's skills, the bytes behind their files and the secret slots their SKILL.md lists
|
|
29
|
+
* (`secrets`, the harness section's when the agent is saved). A plugin's skills carry its label,
|
|
30
|
+
* so a tool call can be traced to the plugin that brought the skill.
|
|
29
31
|
*/
|
|
30
|
-
export declare function skillsDeclaration(listed: readonly LoadedSkill[], plugin?: PluginLabel): Required<Pick<PartDeclaration, "skills" | "skillFiles"
|
|
32
|
+
export declare function skillsDeclaration(listed: readonly LoadedSkill[], plugin?: PluginLabel): Required<Pick<PartDeclaration, "skills" | "skillFiles">> & Pick<PartDeclaration, "skillSecrets">;
|
package/dist/skills/skills.js
CHANGED
|
@@ -13,9 +13,10 @@ import { loadSkillsFromDirectory, resolveSkillsRoot, } from "./load.js";
|
|
|
13
13
|
* ```
|
|
14
14
|
*
|
|
15
15
|
* Sets `skills`: each skill's name, description and files (every file of its folder, binary
|
|
16
|
-
* included, by content hash).
|
|
17
|
-
* the
|
|
18
|
-
*
|
|
16
|
+
* included, by content hash). A SKILL.md's frontmatter `secrets` (environment variable names)
|
|
17
|
+
* become the skill's `secrets` in the harness section when the agent's manifest is saved. The
|
|
18
|
+
* client uploads the files the Runtime lacks when it saves the agent's manifest; the Runtime adds
|
|
19
|
+
* the skill catalog and serves `load_skill` / `read_skill_resource` from them.
|
|
19
20
|
*/
|
|
20
21
|
export function skills(directory) {
|
|
21
22
|
const root = resolveSkillsRoot(directory);
|
|
@@ -29,10 +30,12 @@ export function skills(directory) {
|
|
|
29
30
|
return { id, root, ...skillsDeclaration(listed), diagnostics };
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
|
-
* The manifest's skills
|
|
33
|
-
*
|
|
33
|
+
* The manifest's skills, the bytes behind their files and the secret slots their SKILL.md lists
|
|
34
|
+
* (`secrets`, the harness section's when the agent is saved). A plugin's skills carry its label,
|
|
35
|
+
* so a tool call can be traced to the plugin that brought the skill.
|
|
34
36
|
*/
|
|
35
37
|
export function skillsDeclaration(listed, plugin) {
|
|
38
|
+
const secrets = listed.filter((skill) => skill.secrets !== undefined).map((skill) => [skill.name, skill.secrets]);
|
|
36
39
|
return {
|
|
37
40
|
skills: Object.fromEntries(listed.map((skill) => [
|
|
38
41
|
skill.name,
|
|
@@ -44,5 +47,6 @@ export function skillsDeclaration(listed, plugin) {
|
|
|
44
47
|
},
|
|
45
48
|
])),
|
|
46
49
|
skillFiles: Object.assign({}, ...listed.map((skill) => skill.sources)),
|
|
50
|
+
...(secrets.length === 0 ? {} : { skillSecrets: Object.fromEntries(secrets) }),
|
|
47
51
|
};
|
|
48
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0-beta",
|
|
4
4
|
"description": "Nylorun agent definitions and session client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"test": "vitest run --passWithNoTests"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@nylorun/core": "0.
|
|
46
|
+
"@nylorun/core": "0.25.0-beta",
|
|
47
47
|
"gray-matter": "^4.0.3"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"zod": "^4.6.
|
|
50
|
+
"zod": "^4.6.7"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@types/node": "^26.6.
|
|
53
|
+
"@types/node": "^26.6.5",
|
|
54
54
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
55
|
-
"vitest": "^5.0.
|
|
55
|
+
"vitest": "^5.0.4"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=24"
|