@dexto/tools-builtins 1.10.4 → 1.11.0
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/dist/builtin-tools-factory.cjs +4 -8
- package/dist/builtin-tools-factory.d.ts +2 -3
- package/dist/builtin-tools-factory.d.ts.map +1 -1
- package/dist/builtin-tools-factory.js +4 -8
- package/dist/builtin-tools-factory.test.cjs +3 -4
- package/dist/builtin-tools-factory.test.js +3 -4
- package/dist/implementations/skill-load-tool.cjs +100 -0
- package/dist/implementations/skill-load-tool.d.ts +4 -0
- package/dist/implementations/skill-load-tool.d.ts.map +1 -0
- package/dist/implementations/skill-load-tool.js +76 -0
- package/dist/implementations/skill-load-tool.test.cjs +73 -0
- package/dist/implementations/skill-load-tool.test.d.ts +2 -0
- package/dist/implementations/skill-load-tool.test.d.ts.map +1 -0
- package/dist/implementations/skill-load-tool.test.js +72 -0
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/implementations/invoke-skill-tool.cjs +0 -92
- package/dist/implementations/invoke-skill-tool.d.ts +0 -10
- package/dist/implementations/invoke-skill-tool.d.ts.map +0 -1
- package/dist/implementations/invoke-skill-tool.js +0 -68
- package/dist/implementations/invoke-skill-tool.test.cjs +0 -98
- package/dist/implementations/invoke-skill-tool.test.d.ts +0 -2
- package/dist/implementations/invoke-skill-tool.test.d.ts.map +0 -1
- package/dist/implementations/invoke-skill-tool.test.js +0 -97
- package/dist/implementations/read-skill-tool.cjs +0 -90
- package/dist/implementations/read-skill-tool.d.ts +0 -9
- package/dist/implementations/read-skill-tool.d.ts.map +0 -1
- package/dist/implementations/read-skill-tool.js +0 -66
- package/dist/implementations/read-skill-tool.test.cjs +0 -82
- package/dist/implementations/read-skill-tool.test.d.ts +0 -2
- package/dist/implementations/read-skill-tool.test.d.ts.map +0 -1
- package/dist/implementations/read-skill-tool.test.js +0 -81
|
@@ -27,8 +27,7 @@ var import_zod = require("zod");
|
|
|
27
27
|
var import_ask_user_tool = require("./implementations/ask-user-tool.js");
|
|
28
28
|
var import_delegate_to_url_tool = require("./implementations/delegate-to-url-tool.js");
|
|
29
29
|
var import_get_resource_tool = require("./implementations/get-resource-tool.js");
|
|
30
|
-
var
|
|
31
|
-
var import_read_skill_tool = require("./implementations/read-skill-tool.js");
|
|
30
|
+
var import_skill_load_tool = require("./implementations/skill-load-tool.js");
|
|
32
31
|
var import_list_resources_tool = require("./implementations/list-resources-tool.js");
|
|
33
32
|
var import_http_request_tool = require("./implementations/http-request-tool.js");
|
|
34
33
|
var import_sleep_tool = require("./implementations/sleep-tool.js");
|
|
@@ -39,8 +38,7 @@ const BUILTIN_TOOL_NAMES = [
|
|
|
39
38
|
"delegate_to_url",
|
|
40
39
|
"list_resources",
|
|
41
40
|
"get_resource",
|
|
42
|
-
"
|
|
43
|
-
"read_skill",
|
|
41
|
+
"skill_load",
|
|
44
42
|
"http_request",
|
|
45
43
|
"sleep",
|
|
46
44
|
"web_search",
|
|
@@ -61,10 +59,8 @@ function createToolByName(name) {
|
|
|
61
59
|
return (0, import_list_resources_tool.createListResourcesTool)();
|
|
62
60
|
case "get_resource":
|
|
63
61
|
return (0, import_get_resource_tool.createGetResourceTool)();
|
|
64
|
-
case "
|
|
65
|
-
return (0,
|
|
66
|
-
case "read_skill":
|
|
67
|
-
return (0, import_read_skill_tool.createReadSkillTool)();
|
|
62
|
+
case "skill_load":
|
|
63
|
+
return (0, import_skill_load_tool.createSkillLoadTool)();
|
|
68
64
|
case "http_request":
|
|
69
65
|
return (0, import_http_request_tool.createHttpRequestTool)();
|
|
70
66
|
case "sleep":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { ToolFactory } from '@dexto/agent-config';
|
|
3
|
-
export declare const BUILTIN_TOOL_NAMES: readonly ["ask_user", "delegate_to_url", "list_resources", "get_resource", "
|
|
3
|
+
export declare const BUILTIN_TOOL_NAMES: readonly ["ask_user", "delegate_to_url", "list_resources", "get_resource", "skill_load", "http_request", "sleep", "web_search", "code_search"];
|
|
4
4
|
export type BuiltinToolName = (typeof BUILTIN_TOOL_NAMES)[number];
|
|
5
5
|
export declare const BuiltinToolsConfigSchema: z.ZodObject<{
|
|
6
6
|
type: z.ZodLiteral<"builtin-tools">;
|
|
@@ -8,8 +8,7 @@ export declare const BuiltinToolsConfigSchema: z.ZodObject<{
|
|
|
8
8
|
ask_user: "ask_user";
|
|
9
9
|
delegate_to_url: "delegate_to_url";
|
|
10
10
|
get_resource: "get_resource";
|
|
11
|
-
|
|
12
|
-
read_skill: "read_skill";
|
|
11
|
+
skill_load: "skill_load";
|
|
13
12
|
list_resources: "list_resources";
|
|
14
13
|
http_request: "http_request";
|
|
15
14
|
sleep: "sleep";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-tools-factory.d.ts","sourceRoot":"","sources":["../src/builtin-tools-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"builtin-tools-factory.d.ts","sourceRoot":"","sources":["../src/builtin-tools-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAYvD,eAAO,MAAM,kBAAkB,gJAUrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAIlE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;kBAKxB,CAAC;AAEd,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AA6B3E,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,kBAAkB,CAW/D,CAAC"}
|
|
@@ -2,8 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { createAskUserTool } from "./implementations/ask-user-tool.js";
|
|
3
3
|
import { createDelegateToUrlTool } from "./implementations/delegate-to-url-tool.js";
|
|
4
4
|
import { createGetResourceTool } from "./implementations/get-resource-tool.js";
|
|
5
|
-
import {
|
|
6
|
-
import { createReadSkillTool } from "./implementations/read-skill-tool.js";
|
|
5
|
+
import { createSkillLoadTool } from "./implementations/skill-load-tool.js";
|
|
7
6
|
import { createListResourcesTool } from "./implementations/list-resources-tool.js";
|
|
8
7
|
import { createHttpRequestTool } from "./implementations/http-request-tool.js";
|
|
9
8
|
import { createSleepTool } from "./implementations/sleep-tool.js";
|
|
@@ -14,8 +13,7 @@ const BUILTIN_TOOL_NAMES = [
|
|
|
14
13
|
"delegate_to_url",
|
|
15
14
|
"list_resources",
|
|
16
15
|
"get_resource",
|
|
17
|
-
"
|
|
18
|
-
"read_skill",
|
|
16
|
+
"skill_load",
|
|
19
17
|
"http_request",
|
|
20
18
|
"sleep",
|
|
21
19
|
"web_search",
|
|
@@ -36,10 +34,8 @@ function createToolByName(name) {
|
|
|
36
34
|
return createListResourcesTool();
|
|
37
35
|
case "get_resource":
|
|
38
36
|
return createGetResourceTool();
|
|
39
|
-
case "
|
|
40
|
-
return
|
|
41
|
-
case "read_skill":
|
|
42
|
-
return createReadSkillTool();
|
|
37
|
+
case "skill_load":
|
|
38
|
+
return createSkillLoadTool();
|
|
43
39
|
case "http_request":
|
|
44
40
|
return createHttpRequestTool();
|
|
45
41
|
case "sleep":
|
|
@@ -9,8 +9,7 @@ var import_builtin_tools_factory = require("./builtin-tools-factory.js");
|
|
|
9
9
|
"delegate_to_url",
|
|
10
10
|
"list_resources",
|
|
11
11
|
"get_resource",
|
|
12
|
-
"
|
|
13
|
-
"read_skill",
|
|
12
|
+
"skill_load",
|
|
14
13
|
"http_request",
|
|
15
14
|
"sleep",
|
|
16
15
|
"web_search",
|
|
@@ -20,8 +19,8 @@ var import_builtin_tools_factory = require("./builtin-tools-factory.js");
|
|
|
20
19
|
(0, import_vitest.it)("creates only the selected builtins when enabledTools is provided", () => {
|
|
21
20
|
const tools = import_builtin_tools_factory.builtinToolsFactory.create({
|
|
22
21
|
type: "builtin-tools",
|
|
23
|
-
enabledTools: ["ask_user", "
|
|
22
|
+
enabledTools: ["ask_user", "skill_load"]
|
|
24
23
|
});
|
|
25
|
-
(0, import_vitest.expect)(tools.map((t) => t.id)).toEqual(["ask_user", "
|
|
24
|
+
(0, import_vitest.expect)(tools.map((t) => t.id)).toEqual(["ask_user", "skill_load"]);
|
|
26
25
|
});
|
|
27
26
|
});
|
|
@@ -8,8 +8,7 @@ describe("builtinToolsFactory", () => {
|
|
|
8
8
|
"delegate_to_url",
|
|
9
9
|
"list_resources",
|
|
10
10
|
"get_resource",
|
|
11
|
-
"
|
|
12
|
-
"read_skill",
|
|
11
|
+
"skill_load",
|
|
13
12
|
"http_request",
|
|
14
13
|
"sleep",
|
|
15
14
|
"web_search",
|
|
@@ -19,8 +18,8 @@ describe("builtinToolsFactory", () => {
|
|
|
19
18
|
it("creates only the selected builtins when enabledTools is provided", () => {
|
|
20
19
|
const tools = builtinToolsFactory.create({
|
|
21
20
|
type: "builtin-tools",
|
|
22
|
-
enabledTools: ["ask_user", "
|
|
21
|
+
enabledTools: ["ask_user", "skill_load"]
|
|
23
22
|
});
|
|
24
|
-
expect(tools.map((t) => t.id)).toEqual(["ask_user", "
|
|
23
|
+
expect(tools.map((t) => t.id)).toEqual(["ask_user", "skill_load"]);
|
|
25
24
|
});
|
|
26
25
|
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var skill_load_tool_exports = {};
|
|
20
|
+
__export(skill_load_tool_exports, {
|
|
21
|
+
createSkillLoadTool: () => createSkillLoadTool
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(skill_load_tool_exports);
|
|
24
|
+
var import_core = require("@dexto/core");
|
|
25
|
+
var import_tools = require("@dexto/core/tools");
|
|
26
|
+
async function unavailableSkillResult(skills, error, hint) {
|
|
27
|
+
let availableSkills;
|
|
28
|
+
try {
|
|
29
|
+
availableSkills = (await skills.list()).map((skill) => skill.name);
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
error,
|
|
34
|
+
...availableSkills === void 0 ? {} : { availableSkills },
|
|
35
|
+
_hint: hint
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function createSkillLoadTool() {
|
|
39
|
+
return (0, import_tools.defineTool)({
|
|
40
|
+
id: "skill_load",
|
|
41
|
+
description: `Load one exact Skill by name.
|
|
42
|
+
|
|
43
|
+
Without a path, this returns the Skill instructions and the location of its supporting files. With
|
|
44
|
+
a path, it reads one supporting text file relative to that Skill. Use the exact name from the
|
|
45
|
+
available Skills list; names are not aliases.`,
|
|
46
|
+
inputSchema: import_core.SkillLoadInputSchema,
|
|
47
|
+
presentation: {
|
|
48
|
+
activity: import_tools.TOOL_ACTIVITY.useSkill,
|
|
49
|
+
describeHeader: (input) => (0, import_tools.createLocalToolCallHeader)({
|
|
50
|
+
title: "Load Skill",
|
|
51
|
+
argsText: input.path ? `${input.name}/${input.path}` : input.name
|
|
52
|
+
})
|
|
53
|
+
},
|
|
54
|
+
async execute(input, context) {
|
|
55
|
+
const skills = context.services?.skills;
|
|
56
|
+
if (!skills) {
|
|
57
|
+
throw import_tools.ToolError.configInvalid(
|
|
58
|
+
"skill_load requires ToolExecutionContext.services.skills"
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (input.path) {
|
|
62
|
+
try {
|
|
63
|
+
const content = await skills.readFile(input.name, input.path);
|
|
64
|
+
return {
|
|
65
|
+
name: input.name,
|
|
66
|
+
path: input.path,
|
|
67
|
+
content
|
|
68
|
+
};
|
|
69
|
+
} catch {
|
|
70
|
+
return unavailableSkillResult(
|
|
71
|
+
skills,
|
|
72
|
+
`Skill file unavailable: ${input.name}/${input.path}`,
|
|
73
|
+
"Use a valid relative file path from the selected Skill."
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const loaded = await skills.load(input.name);
|
|
79
|
+
if (loaded) {
|
|
80
|
+
return loaded;
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
return unavailableSkillResult(
|
|
84
|
+
skills,
|
|
85
|
+
`Skill unavailable: ${input.name}`,
|
|
86
|
+
"Use the exact name from the available Skills list."
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return unavailableSkillResult(
|
|
90
|
+
skills,
|
|
91
|
+
`Skill unavailable: ${input.name}`,
|
|
92
|
+
"Use the exact name from the available Skills list."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
98
|
+
0 && (module.exports = {
|
|
99
|
+
createSkillLoadTool
|
|
100
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-load-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/skill-load-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,mBAAmB,CAAC;AAsBpE,wBAAgB,mBAAmB,IAAI,IAAI,CAAC,OAAO,oBAAoB,CAAC,CA8DvE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { SkillLoadInputSchema } from "@dexto/core";
|
|
2
|
+
import { TOOL_ACTIVITY, ToolError, createLocalToolCallHeader, defineTool } from "@dexto/core/tools";
|
|
3
|
+
async function unavailableSkillResult(skills, error, hint) {
|
|
4
|
+
let availableSkills;
|
|
5
|
+
try {
|
|
6
|
+
availableSkills = (await skills.list()).map((skill) => skill.name);
|
|
7
|
+
} catch {
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
error,
|
|
11
|
+
...availableSkills === void 0 ? {} : { availableSkills },
|
|
12
|
+
_hint: hint
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function createSkillLoadTool() {
|
|
16
|
+
return defineTool({
|
|
17
|
+
id: "skill_load",
|
|
18
|
+
description: `Load one exact Skill by name.
|
|
19
|
+
|
|
20
|
+
Without a path, this returns the Skill instructions and the location of its supporting files. With
|
|
21
|
+
a path, it reads one supporting text file relative to that Skill. Use the exact name from the
|
|
22
|
+
available Skills list; names are not aliases.`,
|
|
23
|
+
inputSchema: SkillLoadInputSchema,
|
|
24
|
+
presentation: {
|
|
25
|
+
activity: TOOL_ACTIVITY.useSkill,
|
|
26
|
+
describeHeader: (input) => createLocalToolCallHeader({
|
|
27
|
+
title: "Load Skill",
|
|
28
|
+
argsText: input.path ? `${input.name}/${input.path}` : input.name
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
async execute(input, context) {
|
|
32
|
+
const skills = context.services?.skills;
|
|
33
|
+
if (!skills) {
|
|
34
|
+
throw ToolError.configInvalid(
|
|
35
|
+
"skill_load requires ToolExecutionContext.services.skills"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (input.path) {
|
|
39
|
+
try {
|
|
40
|
+
const content = await skills.readFile(input.name, input.path);
|
|
41
|
+
return {
|
|
42
|
+
name: input.name,
|
|
43
|
+
path: input.path,
|
|
44
|
+
content
|
|
45
|
+
};
|
|
46
|
+
} catch {
|
|
47
|
+
return unavailableSkillResult(
|
|
48
|
+
skills,
|
|
49
|
+
`Skill file unavailable: ${input.name}/${input.path}`,
|
|
50
|
+
"Use a valid relative file path from the selected Skill."
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const loaded = await skills.load(input.name);
|
|
56
|
+
if (loaded) {
|
|
57
|
+
return loaded;
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
return unavailableSkillResult(
|
|
61
|
+
skills,
|
|
62
|
+
`Skill unavailable: ${input.name}`,
|
|
63
|
+
"Use the exact name from the available Skills list."
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return unavailableSkillResult(
|
|
67
|
+
skills,
|
|
68
|
+
`Skill unavailable: ${input.name}`,
|
|
69
|
+
"Use the exact name from the available Skills list."
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
createSkillLoadTool
|
|
76
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_vitest = require("vitest");
|
|
3
|
+
var import_skill_load_tool = require("./skill-load-tool.js");
|
|
4
|
+
(0, import_vitest.describe)("skill_load tool", () => {
|
|
5
|
+
(0, import_vitest.it)("loads one exact skill without listing the skill catalog", async () => {
|
|
6
|
+
const skills = {
|
|
7
|
+
list: import_vitest.vi.fn(),
|
|
8
|
+
load: import_vitest.vi.fn().mockResolvedValue({
|
|
9
|
+
name: "alpha",
|
|
10
|
+
instructions: "Use alpha instructions.",
|
|
11
|
+
supportingFiles: [],
|
|
12
|
+
filesLocation: "hosted",
|
|
13
|
+
baseDirectory: null
|
|
14
|
+
}),
|
|
15
|
+
readFile: import_vitest.vi.fn()
|
|
16
|
+
};
|
|
17
|
+
const tool = (0, import_skill_load_tool.createSkillLoadTool)();
|
|
18
|
+
const result = await tool.execute({ name: "alpha" }, {
|
|
19
|
+
services: { skills }
|
|
20
|
+
});
|
|
21
|
+
(0, import_vitest.expect)(skills.load).toHaveBeenCalledWith("alpha");
|
|
22
|
+
(0, import_vitest.expect)(skills.list).not.toHaveBeenCalled();
|
|
23
|
+
(0, import_vitest.expect)(result).toEqual({
|
|
24
|
+
name: "alpha",
|
|
25
|
+
instructions: "Use alpha instructions.",
|
|
26
|
+
supportingFiles: [],
|
|
27
|
+
filesLocation: "hosted",
|
|
28
|
+
baseDirectory: null
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
(0, import_vitest.it)("returns a structured unavailable result when loading fails", async () => {
|
|
32
|
+
const skills = {
|
|
33
|
+
list: import_vitest.vi.fn().mockResolvedValue([
|
|
34
|
+
{ name: "alpha", description: "Alpha instructions" },
|
|
35
|
+
{ name: "beta", description: "Beta instructions" }
|
|
36
|
+
]),
|
|
37
|
+
load: import_vitest.vi.fn().mockRejectedValue(new Error("release unavailable")),
|
|
38
|
+
readFile: import_vitest.vi.fn()
|
|
39
|
+
};
|
|
40
|
+
const result = await (0, import_skill_load_tool.createSkillLoadTool)().execute({ name: "missing" }, {
|
|
41
|
+
services: { skills }
|
|
42
|
+
});
|
|
43
|
+
(0, import_vitest.expect)(result).toEqual({
|
|
44
|
+
error: "Skill unavailable: missing",
|
|
45
|
+
availableSkills: ["alpha", "beta"],
|
|
46
|
+
_hint: "Use the exact name from the available Skills list."
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
(0, import_vitest.it)("reads a supporting file and isolates file failures", async () => {
|
|
50
|
+
const skills = {
|
|
51
|
+
list: import_vitest.vi.fn().mockResolvedValue([{ name: "alpha", description: "Alpha instructions" }]),
|
|
52
|
+
load: import_vitest.vi.fn(),
|
|
53
|
+
readFile: import_vitest.vi.fn().mockResolvedValueOnce("Checklist").mockRejectedValueOnce(new Error("artifact unavailable"))
|
|
54
|
+
};
|
|
55
|
+
const tool = (0, import_skill_load_tool.createSkillLoadTool)();
|
|
56
|
+
const context = { services: { skills } };
|
|
57
|
+
await (0, import_vitest.expect)(
|
|
58
|
+
tool.execute({ name: "alpha", path: "references/checklist.md" }, context)
|
|
59
|
+
).resolves.toEqual({
|
|
60
|
+
name: "alpha",
|
|
61
|
+
path: "references/checklist.md",
|
|
62
|
+
content: "Checklist"
|
|
63
|
+
});
|
|
64
|
+
await (0, import_vitest.expect)(
|
|
65
|
+
tool.execute({ name: "alpha", path: "references/missing.md" }, context)
|
|
66
|
+
).resolves.toEqual({
|
|
67
|
+
error: "Skill file unavailable: alpha/references/missing.md",
|
|
68
|
+
availableSkills: ["alpha"],
|
|
69
|
+
_hint: "Use a valid relative file path from the selected Skill."
|
|
70
|
+
});
|
|
71
|
+
(0, import_vitest.expect)(skills.load).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-load-tool.test.d.ts","sourceRoot":"","sources":["../../src/implementations/skill-load-tool.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createSkillLoadTool } from "./skill-load-tool.js";
|
|
3
|
+
describe("skill_load tool", () => {
|
|
4
|
+
it("loads one exact skill without listing the skill catalog", async () => {
|
|
5
|
+
const skills = {
|
|
6
|
+
list: vi.fn(),
|
|
7
|
+
load: vi.fn().mockResolvedValue({
|
|
8
|
+
name: "alpha",
|
|
9
|
+
instructions: "Use alpha instructions.",
|
|
10
|
+
supportingFiles: [],
|
|
11
|
+
filesLocation: "hosted",
|
|
12
|
+
baseDirectory: null
|
|
13
|
+
}),
|
|
14
|
+
readFile: vi.fn()
|
|
15
|
+
};
|
|
16
|
+
const tool = createSkillLoadTool();
|
|
17
|
+
const result = await tool.execute({ name: "alpha" }, {
|
|
18
|
+
services: { skills }
|
|
19
|
+
});
|
|
20
|
+
expect(skills.load).toHaveBeenCalledWith("alpha");
|
|
21
|
+
expect(skills.list).not.toHaveBeenCalled();
|
|
22
|
+
expect(result).toEqual({
|
|
23
|
+
name: "alpha",
|
|
24
|
+
instructions: "Use alpha instructions.",
|
|
25
|
+
supportingFiles: [],
|
|
26
|
+
filesLocation: "hosted",
|
|
27
|
+
baseDirectory: null
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
it("returns a structured unavailable result when loading fails", async () => {
|
|
31
|
+
const skills = {
|
|
32
|
+
list: vi.fn().mockResolvedValue([
|
|
33
|
+
{ name: "alpha", description: "Alpha instructions" },
|
|
34
|
+
{ name: "beta", description: "Beta instructions" }
|
|
35
|
+
]),
|
|
36
|
+
load: vi.fn().mockRejectedValue(new Error("release unavailable")),
|
|
37
|
+
readFile: vi.fn()
|
|
38
|
+
};
|
|
39
|
+
const result = await createSkillLoadTool().execute({ name: "missing" }, {
|
|
40
|
+
services: { skills }
|
|
41
|
+
});
|
|
42
|
+
expect(result).toEqual({
|
|
43
|
+
error: "Skill unavailable: missing",
|
|
44
|
+
availableSkills: ["alpha", "beta"],
|
|
45
|
+
_hint: "Use the exact name from the available Skills list."
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
it("reads a supporting file and isolates file failures", async () => {
|
|
49
|
+
const skills = {
|
|
50
|
+
list: vi.fn().mockResolvedValue([{ name: "alpha", description: "Alpha instructions" }]),
|
|
51
|
+
load: vi.fn(),
|
|
52
|
+
readFile: vi.fn().mockResolvedValueOnce("Checklist").mockRejectedValueOnce(new Error("artifact unavailable"))
|
|
53
|
+
};
|
|
54
|
+
const tool = createSkillLoadTool();
|
|
55
|
+
const context = { services: { skills } };
|
|
56
|
+
await expect(
|
|
57
|
+
tool.execute({ name: "alpha", path: "references/checklist.md" }, context)
|
|
58
|
+
).resolves.toEqual({
|
|
59
|
+
name: "alpha",
|
|
60
|
+
path: "references/checklist.md",
|
|
61
|
+
content: "Checklist"
|
|
62
|
+
});
|
|
63
|
+
await expect(
|
|
64
|
+
tool.execute({ name: "alpha", path: "references/missing.md" }, context)
|
|
65
|
+
).resolves.toEqual({
|
|
66
|
+
error: "Skill file unavailable: alpha/references/missing.md",
|
|
67
|
+
availableSkills: ["alpha"],
|
|
68
|
+
_hint: "Use a valid relative file path from the selected Skill."
|
|
69
|
+
});
|
|
70
|
+
expect(skills.load).not.toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ToolFactory } from '@dexto/agent-config';
|
|
3
3
|
|
|
4
|
-
declare const BUILTIN_TOOL_NAMES: readonly ["ask_user", "delegate_to_url", "list_resources", "get_resource", "
|
|
4
|
+
declare const BUILTIN_TOOL_NAMES: readonly ["ask_user", "delegate_to_url", "list_resources", "get_resource", "skill_load", "http_request", "sleep", "web_search", "code_search"];
|
|
5
5
|
type BuiltinToolName = (typeof BUILTIN_TOOL_NAMES)[number];
|
|
6
6
|
declare const BuiltinToolsConfigSchema: z.ZodObject<{
|
|
7
7
|
type: z.ZodLiteral<"builtin-tools">;
|
|
@@ -9,8 +9,7 @@ declare const BuiltinToolsConfigSchema: z.ZodObject<{
|
|
|
9
9
|
ask_user: "ask_user";
|
|
10
10
|
delegate_to_url: "delegate_to_url";
|
|
11
11
|
get_resource: "get_resource";
|
|
12
|
-
|
|
13
|
-
read_skill: "read_skill";
|
|
12
|
+
skill_load: "skill_load";
|
|
14
13
|
list_resources: "list_resources";
|
|
15
14
|
http_request: "http_request";
|
|
16
15
|
sleep: "sleep";
|
package/dist/index.d.ts
CHANGED
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
* - delegate_to_url
|
|
10
10
|
* - list_resources
|
|
11
11
|
* - get_resource
|
|
12
|
-
* -
|
|
13
|
-
* - read_skill
|
|
12
|
+
* - skill_load
|
|
14
13
|
*/
|
|
15
14
|
export { builtinToolsFactory, BuiltinToolsConfigSchema } from './builtin-tools-factory.js';
|
|
16
15
|
export { BUILTIN_TOOL_NAMES } from './builtin-tools-factory.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dexto/tools-builtins",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Built-in tools factory for Dexto agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"undici": "^7.24.6",
|
|
21
21
|
"zod": "^4.3.6",
|
|
22
|
-
"@dexto/agent-config": "1.
|
|
23
|
-
"@dexto/core": "1.
|
|
22
|
+
"@dexto/agent-config": "1.11.0",
|
|
23
|
+
"@dexto/core": "1.11.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"tsup": "^8.0.0",
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var invoke_skill_tool_exports = {};
|
|
20
|
-
__export(invoke_skill_tool_exports, {
|
|
21
|
-
createInvokeSkillTool: () => createInvokeSkillTool
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(invoke_skill_tool_exports);
|
|
24
|
-
var import_zod = require("zod");
|
|
25
|
-
var import_tools = require("@dexto/core/tools");
|
|
26
|
-
const InvokeSkillInputSchema = import_zod.z.object({
|
|
27
|
-
skill: import_zod.z.string().min(1, "Skill name is required").describe(
|
|
28
|
-
'The name of the skill to invoke (e.g., "plugin-name:skill-name" or "skill-name")'
|
|
29
|
-
),
|
|
30
|
-
args: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional().describe("Optional arguments to pass to the skill"),
|
|
31
|
-
taskContext: import_zod.z.string().optional().describe("Context about what task this skill should accomplish")
|
|
32
|
-
}).strict();
|
|
33
|
-
function createInvokeSkillTool() {
|
|
34
|
-
return (0, import_tools.defineTool)({
|
|
35
|
-
id: "invoke_skill",
|
|
36
|
-
description: buildToolDescription(),
|
|
37
|
-
inputSchema: InvokeSkillInputSchema,
|
|
38
|
-
presentation: {
|
|
39
|
-
activity: import_tools.TOOL_ACTIVITY.useSkill,
|
|
40
|
-
describeHeader: (input) => {
|
|
41
|
-
const colonIndex = input.skill.indexOf(":");
|
|
42
|
-
const displaySkillName = colonIndex >= 0 ? input.skill.slice(colonIndex + 1) : input.skill;
|
|
43
|
-
return (0, import_tools.createLocalToolCallHeader)({
|
|
44
|
-
title: "Skill",
|
|
45
|
-
argsText: `/${displaySkillName}`
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
async execute(input, context) {
|
|
50
|
-
const skillManager = context.services?.skills;
|
|
51
|
-
if (!skillManager) {
|
|
52
|
-
throw import_tools.ToolError.configInvalid(
|
|
53
|
-
"invoke_skill requires ToolExecutionContext.services.skills"
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
const invoked = await skillManager.invoke(input.skill, input.args);
|
|
57
|
-
if (!invoked) {
|
|
58
|
-
const availableSkills = (await skillManager.list()).map(
|
|
59
|
-
(availableSkill) => availableSkill.displayName
|
|
60
|
-
);
|
|
61
|
-
return {
|
|
62
|
-
error: `Skill '${input.skill}' not found or not available for model invocation. Use a skill from the available list.`,
|
|
63
|
-
availableSkills
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
const content = input.taskContext ? `## Task Context
|
|
67
|
-
${input.taskContext}
|
|
68
|
-
|
|
69
|
-
## Skill Instructions
|
|
70
|
-
${invoked.instructions}` : invoked.instructions;
|
|
71
|
-
return {
|
|
72
|
-
skill: invoked.id,
|
|
73
|
-
content,
|
|
74
|
-
instructions: "Follow the instructions in the skill content above to complete the task."
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
function buildToolDescription() {
|
|
80
|
-
return `Invoke a skill to load specialized instructions for a task.
|
|
81
|
-
|
|
82
|
-
When to use:
|
|
83
|
-
- When you recognize a task that matches an available skill
|
|
84
|
-
- When you need specialized guidance for a complex operation
|
|
85
|
-
- When the user references a skill by name
|
|
86
|
-
|
|
87
|
-
Available skills are listed in your system prompt. Use the skill name exactly as shown.`;
|
|
88
|
-
}
|
|
89
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
90
|
-
0 && (module.exports = {
|
|
91
|
-
createInvokeSkillTool
|
|
92
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { Tool } from '@dexto/core/tools';
|
|
3
|
-
declare const InvokeSkillInputSchema: z.ZodObject<{
|
|
4
|
-
skill: z.ZodString;
|
|
5
|
-
args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
6
|
-
taskContext: z.ZodOptional<z.ZodString>;
|
|
7
|
-
}, z.core.$strict>;
|
|
8
|
-
export declare function createInvokeSkillTool(): Tool<typeof InvokeSkillInputSchema>;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=invoke-skill-tool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invoke-skill-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/invoke-skill-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,mBAAmB,CAAC;AAapE,QAAA,MAAM,sBAAsB;;;;kBAiBf,CAAC;AAEd,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,OAAO,sBAAsB,CAAC,CAiD3E"}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { TOOL_ACTIVITY, ToolError, createLocalToolCallHeader, defineTool } from "@dexto/core/tools";
|
|
3
|
-
const InvokeSkillInputSchema = z.object({
|
|
4
|
-
skill: z.string().min(1, "Skill name is required").describe(
|
|
5
|
-
'The name of the skill to invoke (e.g., "plugin-name:skill-name" or "skill-name")'
|
|
6
|
-
),
|
|
7
|
-
args: z.record(z.string(), z.string()).optional().describe("Optional arguments to pass to the skill"),
|
|
8
|
-
taskContext: z.string().optional().describe("Context about what task this skill should accomplish")
|
|
9
|
-
}).strict();
|
|
10
|
-
function createInvokeSkillTool() {
|
|
11
|
-
return defineTool({
|
|
12
|
-
id: "invoke_skill",
|
|
13
|
-
description: buildToolDescription(),
|
|
14
|
-
inputSchema: InvokeSkillInputSchema,
|
|
15
|
-
presentation: {
|
|
16
|
-
activity: TOOL_ACTIVITY.useSkill,
|
|
17
|
-
describeHeader: (input) => {
|
|
18
|
-
const colonIndex = input.skill.indexOf(":");
|
|
19
|
-
const displaySkillName = colonIndex >= 0 ? input.skill.slice(colonIndex + 1) : input.skill;
|
|
20
|
-
return createLocalToolCallHeader({
|
|
21
|
-
title: "Skill",
|
|
22
|
-
argsText: `/${displaySkillName}`
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
async execute(input, context) {
|
|
27
|
-
const skillManager = context.services?.skills;
|
|
28
|
-
if (!skillManager) {
|
|
29
|
-
throw ToolError.configInvalid(
|
|
30
|
-
"invoke_skill requires ToolExecutionContext.services.skills"
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
const invoked = await skillManager.invoke(input.skill, input.args);
|
|
34
|
-
if (!invoked) {
|
|
35
|
-
const availableSkills = (await skillManager.list()).map(
|
|
36
|
-
(availableSkill) => availableSkill.displayName
|
|
37
|
-
);
|
|
38
|
-
return {
|
|
39
|
-
error: `Skill '${input.skill}' not found or not available for model invocation. Use a skill from the available list.`,
|
|
40
|
-
availableSkills
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
const content = input.taskContext ? `## Task Context
|
|
44
|
-
${input.taskContext}
|
|
45
|
-
|
|
46
|
-
## Skill Instructions
|
|
47
|
-
${invoked.instructions}` : invoked.instructions;
|
|
48
|
-
return {
|
|
49
|
-
skill: invoked.id,
|
|
50
|
-
content,
|
|
51
|
-
instructions: "Follow the instructions in the skill content above to complete the task."
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
function buildToolDescription() {
|
|
57
|
-
return `Invoke a skill to load specialized instructions for a task.
|
|
58
|
-
|
|
59
|
-
When to use:
|
|
60
|
-
- When you recognize a task that matches an available skill
|
|
61
|
-
- When you need specialized guidance for a complex operation
|
|
62
|
-
- When the user references a skill by name
|
|
63
|
-
|
|
64
|
-
Available skills are listed in your system prompt. Use the skill name exactly as shown.`;
|
|
65
|
-
}
|
|
66
|
-
export {
|
|
67
|
-
createInvokeSkillTool
|
|
68
|
-
};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var import_vitest = require("vitest");
|
|
3
|
-
var import_invoke_skill_tool = require("./invoke-skill-tool.js");
|
|
4
|
-
(0, import_vitest.describe)("invoke_skill tool", () => {
|
|
5
|
-
(0, import_vitest.it)("invokes skills through SkillManager", async () => {
|
|
6
|
-
const skillManager = {
|
|
7
|
-
list: import_vitest.vi.fn().mockResolvedValue([
|
|
8
|
-
{ id: "alpha", displayName: "Alpha", description: "Use alpha" }
|
|
9
|
-
]),
|
|
10
|
-
invoke: import_vitest.vi.fn().mockResolvedValue({
|
|
11
|
-
id: "alpha",
|
|
12
|
-
displayName: "Alpha",
|
|
13
|
-
instructions: "Use alpha instructions."
|
|
14
|
-
})
|
|
15
|
-
};
|
|
16
|
-
const tool = (0, import_invoke_skill_tool.createInvokeSkillTool)();
|
|
17
|
-
const result = await tool.execute(
|
|
18
|
-
{
|
|
19
|
-
skill: "Alpha",
|
|
20
|
-
args: { mode: "fast" }
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
logger: {
|
|
24
|
-
warn: import_vitest.vi.fn()
|
|
25
|
-
},
|
|
26
|
-
services: {
|
|
27
|
-
skills: skillManager
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
(0, import_vitest.expect)(skillManager.invoke).toHaveBeenCalledWith("Alpha", { mode: "fast" });
|
|
32
|
-
(0, import_vitest.expect)(result).toEqual({
|
|
33
|
-
skill: "alpha",
|
|
34
|
-
content: "Use alpha instructions.",
|
|
35
|
-
instructions: "Follow the instructions in the skill content above to complete the task."
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
(0, import_vitest.it)("adds task context to returned skill instructions", async () => {
|
|
39
|
-
const skillManager = {
|
|
40
|
-
list: import_vitest.vi.fn(),
|
|
41
|
-
invoke: import_vitest.vi.fn().mockResolvedValue({
|
|
42
|
-
id: "alpha",
|
|
43
|
-
displayName: "Alpha",
|
|
44
|
-
instructions: "Use alpha instructions."
|
|
45
|
-
})
|
|
46
|
-
};
|
|
47
|
-
const tool = (0, import_invoke_skill_tool.createInvokeSkillTool)();
|
|
48
|
-
const result = await tool.execute(
|
|
49
|
-
{
|
|
50
|
-
skill: "Alpha",
|
|
51
|
-
taskContext: "Refactor the storage layer."
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
logger: {
|
|
55
|
-
warn: import_vitest.vi.fn()
|
|
56
|
-
},
|
|
57
|
-
services: {
|
|
58
|
-
skills: skillManager
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
(0, import_vitest.expect)(result).toMatchObject({
|
|
63
|
-
content: "## Task Context\nRefactor the storage layer.\n\n## Skill Instructions\nUse alpha instructions."
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
(0, import_vitest.it)("returns available skills when the requested skill is missing", async () => {
|
|
67
|
-
const skillManager = {
|
|
68
|
-
list: import_vitest.vi.fn().mockResolvedValue([
|
|
69
|
-
{ id: "alpha", displayName: "Alpha" },
|
|
70
|
-
{ id: "beta", displayName: "Beta" }
|
|
71
|
-
]),
|
|
72
|
-
invoke: import_vitest.vi.fn().mockResolvedValue(null)
|
|
73
|
-
};
|
|
74
|
-
const tool = (0, import_invoke_skill_tool.createInvokeSkillTool)();
|
|
75
|
-
const result = await tool.execute({ skill: "missing" }, {
|
|
76
|
-
logger: {
|
|
77
|
-
warn: import_vitest.vi.fn()
|
|
78
|
-
},
|
|
79
|
-
services: {
|
|
80
|
-
skills: skillManager
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
(0, import_vitest.expect)(result).toEqual({
|
|
84
|
-
error: "Skill 'missing' not found or not available for model invocation. Use a skill from the available list.",
|
|
85
|
-
availableSkills: ["Alpha", "Beta"]
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
(0, import_vitest.it)("requires ToolExecutionContext.services.skills", async () => {
|
|
89
|
-
const tool = (0, import_invoke_skill_tool.createInvokeSkillTool)();
|
|
90
|
-
await (0, import_vitest.expect)(
|
|
91
|
-
tool.execute({ skill: "alpha" }, {
|
|
92
|
-
logger: {
|
|
93
|
-
warn: import_vitest.vi.fn()
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
).rejects.toThrow("invoke_skill requires ToolExecutionContext.services.skills");
|
|
97
|
-
});
|
|
98
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invoke-skill-tool.test.d.ts","sourceRoot":"","sources":["../../src/implementations/invoke-skill-tool.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { createInvokeSkillTool } from "./invoke-skill-tool.js";
|
|
3
|
-
describe("invoke_skill tool", () => {
|
|
4
|
-
it("invokes skills through SkillManager", async () => {
|
|
5
|
-
const skillManager = {
|
|
6
|
-
list: vi.fn().mockResolvedValue([
|
|
7
|
-
{ id: "alpha", displayName: "Alpha", description: "Use alpha" }
|
|
8
|
-
]),
|
|
9
|
-
invoke: vi.fn().mockResolvedValue({
|
|
10
|
-
id: "alpha",
|
|
11
|
-
displayName: "Alpha",
|
|
12
|
-
instructions: "Use alpha instructions."
|
|
13
|
-
})
|
|
14
|
-
};
|
|
15
|
-
const tool = createInvokeSkillTool();
|
|
16
|
-
const result = await tool.execute(
|
|
17
|
-
{
|
|
18
|
-
skill: "Alpha",
|
|
19
|
-
args: { mode: "fast" }
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
logger: {
|
|
23
|
-
warn: vi.fn()
|
|
24
|
-
},
|
|
25
|
-
services: {
|
|
26
|
-
skills: skillManager
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
);
|
|
30
|
-
expect(skillManager.invoke).toHaveBeenCalledWith("Alpha", { mode: "fast" });
|
|
31
|
-
expect(result).toEqual({
|
|
32
|
-
skill: "alpha",
|
|
33
|
-
content: "Use alpha instructions.",
|
|
34
|
-
instructions: "Follow the instructions in the skill content above to complete the task."
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
it("adds task context to returned skill instructions", async () => {
|
|
38
|
-
const skillManager = {
|
|
39
|
-
list: vi.fn(),
|
|
40
|
-
invoke: vi.fn().mockResolvedValue({
|
|
41
|
-
id: "alpha",
|
|
42
|
-
displayName: "Alpha",
|
|
43
|
-
instructions: "Use alpha instructions."
|
|
44
|
-
})
|
|
45
|
-
};
|
|
46
|
-
const tool = createInvokeSkillTool();
|
|
47
|
-
const result = await tool.execute(
|
|
48
|
-
{
|
|
49
|
-
skill: "Alpha",
|
|
50
|
-
taskContext: "Refactor the storage layer."
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
logger: {
|
|
54
|
-
warn: vi.fn()
|
|
55
|
-
},
|
|
56
|
-
services: {
|
|
57
|
-
skills: skillManager
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
);
|
|
61
|
-
expect(result).toMatchObject({
|
|
62
|
-
content: "## Task Context\nRefactor the storage layer.\n\n## Skill Instructions\nUse alpha instructions."
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
it("returns available skills when the requested skill is missing", async () => {
|
|
66
|
-
const skillManager = {
|
|
67
|
-
list: vi.fn().mockResolvedValue([
|
|
68
|
-
{ id: "alpha", displayName: "Alpha" },
|
|
69
|
-
{ id: "beta", displayName: "Beta" }
|
|
70
|
-
]),
|
|
71
|
-
invoke: vi.fn().mockResolvedValue(null)
|
|
72
|
-
};
|
|
73
|
-
const tool = createInvokeSkillTool();
|
|
74
|
-
const result = await tool.execute({ skill: "missing" }, {
|
|
75
|
-
logger: {
|
|
76
|
-
warn: vi.fn()
|
|
77
|
-
},
|
|
78
|
-
services: {
|
|
79
|
-
skills: skillManager
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
expect(result).toEqual({
|
|
83
|
-
error: "Skill 'missing' not found or not available for model invocation. Use a skill from the available list.",
|
|
84
|
-
availableSkills: ["Alpha", "Beta"]
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
it("requires ToolExecutionContext.services.skills", async () => {
|
|
88
|
-
const tool = createInvokeSkillTool();
|
|
89
|
-
await expect(
|
|
90
|
-
tool.execute({ skill: "alpha" }, {
|
|
91
|
-
logger: {
|
|
92
|
-
warn: vi.fn()
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
).rejects.toThrow("invoke_skill requires ToolExecutionContext.services.skills");
|
|
96
|
-
});
|
|
97
|
-
});
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var read_skill_tool_exports = {};
|
|
20
|
-
__export(read_skill_tool_exports, {
|
|
21
|
-
createReadSkillTool: () => createReadSkillTool
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(read_skill_tool_exports);
|
|
24
|
-
var import_zod = require("zod");
|
|
25
|
-
var import_tools = require("@dexto/core/tools");
|
|
26
|
-
const ReadSkillInputSchema = import_zod.z.object({
|
|
27
|
-
skill: import_zod.z.string().min(1, "Skill name is required"),
|
|
28
|
-
path: import_zod.z.string().min(1).optional()
|
|
29
|
-
}).strict();
|
|
30
|
-
function createReadSkillTool() {
|
|
31
|
-
return (0, import_tools.defineTool)({
|
|
32
|
-
id: "read_skill",
|
|
33
|
-
description: "Read skill instructions or a file from a skill bundle. This is read-only and does not invoke the skill.",
|
|
34
|
-
inputSchema: ReadSkillInputSchema,
|
|
35
|
-
presentation: {
|
|
36
|
-
activity: import_tools.TOOL_ACTIVITY.readSkill,
|
|
37
|
-
describeHeader: (input) => (0, import_tools.createLocalToolCallHeader)({
|
|
38
|
-
title: "Read Skill",
|
|
39
|
-
argsText: input.path ? `${input.skill}/${input.path}` : input.skill
|
|
40
|
-
})
|
|
41
|
-
},
|
|
42
|
-
async execute(input, context) {
|
|
43
|
-
const skillManager = getSkillManager(context);
|
|
44
|
-
if (!skillManager) {
|
|
45
|
-
throw import_tools.ToolError.configInvalid(
|
|
46
|
-
"read_skill requires ToolExecutionContext.services.skills"
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
if (input.path) {
|
|
50
|
-
try {
|
|
51
|
-
const content = await skillManager.readFile(input.skill, input.path);
|
|
52
|
-
return {
|
|
53
|
-
success: true,
|
|
54
|
-
skill: input.skill,
|
|
55
|
-
path: input.path,
|
|
56
|
-
content
|
|
57
|
-
};
|
|
58
|
-
} catch {
|
|
59
|
-
return {
|
|
60
|
-
success: false,
|
|
61
|
-
error: `Skill file not found: ${input.skill}/${input.path}`,
|
|
62
|
-
_hint: "Use a valid file path from the skill bundle."
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const skill = await skillManager.get(input.skill);
|
|
67
|
-
if (!skill) {
|
|
68
|
-
return {
|
|
69
|
-
success: false,
|
|
70
|
-
error: `Skill not found: ${input.skill}`,
|
|
71
|
-
_hint: "Use a skill from the available skills list."
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return {
|
|
75
|
-
success: true,
|
|
76
|
-
skill: skill.id,
|
|
77
|
-
displayName: skill.displayName,
|
|
78
|
-
content: skill.instructions
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
function getSkillManager(context) {
|
|
84
|
-
const services = context.services;
|
|
85
|
-
return services?.skills;
|
|
86
|
-
}
|
|
87
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
88
|
-
0 && (module.exports = {
|
|
89
|
-
createReadSkillTool
|
|
90
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { Tool } from '@dexto/core/tools';
|
|
3
|
-
declare const ReadSkillInputSchema: z.ZodObject<{
|
|
4
|
-
skill: z.ZodString;
|
|
5
|
-
path: z.ZodOptional<z.ZodString>;
|
|
6
|
-
}, z.core.$strict>;
|
|
7
|
-
export declare function createReadSkillTool(): Tool<typeof ReadSkillInputSchema>;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=read-skill-tool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-skill-tool.d.ts","sourceRoot":"","sources":["../../src/implementations/read-skill-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,mBAAmB,CAAC;AAapE,QAAA,MAAM,oBAAoB;;;kBAKb,CAAC;AAEd,wBAAgB,mBAAmB,IAAI,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAyDvE"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { TOOL_ACTIVITY, ToolError, createLocalToolCallHeader, defineTool } from "@dexto/core/tools";
|
|
3
|
-
const ReadSkillInputSchema = z.object({
|
|
4
|
-
skill: z.string().min(1, "Skill name is required"),
|
|
5
|
-
path: z.string().min(1).optional()
|
|
6
|
-
}).strict();
|
|
7
|
-
function createReadSkillTool() {
|
|
8
|
-
return defineTool({
|
|
9
|
-
id: "read_skill",
|
|
10
|
-
description: "Read skill instructions or a file from a skill bundle. This is read-only and does not invoke the skill.",
|
|
11
|
-
inputSchema: ReadSkillInputSchema,
|
|
12
|
-
presentation: {
|
|
13
|
-
activity: TOOL_ACTIVITY.readSkill,
|
|
14
|
-
describeHeader: (input) => createLocalToolCallHeader({
|
|
15
|
-
title: "Read Skill",
|
|
16
|
-
argsText: input.path ? `${input.skill}/${input.path}` : input.skill
|
|
17
|
-
})
|
|
18
|
-
},
|
|
19
|
-
async execute(input, context) {
|
|
20
|
-
const skillManager = getSkillManager(context);
|
|
21
|
-
if (!skillManager) {
|
|
22
|
-
throw ToolError.configInvalid(
|
|
23
|
-
"read_skill requires ToolExecutionContext.services.skills"
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
if (input.path) {
|
|
27
|
-
try {
|
|
28
|
-
const content = await skillManager.readFile(input.skill, input.path);
|
|
29
|
-
return {
|
|
30
|
-
success: true,
|
|
31
|
-
skill: input.skill,
|
|
32
|
-
path: input.path,
|
|
33
|
-
content
|
|
34
|
-
};
|
|
35
|
-
} catch {
|
|
36
|
-
return {
|
|
37
|
-
success: false,
|
|
38
|
-
error: `Skill file not found: ${input.skill}/${input.path}`,
|
|
39
|
-
_hint: "Use a valid file path from the skill bundle."
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const skill = await skillManager.get(input.skill);
|
|
44
|
-
if (!skill) {
|
|
45
|
-
return {
|
|
46
|
-
success: false,
|
|
47
|
-
error: `Skill not found: ${input.skill}`,
|
|
48
|
-
_hint: "Use a skill from the available skills list."
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
success: true,
|
|
53
|
-
skill: skill.id,
|
|
54
|
-
displayName: skill.displayName,
|
|
55
|
-
content: skill.instructions
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
function getSkillManager(context) {
|
|
61
|
-
const services = context.services;
|
|
62
|
-
return services?.skills;
|
|
63
|
-
}
|
|
64
|
-
export {
|
|
65
|
-
createReadSkillTool
|
|
66
|
-
};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var import_tools = require("@dexto/core/tools");
|
|
3
|
-
var import_vitest = require("vitest");
|
|
4
|
-
var import_read_skill_tool = require("./read-skill-tool.js");
|
|
5
|
-
(0, import_vitest.describe)("read_skill tool", () => {
|
|
6
|
-
(0, import_vitest.it)("returns primary skill instructions when no path is provided", async () => {
|
|
7
|
-
const skills = {
|
|
8
|
-
get: import_vitest.vi.fn().mockResolvedValue({
|
|
9
|
-
id: "alpha",
|
|
10
|
-
displayName: "Alpha",
|
|
11
|
-
instructions: "Use alpha instructions."
|
|
12
|
-
})
|
|
13
|
-
};
|
|
14
|
-
const tool = (0, import_read_skill_tool.createReadSkillTool)();
|
|
15
|
-
const result = await tool.execute({ skill: "Alpha" }, {
|
|
16
|
-
services: { skills }
|
|
17
|
-
});
|
|
18
|
-
(0, import_vitest.expect)(skills.get).toHaveBeenCalledWith("Alpha");
|
|
19
|
-
(0, import_vitest.expect)(result).toEqual({
|
|
20
|
-
success: true,
|
|
21
|
-
skill: "alpha",
|
|
22
|
-
displayName: "Alpha",
|
|
23
|
-
content: "Use alpha instructions."
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
(0, import_vitest.it)("delegates file reads to SkillManager when path is provided", async () => {
|
|
27
|
-
const skills = {
|
|
28
|
-
get: import_vitest.vi.fn(),
|
|
29
|
-
readFile: import_vitest.vi.fn().mockResolvedValue("# Details\nUse more context.")
|
|
30
|
-
};
|
|
31
|
-
const tool = (0, import_read_skill_tool.createReadSkillTool)();
|
|
32
|
-
const result = await tool.execute({ skill: "Alpha", path: "docs/details.md" }, {
|
|
33
|
-
services: { skills }
|
|
34
|
-
});
|
|
35
|
-
(0, import_vitest.expect)(skills.get).not.toHaveBeenCalled();
|
|
36
|
-
(0, import_vitest.expect)(skills.readFile).toHaveBeenCalledWith("Alpha", "docs/details.md");
|
|
37
|
-
(0, import_vitest.expect)(result).toEqual({
|
|
38
|
-
success: true,
|
|
39
|
-
skill: "Alpha",
|
|
40
|
-
path: "docs/details.md",
|
|
41
|
-
content: "# Details\nUse more context."
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
(0, import_vitest.it)("returns a structured error when the skill is missing", async () => {
|
|
45
|
-
const skills = {
|
|
46
|
-
get: import_vitest.vi.fn().mockResolvedValue(null)
|
|
47
|
-
};
|
|
48
|
-
const tool = (0, import_read_skill_tool.createReadSkillTool)();
|
|
49
|
-
const result = await tool.execute({ skill: "Missing" }, {
|
|
50
|
-
services: { skills }
|
|
51
|
-
});
|
|
52
|
-
(0, import_vitest.expect)(result).toEqual({
|
|
53
|
-
success: false,
|
|
54
|
-
error: "Skill not found: Missing",
|
|
55
|
-
_hint: "Use a skill from the available skills list."
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
(0, import_vitest.it)("returns a structured error when a skill file is missing", async () => {
|
|
59
|
-
const skills = {
|
|
60
|
-
readFile: import_vitest.vi.fn().mockRejectedValue(new Error("Skill file not found"))
|
|
61
|
-
};
|
|
62
|
-
const tool = (0, import_read_skill_tool.createReadSkillTool)();
|
|
63
|
-
const result = await tool.execute({ skill: "Alpha", path: "missing.md" }, {
|
|
64
|
-
services: { skills }
|
|
65
|
-
});
|
|
66
|
-
(0, import_vitest.expect)(result).toEqual({
|
|
67
|
-
success: false,
|
|
68
|
-
error: "Skill file not found: Alpha/missing.md",
|
|
69
|
-
_hint: "Use a valid file path from the skill bundle."
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
(0, import_vitest.it)("requires ToolExecutionContext.services.skills", async () => {
|
|
73
|
-
const tool = (0, import_read_skill_tool.createReadSkillTool)();
|
|
74
|
-
await (0, import_vitest.expect)(
|
|
75
|
-
tool.execute({ skill: "Alpha" }, {})
|
|
76
|
-
).rejects.toMatchObject({
|
|
77
|
-
code: import_tools.ToolError.configInvalid(
|
|
78
|
-
"read_skill requires ToolExecutionContext.services.skills"
|
|
79
|
-
).code
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-skill-tool.test.d.ts","sourceRoot":"","sources":["../../src/implementations/read-skill-tool.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { ToolError } from "@dexto/core/tools";
|
|
2
|
-
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { createReadSkillTool } from "./read-skill-tool.js";
|
|
4
|
-
describe("read_skill tool", () => {
|
|
5
|
-
it("returns primary skill instructions when no path is provided", async () => {
|
|
6
|
-
const skills = {
|
|
7
|
-
get: vi.fn().mockResolvedValue({
|
|
8
|
-
id: "alpha",
|
|
9
|
-
displayName: "Alpha",
|
|
10
|
-
instructions: "Use alpha instructions."
|
|
11
|
-
})
|
|
12
|
-
};
|
|
13
|
-
const tool = createReadSkillTool();
|
|
14
|
-
const result = await tool.execute({ skill: "Alpha" }, {
|
|
15
|
-
services: { skills }
|
|
16
|
-
});
|
|
17
|
-
expect(skills.get).toHaveBeenCalledWith("Alpha");
|
|
18
|
-
expect(result).toEqual({
|
|
19
|
-
success: true,
|
|
20
|
-
skill: "alpha",
|
|
21
|
-
displayName: "Alpha",
|
|
22
|
-
content: "Use alpha instructions."
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
it("delegates file reads to SkillManager when path is provided", async () => {
|
|
26
|
-
const skills = {
|
|
27
|
-
get: vi.fn(),
|
|
28
|
-
readFile: vi.fn().mockResolvedValue("# Details\nUse more context.")
|
|
29
|
-
};
|
|
30
|
-
const tool = createReadSkillTool();
|
|
31
|
-
const result = await tool.execute({ skill: "Alpha", path: "docs/details.md" }, {
|
|
32
|
-
services: { skills }
|
|
33
|
-
});
|
|
34
|
-
expect(skills.get).not.toHaveBeenCalled();
|
|
35
|
-
expect(skills.readFile).toHaveBeenCalledWith("Alpha", "docs/details.md");
|
|
36
|
-
expect(result).toEqual({
|
|
37
|
-
success: true,
|
|
38
|
-
skill: "Alpha",
|
|
39
|
-
path: "docs/details.md",
|
|
40
|
-
content: "# Details\nUse more context."
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
it("returns a structured error when the skill is missing", async () => {
|
|
44
|
-
const skills = {
|
|
45
|
-
get: vi.fn().mockResolvedValue(null)
|
|
46
|
-
};
|
|
47
|
-
const tool = createReadSkillTool();
|
|
48
|
-
const result = await tool.execute({ skill: "Missing" }, {
|
|
49
|
-
services: { skills }
|
|
50
|
-
});
|
|
51
|
-
expect(result).toEqual({
|
|
52
|
-
success: false,
|
|
53
|
-
error: "Skill not found: Missing",
|
|
54
|
-
_hint: "Use a skill from the available skills list."
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
it("returns a structured error when a skill file is missing", async () => {
|
|
58
|
-
const skills = {
|
|
59
|
-
readFile: vi.fn().mockRejectedValue(new Error("Skill file not found"))
|
|
60
|
-
};
|
|
61
|
-
const tool = createReadSkillTool();
|
|
62
|
-
const result = await tool.execute({ skill: "Alpha", path: "missing.md" }, {
|
|
63
|
-
services: { skills }
|
|
64
|
-
});
|
|
65
|
-
expect(result).toEqual({
|
|
66
|
-
success: false,
|
|
67
|
-
error: "Skill file not found: Alpha/missing.md",
|
|
68
|
-
_hint: "Use a valid file path from the skill bundle."
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
it("requires ToolExecutionContext.services.skills", async () => {
|
|
72
|
-
const tool = createReadSkillTool();
|
|
73
|
-
await expect(
|
|
74
|
-
tool.execute({ skill: "Alpha" }, {})
|
|
75
|
-
).rejects.toMatchObject({
|
|
76
|
-
code: ToolError.configInvalid(
|
|
77
|
-
"read_skill requires ToolExecutionContext.services.skills"
|
|
78
|
-
).code
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
});
|