@nylorun/agents 0.20.0-beta → 0.22.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 +138 -0
- package/README.md +97 -34
- package/dist/builder.d.ts +2 -3
- package/dist/builder.js +5 -5
- package/dist/client.d.ts +1 -1
- package/dist/connection.d.ts +1 -1
- package/dist/connection.js +1 -1
- package/dist/environments.d.ts +193 -23
- package/dist/environments.js +139 -14
- package/dist/http.js +2 -2
- package/dist/index.d.ts +10 -12
- package/dist/index.js +5 -6
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +1 -1
- package/dist/plugins/load.d.ts +1 -0
- package/dist/plugins/load.js +1 -0
- package/dist/plugins/plugin.d.ts +9 -5
- package/dist/plugins/plugin.js +19 -21
- package/dist/session-client.d.ts +12 -8
- package/dist/session-client.js +8 -15
- package/dist/skills/index.d.ts +1 -3
- package/dist/skills/index.js +1 -2
- package/dist/skills/skills.d.ts +11 -11
- package/dist/skills/skills.js +17 -23
- package/package.json +2 -2
- package/dist/skills/catalog.d.ts +0 -5
- package/dist/skills/catalog.js +0 -14
package/dist/plugins/plugin.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PartDeclaration } from "@nylorun/core/define";
|
|
2
2
|
import { type LoadedPlugin, type PluginDiagnostic } from "./load.js";
|
|
3
|
-
export interface
|
|
3
|
+
export interface PluginPart extends PartDeclaration {
|
|
4
4
|
readonly diagnostics: readonly PluginDiagnostic[];
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
* Read an Agent Plugin package
|
|
7
|
+
* Read an Agent Plugin package as one part of an agent, for `.plugin()`. Each part it skips
|
|
8
8
|
* (an invalid MCP server or skill) is a process warning, so building or registering the agent
|
|
9
9
|
* says why the agent has less than the package declares. A stdio MCP server throws: Nylorun
|
|
10
10
|
* accepts remote servers only.
|
|
11
11
|
*/
|
|
12
|
-
export declare function plugin(directory: string):
|
|
13
|
-
|
|
12
|
+
export declare function plugin(directory: string): PluginPart;
|
|
13
|
+
/**
|
|
14
|
+
* The part a plugin adds: its skills and remote MCP servers, each labelled with the plugin's name
|
|
15
|
+
* and version. The plugin itself is not in the manifest; the labels say where each part came from.
|
|
16
|
+
*/
|
|
17
|
+
export declare function partFromPlugin(loaded: LoadedPlugin): PluginPart;
|
package/dist/plugins/plugin.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { formatSkillCatalog, SKILLS_USAGE } from "../skills/catalog.js";
|
|
2
1
|
import { skillsDeclaration } from "../skills/skills.js";
|
|
3
2
|
import { loadPlugin, } from "./load.js";
|
|
4
3
|
/**
|
|
5
|
-
* Read an Agent Plugin package
|
|
4
|
+
* Read an Agent Plugin package as one part of an agent, for `.plugin()`. Each part it skips
|
|
6
5
|
* (an invalid MCP server or skill) is a process warning, so building or registering the agent
|
|
7
6
|
* says why the agent has less than the package declares. A stdio MCP server throws: Nylorun
|
|
8
7
|
* accepts remote servers only.
|
|
@@ -10,7 +9,7 @@ import { loadPlugin, } from "./load.js";
|
|
|
10
9
|
export function plugin(directory) {
|
|
11
10
|
const loaded = loadPlugin(directory);
|
|
12
11
|
warn(loaded);
|
|
13
|
-
return
|
|
12
|
+
return partFromPlugin(loaded);
|
|
14
13
|
}
|
|
15
14
|
function warn(loaded) {
|
|
16
15
|
for (const diagnostic of loaded.diagnostics) {
|
|
@@ -23,26 +22,25 @@ function warn(loaded) {
|
|
|
23
22
|
});
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
/**
|
|
26
|
+
* The part a plugin adds: its skills and remote MCP servers, each labelled with the plugin's name
|
|
27
|
+
* and version. The plugin itself is not in the manifest; the labels say where each part came from.
|
|
28
|
+
*/
|
|
29
|
+
export function partFromPlugin(loaded) {
|
|
30
|
+
const label = {
|
|
31
|
+
name: loaded.name,
|
|
32
|
+
...(loaded.version === undefined ? {} : { version: loaded.version }),
|
|
33
|
+
};
|
|
34
|
+
const skills = Object.values(loaded.skills);
|
|
35
|
+
const servers = Object.entries(loaded.mcpServers);
|
|
37
36
|
return {
|
|
38
|
-
id: loaded.name
|
|
39
|
-
|
|
40
|
-
...(
|
|
41
|
-
...(instructions === undefined ? {} : { instructions }),
|
|
42
|
-
...(names.length === 0 ? {} : skillsDeclaration(names)),
|
|
43
|
-
...(Object.keys(loaded.mcpServers).length === 0
|
|
37
|
+
id: `plugin:${loaded.name}`,
|
|
38
|
+
...(skills.length === 0 ? {} : skillsDeclaration(skills, label)),
|
|
39
|
+
...(servers.length === 0
|
|
44
40
|
? {}
|
|
45
|
-
: {
|
|
41
|
+
: {
|
|
42
|
+
mcpServers: Object.fromEntries(servers.map(([name, server]) => [name, { ...server, plugin: label }])),
|
|
43
|
+
}),
|
|
46
44
|
diagnostics: loaded.diagnostics,
|
|
47
45
|
};
|
|
48
46
|
}
|
package/dist/session-client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The Runtime API client classes, with no Node-only imports. `client.ts` adds `createClient`,
|
|
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";
|
|
@@ -20,8 +20,6 @@ export interface AgentSource {
|
|
|
20
20
|
build?(): BuiltAgent | BuiltWorkflow;
|
|
21
21
|
getBinding?: BuiltAgent["getBinding"] | BuiltWorkflow["getBinding"];
|
|
22
22
|
}
|
|
23
|
-
/** Closures stay on the live binding. The published manifest cannot name them. */
|
|
24
|
-
export declare function assertNoMiddlewareClosures(agent: AgentSource): void;
|
|
25
23
|
export interface SessionView {
|
|
26
24
|
id: string;
|
|
27
25
|
agentId: string;
|
|
@@ -96,11 +94,13 @@ export declare class AgentsClient {
|
|
|
96
94
|
* it names that the Runtime does not hold. A definition with a tool that runs your code
|
|
97
95
|
* (`tool({ run })`, a flow's tool stage) is refused before anything is sent: the Runtime runs
|
|
98
96
|
* agents from their manifests alone. `implementationVersion` defaults to
|
|
99
|
-
* `NYLORUN_IMPLEMENTATION_VERSION`, else `dev`.
|
|
97
|
+
* `NYLORUN_IMPLEMENTATION_VERSION`, else `dev`. `dryRun` (protocol 14) runs every check and
|
|
98
|
+
* saves nothing; the skill files are still uploaded, since they are stored by content.
|
|
100
99
|
*/
|
|
101
100
|
saveAgent(agent: AgentSource | BuiltWorkflow, options?: {
|
|
102
101
|
implementationVersion?: string;
|
|
103
102
|
requestId?: string;
|
|
103
|
+
dryRun?: boolean;
|
|
104
104
|
}): Promise<unknown>;
|
|
105
105
|
createSession(options: CreateSessionOptions): Promise<SessionClient>;
|
|
106
106
|
session(sessionId: string): SessionClient;
|
|
@@ -241,10 +241,14 @@ export declare class SessionClient {
|
|
|
241
241
|
effectId: string;
|
|
242
242
|
turnId: string;
|
|
243
243
|
callId: string | null;
|
|
244
|
-
capabilityId: string | null;
|
|
245
244
|
toolName: string | null;
|
|
246
|
-
kind: "http" | "mcp" | "platform" | "sandbox" | null;
|
|
245
|
+
kind: "harness" | "http" | "mcp" | "platform" | "sandbox" | null;
|
|
247
246
|
server: string | null;
|
|
247
|
+
skill: string | null;
|
|
248
|
+
plugin: {
|
|
249
|
+
name: string;
|
|
250
|
+
version?: string | undefined;
|
|
251
|
+
} | null;
|
|
248
252
|
status: "cancelled" | "completed" | "failed" | "held" | "invoking" | "uncertain";
|
|
249
253
|
attempts: number;
|
|
250
254
|
input: unknown;
|
|
@@ -369,5 +373,5 @@ export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
|
|
|
369
373
|
export type { Destination, IncompatibleReason } from "./http.js";
|
|
370
374
|
export type { LiveEvent } from "@nylorun/core/contracts";
|
|
371
375
|
export { AccessClient } from "./access.js";
|
|
372
|
-
export { EnvironmentSecretsClient, EnvironmentsClient } from "./environments.js";
|
|
373
|
-
export type {
|
|
376
|
+
export { EnvironmentManifestsClient, EnvironmentSecretsClient, EnvironmentsClient, environmentFiles, environmentManifest, } from "./environments.js";
|
|
377
|
+
export type { EnvironmentFileBytes, EnvironmentInput, EnvironmentManifestInput, EnvironmentSecretInput, ForSessionOptions, SessionEnvironmentHandle, } from "./environments.js";
|
package/dist/session-client.js
CHANGED
|
@@ -30,7 +30,6 @@ function linkedSessionId(event) {
|
|
|
30
30
|
? sessionId
|
|
31
31
|
: undefined;
|
|
32
32
|
}
|
|
33
|
-
const middlewareClosure = "Hosted definitions support declarative capabilities, not middleware closures";
|
|
34
33
|
/** The agent's declarations, then those of each agent it uses as a tool. */
|
|
35
34
|
function declarationsOf(agent) {
|
|
36
35
|
if (isBuiltWorkflow(agent) || agent.manifest.kind === "workflow")
|
|
@@ -39,15 +38,15 @@ function declarationsOf(agent) {
|
|
|
39
38
|
if (isBuiltWorkflow(built))
|
|
40
39
|
return [];
|
|
41
40
|
const binding = built.getBinding?.();
|
|
42
|
-
if (!binding || !("
|
|
41
|
+
if (!binding || !("parts" in binding))
|
|
43
42
|
return [];
|
|
44
|
-
const found = [...(binding.
|
|
43
|
+
const found = [...(binding.parts ?? [])];
|
|
45
44
|
for (const tool of binding.tools ?? []) {
|
|
46
45
|
const delegate = delegateOf(tool);
|
|
47
|
-
found.push(...(delegate?.agent?.getBinding().
|
|
46
|
+
found.push(...(delegate?.agent?.getBinding().parts ?? []));
|
|
48
47
|
// A flow agent used as a tool: its agents' declarations.
|
|
49
48
|
for (const leaf of Object.values(delegate?.workflow?.getBinding().agents ?? {}))
|
|
50
|
-
found.push(...(leaf.
|
|
49
|
+
found.push(...(leaf.parts ?? []));
|
|
51
50
|
}
|
|
52
51
|
return found;
|
|
53
52
|
}
|
|
@@ -58,11 +57,6 @@ function skillFilesOf(agent, into = new Map()) {
|
|
|
58
57
|
into.set(sha256, source);
|
|
59
58
|
return into;
|
|
60
59
|
}
|
|
61
|
-
/** Closures stay on the live binding. The published manifest cannot name them. */
|
|
62
|
-
export function assertNoMiddlewareClosures(agent) {
|
|
63
|
-
if (declarationsOf(agent).some((item) => item.hasMiddleware))
|
|
64
|
-
throw new Error(middlewareClosure);
|
|
65
|
-
}
|
|
66
60
|
export class AgentsClient {
|
|
67
61
|
transport;
|
|
68
62
|
/** The subject this client acts for (`as`), or `undefined` for the principal itself. */
|
|
@@ -134,7 +128,8 @@ export class AgentsClient {
|
|
|
134
128
|
* it names that the Runtime does not hold. A definition with a tool that runs your code
|
|
135
129
|
* (`tool({ run })`, a flow's tool stage) is refused before anything is sent: the Runtime runs
|
|
136
130
|
* agents from their manifests alone. `implementationVersion` defaults to
|
|
137
|
-
* `NYLORUN_IMPLEMENTATION_VERSION`, else `dev`.
|
|
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.
|
|
138
133
|
*/
|
|
139
134
|
async saveAgent(agent, options = {}) {
|
|
140
135
|
const files = new Map();
|
|
@@ -142,12 +137,10 @@ export class AgentsClient {
|
|
|
142
137
|
// A flow agent embeds its agents: one document, carrying their files.
|
|
143
138
|
for (const binding of Object.values(agent.getBinding().agents)) {
|
|
144
139
|
const leaf = { id: binding.manifest.id, manifest: binding.manifest, getBinding: () => binding };
|
|
145
|
-
assertNoMiddlewareClosures(leaf);
|
|
146
140
|
skillFilesOf(leaf, files);
|
|
147
141
|
}
|
|
148
142
|
}
|
|
149
143
|
else {
|
|
150
|
-
assertNoMiddlewareClosures(agent);
|
|
151
144
|
skillFilesOf(agent, files);
|
|
152
145
|
}
|
|
153
146
|
const refusal = codeToolRefusal(agent.manifest) ??
|
|
@@ -155,7 +148,7 @@ export class AgentsClient {
|
|
|
155
148
|
if (refusal)
|
|
156
149
|
throw new Error(refusal);
|
|
157
150
|
await this.files.ensure(files);
|
|
158
|
-
return this.transport.json(`/v1/agents/${segment(agent.id)}`, "PUT", {
|
|
151
|
+
return this.transport.json(`/v1/agents/${segment(agent.id)}${options.dryRun ? "?dryRun=true" : ""}`, "PUT", {
|
|
159
152
|
requestId: options.requestId ?? id(),
|
|
160
153
|
manifest: agent.manifest,
|
|
161
154
|
implementationVersion: options.implementationVersion ?? env("NYLORUN_IMPLEMENTATION_VERSION") ?? "dev",
|
|
@@ -392,4 +385,4 @@ export class SessionClient {
|
|
|
392
385
|
}
|
|
393
386
|
export { RuntimeError, IncompatibleRuntimeError } from "./http.js";
|
|
394
387
|
export { AccessClient } from "./access.js";
|
|
395
|
-
export { EnvironmentSecretsClient, EnvironmentsClient } from "./environments.js";
|
|
388
|
+
export { EnvironmentManifestsClient, EnvironmentSecretsClient, EnvironmentsClient, environmentFiles, environmentManifest, } from "./environments.js";
|
package/dist/skills/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export { skills } from "./skills.js";
|
|
2
|
-
export type { SkillsCapability, SkillsOptions } from "./skills.js";
|
|
3
1
|
export { loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
|
|
4
2
|
export type { LoadedSkill, SkillDiagnostic } from "./load.js";
|
|
5
|
-
export { formatSkillCatalog, SKILLS_USAGE } from "
|
|
3
|
+
export { formatSkillCatalog, SKILLS_USAGE } from "@nylorun/core/define";
|
package/dist/skills/index.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export { skills } from "./skills.js";
|
|
2
1
|
export { loadSkillsFromDirectory, resolveSkillsRoot, parseSkill, SkillsError, } from "./load.js";
|
|
3
|
-
export { formatSkillCatalog, SKILLS_USAGE } from "
|
|
2
|
+
export { formatSkillCatalog, SKILLS_USAGE } from "@nylorun/core/define";
|
package/dist/skills/skills.d.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PartDeclaration, PluginLabel } from "@nylorun/core/define";
|
|
2
2
|
import { type LoadedSkill, type SkillDiagnostic } from "./load.js";
|
|
3
|
-
export interface
|
|
4
|
-
/** Capability id. Defaults to the catalog directory basename. */
|
|
5
|
-
readonly id?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface SkillsCapability extends CapabilityDeclaration {
|
|
3
|
+
export interface SkillsPart extends PartDeclaration {
|
|
8
4
|
readonly diagnostics: readonly SkillDiagnostic[];
|
|
9
5
|
/** Absolute catalog directory that was loaded. */
|
|
10
6
|
readonly root: string;
|
|
11
7
|
}
|
|
12
8
|
/**
|
|
13
|
-
* Load an agentskills.io catalog folder
|
|
9
|
+
* Load an agentskills.io catalog folder as one part of an agent, for `.skills()`.
|
|
14
10
|
*
|
|
15
11
|
* Expected layout:
|
|
16
12
|
* ```
|
|
@@ -23,8 +19,12 @@ export interface SkillsCapability extends CapabilityDeclaration {
|
|
|
23
19
|
*
|
|
24
20
|
* Sets `skills`: each skill's name, description and files (every file of its folder, binary
|
|
25
21
|
* included, by content hash). The client uploads the files the Runtime lacks when it registers
|
|
26
|
-
* the agent
|
|
22
|
+
* the agent; the Runtime adds the skill catalog and serves `load_skill` / `read_skill_resource`
|
|
23
|
+
* from them.
|
|
24
|
+
*/
|
|
25
|
+
export declare function skills(directory: string): SkillsPart;
|
|
26
|
+
/**
|
|
27
|
+
* The manifest's skills and the bytes behind their files. A plugin's skills carry its label, so
|
|
28
|
+
* a tool call can be traced to the plugin that brought the skill.
|
|
27
29
|
*/
|
|
28
|
-
export declare function
|
|
29
|
-
/** The manifest's skills and the bytes behind their files, for a capability declaration. */
|
|
30
|
-
export declare function skillsDeclaration(listed: readonly LoadedSkill[]): Required<Pick<CapabilityDeclaration, "skills" | "skillFiles">>;
|
|
30
|
+
export declare function skillsDeclaration(listed: readonly LoadedSkill[], plugin?: PluginLabel): Required<Pick<PartDeclaration, "skills" | "skillFiles">>;
|
package/dist/skills/skills.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
-
import { formatSkillCatalog, SKILLS_USAGE } from "./catalog.js";
|
|
3
2
|
import { loadSkillsFromDirectory, resolveSkillsRoot, } from "./load.js";
|
|
4
3
|
/**
|
|
5
|
-
* Load an agentskills.io catalog folder
|
|
4
|
+
* Load an agentskills.io catalog folder as one part of an agent, for `.skills()`.
|
|
6
5
|
*
|
|
7
6
|
* Expected layout:
|
|
8
7
|
* ```
|
|
@@ -15,39 +14,34 @@ import { loadSkillsFromDirectory, resolveSkillsRoot, } from "./load.js";
|
|
|
15
14
|
*
|
|
16
15
|
* Sets `skills`: each skill's name, description and files (every file of its folder, binary
|
|
17
16
|
* included, by content hash). The client uploads the files the Runtime lacks when it registers
|
|
18
|
-
* the agent
|
|
17
|
+
* the agent; the Runtime adds the skill catalog and serves `load_skill` / `read_skill_resource`
|
|
18
|
+
* from them.
|
|
19
19
|
*/
|
|
20
|
-
export function skills(directory
|
|
20
|
+
export function skills(directory) {
|
|
21
21
|
const root = resolveSkillsRoot(directory);
|
|
22
22
|
const diagnostics = [];
|
|
23
23
|
const loaded = loadSkillsFromDirectory(root, diagnostics);
|
|
24
24
|
const listed = Object.values(loaded);
|
|
25
|
-
const id =
|
|
25
|
+
const id = `skills:${basename(root)}`;
|
|
26
26
|
if (listed.length === 0) {
|
|
27
27
|
return { id, root, diagnostics };
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
id,
|
|
32
|
-
root,
|
|
33
|
-
instructions: [
|
|
34
|
-
SKILLS_USAGE,
|
|
35
|
-
formatSkillCatalog(listed.map((skill) => ({
|
|
36
|
-
name: skill.name,
|
|
37
|
-
description: skill.description,
|
|
38
|
-
}))),
|
|
39
|
-
],
|
|
40
|
-
skills: skillManifest,
|
|
41
|
-
skillFiles,
|
|
42
|
-
diagnostics,
|
|
43
|
-
};
|
|
29
|
+
return { id, root, ...skillsDeclaration(listed), diagnostics };
|
|
44
30
|
}
|
|
45
|
-
/**
|
|
46
|
-
|
|
31
|
+
/**
|
|
32
|
+
* The manifest's skills and the bytes behind their files. A plugin's skills carry its label, so
|
|
33
|
+
* a tool call can be traced to the plugin that brought the skill.
|
|
34
|
+
*/
|
|
35
|
+
export function skillsDeclaration(listed, plugin) {
|
|
47
36
|
return {
|
|
48
37
|
skills: Object.fromEntries(listed.map((skill) => [
|
|
49
38
|
skill.name,
|
|
50
|
-
{
|
|
39
|
+
{
|
|
40
|
+
name: skill.name,
|
|
41
|
+
description: skill.description,
|
|
42
|
+
files: skill.files,
|
|
43
|
+
...(plugin === undefined ? {} : { plugin }),
|
|
44
|
+
},
|
|
51
45
|
])),
|
|
52
46
|
skillFiles: Object.assign({}, ...listed.map((skill) => skill.sources)),
|
|
53
47
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0-beta",
|
|
4
4
|
"description": "Nylorun agent definitions and session client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"test": "vitest run --passWithNoTests"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@nylorun/core": "0.
|
|
46
|
+
"@nylorun/core": "0.22.0-beta",
|
|
47
47
|
"gray-matter": "^4.0.3"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
package/dist/skills/catalog.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export declare const SKILLS_USAGE = "The following skills provide specialized instructions. When a task matches a skill description, call load_skill with that name before proceeding.";
|
|
2
|
-
export declare function formatSkillCatalog(skills: readonly {
|
|
3
|
-
name: string;
|
|
4
|
-
description: string;
|
|
5
|
-
}[]): string;
|
package/dist/skills/catalog.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const SKILLS_USAGE = "The following skills provide specialized instructions. When a task matches a skill description, call load_skill with that name before proceeding.";
|
|
2
|
-
export function formatSkillCatalog(skills) {
|
|
3
|
-
const entries = skills
|
|
4
|
-
.map((skill) => ` <skill>\n <name>${escapeXml(skill.name)}</name>\n <description>${escapeXml(skill.description)}</description>\n </skill>`)
|
|
5
|
-
.join("\n");
|
|
6
|
-
return `<available_skills>\n${entries}\n</available_skills>`;
|
|
7
|
-
}
|
|
8
|
-
function escapeXml(value) {
|
|
9
|
-
return value
|
|
10
|
-
.replaceAll("&", "&")
|
|
11
|
-
.replaceAll("<", "<")
|
|
12
|
-
.replaceAll(">", ">")
|
|
13
|
-
.replaceAll('"', """);
|
|
14
|
-
}
|