@studio-foundation/runner 0.3.0-beta.1
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/ARCHITECTURE.md +53 -0
- package/LICENSE +663 -0
- package/README.md +125 -0
- package/configs/agents/analyst.agent.yaml +31 -0
- package/configs/agents/code-generator.agent.yaml +31 -0
- package/configs/agents/generic.agent.yaml +23 -0
- package/dist/__tests__/script-executor.test.d.ts +2 -0
- package/dist/__tests__/script-executor.test.d.ts.map +1 -0
- package/dist/__tests__/script-executor.test.js +173 -0
- package/dist/__tests__/script-executor.test.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/integration-loader.d.ts +20 -0
- package/dist/integrations/integration-loader.d.ts.map +1 -0
- package/dist/integrations/integration-loader.js +71 -0
- package/dist/integrations/integration-loader.js.map +1 -0
- package/dist/integrations/integration-loader.test.d.ts +2 -0
- package/dist/integrations/integration-loader.test.d.ts.map +1 -0
- package/dist/integrations/integration-loader.test.js +77 -0
- package/dist/integrations/integration-loader.test.js.map +1 -0
- package/dist/middleware/anonymization.d.ts +22 -0
- package/dist/middleware/anonymization.d.ts.map +1 -0
- package/dist/middleware/anonymization.js +37 -0
- package/dist/middleware/anonymization.js.map +1 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +10 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/mcp-client.d.ts +19 -0
- package/dist/plugins/mcp-client.d.ts.map +1 -0
- package/dist/plugins/mcp-client.js +126 -0
- package/dist/plugins/mcp-client.js.map +1 -0
- package/dist/plugins/mcp-client.test.d.ts +2 -0
- package/dist/plugins/mcp-client.test.d.ts.map +1 -0
- package/dist/plugins/mcp-client.test.js +160 -0
- package/dist/plugins/mcp-client.test.js.map +1 -0
- package/dist/plugins/oauth-provider.d.ts +27 -0
- package/dist/plugins/oauth-provider.d.ts.map +1 -0
- package/dist/plugins/oauth-provider.js +140 -0
- package/dist/plugins/oauth-provider.js.map +1 -0
- package/dist/plugins/oauth-provider.test.d.ts +2 -0
- package/dist/plugins/oauth-provider.test.d.ts.map +1 -0
- package/dist/plugins/oauth-provider.test.js +144 -0
- package/dist/plugins/oauth-provider.test.js.map +1 -0
- package/dist/plugins/plugin-loader.d.ts +29 -0
- package/dist/plugins/plugin-loader.d.ts.map +1 -0
- package/dist/plugins/plugin-loader.js +71 -0
- package/dist/plugins/plugin-loader.js.map +1 -0
- package/dist/plugins/plugin-loader.test.d.ts +2 -0
- package/dist/plugins/plugin-loader.test.d.ts.map +1 -0
- package/dist/plugins/plugin-loader.test.js +87 -0
- package/dist/plugins/plugin-loader.test.js.map +1 -0
- package/dist/prompt-builder.d.ts +47 -0
- package/dist/prompt-builder.d.ts.map +1 -0
- package/dist/prompt-builder.js +263 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/prompt-builder.test.d.ts +2 -0
- package/dist/prompt-builder.test.d.ts.map +1 -0
- package/dist/prompt-builder.test.js +154 -0
- package/dist/prompt-builder.test.js.map +1 -0
- package/dist/providers/anthropic.d.ts +14 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +118 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/anthropic.test.d.ts +2 -0
- package/dist/providers/anthropic.test.d.ts.map +1 -0
- package/dist/providers/anthropic.test.js +76 -0
- package/dist/providers/anthropic.test.js.map +1 -0
- package/dist/providers/mock.d.ts +17 -0
- package/dist/providers/mock.d.ts.map +1 -0
- package/dist/providers/mock.js +39 -0
- package/dist/providers/mock.js.map +1 -0
- package/dist/providers/ollama.d.ts +18 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +155 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/ollama.test.d.ts +2 -0
- package/dist/providers/ollama.test.d.ts.map +1 -0
- package/dist/providers/ollama.test.js +123 -0
- package/dist/providers/ollama.test.js.map +1 -0
- package/dist/providers/openai-responses.d.ts +18 -0
- package/dist/providers/openai-responses.d.ts.map +1 -0
- package/dist/providers/openai-responses.js +175 -0
- package/dist/providers/openai-responses.js.map +1 -0
- package/dist/providers/openai.d.ts +16 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +132 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openai.test.d.ts +2 -0
- package/dist/providers/openai.test.d.ts.map +1 -0
- package/dist/providers/openai.test.js +51 -0
- package/dist/providers/openai.test.js.map +1 -0
- package/dist/providers/provider.d.ts +42 -0
- package/dist/providers/provider.d.ts.map +1 -0
- package/dist/providers/provider.js +10 -0
- package/dist/providers/provider.js.map +1 -0
- package/dist/providers/registry.d.ts +42 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +65 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/runner.d.ts +46 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +324 -0
- package/dist/runner.js.map +1 -0
- package/dist/runner.test.d.ts +2 -0
- package/dist/runner.test.d.ts.map +1 -0
- package/dist/runner.test.js +280 -0
- package/dist/runner.test.js.map +1 -0
- package/dist/script-executor.d.ts +11 -0
- package/dist/script-executor.d.ts.map +1 -0
- package/dist/script-executor.js +85 -0
- package/dist/script-executor.js.map +1 -0
- package/dist/tools/builtin/git.d.ts +6 -0
- package/dist/tools/builtin/git.d.ts.map +1 -0
- package/dist/tools/builtin/git.js +294 -0
- package/dist/tools/builtin/git.js.map +1 -0
- package/dist/tools/builtin/patch.d.ts +6 -0
- package/dist/tools/builtin/patch.d.ts.map +1 -0
- package/dist/tools/builtin/patch.js +238 -0
- package/dist/tools/builtin/patch.js.map +1 -0
- package/dist/tools/builtin/repo-manager.d.ts +6 -0
- package/dist/tools/builtin/repo-manager.d.ts.map +1 -0
- package/dist/tools/builtin/repo-manager.js +171 -0
- package/dist/tools/builtin/repo-manager.js.map +1 -0
- package/dist/tools/builtin/search.d.ts +6 -0
- package/dist/tools/builtin/search.d.ts.map +1 -0
- package/dist/tools/builtin/search.js +104 -0
- package/dist/tools/builtin/search.js.map +1 -0
- package/dist/tools/builtin/shell.d.ts +6 -0
- package/dist/tools/builtin/shell.d.ts.map +1 -0
- package/dist/tools/builtin/shell.js +78 -0
- package/dist/tools/builtin/shell.js.map +1 -0
- package/dist/tools/builtin/studio-run.d.ts +12 -0
- package/dist/tools/builtin/studio-run.d.ts.map +1 -0
- package/dist/tools/builtin/studio-run.js +61 -0
- package/dist/tools/builtin/studio-run.js.map +1 -0
- package/dist/tools/builtin/web-search.d.ts +7 -0
- package/dist/tools/builtin/web-search.d.ts.map +1 -0
- package/dist/tools/builtin/web-search.js +94 -0
- package/dist/tools/builtin/web-search.js.map +1 -0
- package/dist/tools/builtin/web-search.test.d.ts +5 -0
- package/dist/tools/builtin/web-search.test.d.ts.map +1 -0
- package/dist/tools/builtin/web-search.test.js +90 -0
- package/dist/tools/builtin/web-search.test.js.map +1 -0
- package/dist/tools/errors.d.ts +4 -0
- package/dist/tools/errors.d.ts.map +1 -0
- package/dist/tools/errors.js +11 -0
- package/dist/tools/errors.js.map +1 -0
- package/dist/tools/errors.test.d.ts +2 -0
- package/dist/tools/errors.test.d.ts.map +1 -0
- package/dist/tools/errors.test.js +14 -0
- package/dist/tools/errors.test.js.map +1 -0
- package/dist/tools/plugin-loader.d.ts +31 -0
- package/dist/tools/plugin-loader.d.ts.map +1 -0
- package/dist/tools/plugin-loader.js +183 -0
- package/dist/tools/plugin-loader.js.map +1 -0
- package/dist/tools/plugin-loader.test.d.ts +2 -0
- package/dist/tools/plugin-loader.test.d.ts.map +1 -0
- package/dist/tools/plugin-loader.test.js +116 -0
- package/dist/tools/plugin-loader.test.js.map +1 -0
- package/dist/tools/skills/skill-loader.d.ts +23 -0
- package/dist/tools/skills/skill-loader.d.ts.map +1 -0
- package/dist/tools/skills/skill-loader.js +58 -0
- package/dist/tools/skills/skill-loader.js.map +1 -0
- package/dist/tools/skills/skill-loader.test.d.ts +2 -0
- package/dist/tools/skills/skill-loader.test.d.ts.map +1 -0
- package/dist/tools/skills/skill-loader.test.js +92 -0
- package/dist/tools/skills/skill-loader.test.js.map +1 -0
- package/dist/tools/tool-executor.d.ts +12 -0
- package/dist/tools/tool-executor.d.ts.map +1 -0
- package/dist/tools/tool-executor.js +76 -0
- package/dist/tools/tool-executor.js.map +1 -0
- package/dist/tools/tool-executor.test.d.ts +2 -0
- package/dist/tools/tool-executor.test.d.ts.map +1 -0
- package/dist/tools/tool-executor.test.js +83 -0
- package/dist/tools/tool-executor.test.js.map +1 -0
- package/dist/tools/tool-registry.d.ts +65 -0
- package/dist/tools/tool-registry.d.ts.map +1 -0
- package/dist/tools/tool-registry.js +112 -0
- package/dist/tools/tool-registry.js.map +1 -0
- package/dist/tools/yaml-executor.d.ts +22 -0
- package/dist/tools/yaml-executor.d.ts.map +1 -0
- package/dist/tools/yaml-executor.js +80 -0
- package/dist/tools/yaml-executor.js.map +1 -0
- package/dist/utils/race-signal.d.ts +6 -0
- package/dist/utils/race-signal.d.ts.map +1 -0
- package/dist/utils/race-signal.js +21 -0
- package/dist/utils/race-signal.js.map +1 -0
- package/dist/utils/race-signal.test.d.ts +2 -0
- package/dist/utils/race-signal.test.d.ts.map +1 -0
- package/dist/utils/race-signal.test.js +48 -0
- package/dist/utils/race-signal.test.js.map +1 -0
- package/package.json +36 -0
- package/src/__tests__/script-executor.test.ts +180 -0
- package/src/index.ts +68 -0
- package/src/integrations/integration-loader.test.ts +88 -0
- package/src/integrations/integration-loader.ts +68 -0
- package/src/middleware/anonymization.ts +38 -0
- package/src/plugins/index.ts +4 -0
- package/src/plugins/mcp-client.test.ts +148 -0
- package/src/plugins/mcp-client.ts +128 -0
- package/src/plugins/oauth-provider.test.ts +167 -0
- package/src/plugins/oauth-provider.ts +175 -0
- package/src/plugins/plugin-loader.test.ts +114 -0
- package/src/plugins/plugin-loader.ts +90 -0
- package/src/prompt-builder.test.ts +167 -0
- package/src/prompt-builder.ts +332 -0
- package/src/providers/anthropic.test.ts +101 -0
- package/src/providers/anthropic.ts +135 -0
- package/src/providers/mock.ts +57 -0
- package/src/providers/ollama.test.ts +166 -0
- package/src/providers/ollama.ts +152 -0
- package/src/providers/openai-responses.ts +212 -0
- package/src/providers/openai.test.ts +67 -0
- package/src/providers/openai.ts +139 -0
- package/src/providers/provider.ts +54 -0
- package/src/providers/registry.ts +77 -0
- package/src/runner.test.ts +343 -0
- package/src/runner.ts +396 -0
- package/src/script-executor.ts +107 -0
- package/src/tools/builtin/git.ts +311 -0
- package/src/tools/builtin/patch.ts +257 -0
- package/src/tools/builtin/repo-manager.ts +142 -0
- package/src/tools/builtin/search.ts +108 -0
- package/src/tools/builtin/shell.ts +82 -0
- package/src/tools/builtin/studio-run.ts +73 -0
- package/src/tools/builtin/web-search.test.ts +122 -0
- package/src/tools/builtin/web-search.ts +101 -0
- package/src/tools/errors.test.ts +12 -0
- package/src/tools/errors.ts +6 -0
- package/src/tools/plugin-loader.test.ts +130 -0
- package/src/tools/plugin-loader.ts +203 -0
- package/src/tools/skills/README.md +49 -0
- package/src/tools/skills/skill-loader.test.ts +106 -0
- package/src/tools/skills/skill-loader.ts +62 -0
- package/src/tools/tool-executor.test.ts +88 -0
- package/src/tools/tool-executor.ts +84 -0
- package/src/tools/tool-registry.ts +130 -0
- package/src/tools/yaml-executor.ts +120 -0
- package/src/utils/race-signal.test.ts +50 -0
- package/src/utils/race-signal.ts +17 -0
- package/templates/integrations/linear.integration.yaml +35 -0
- package/templates/integrations/slack.integration.yaml +22 -0
- package/templates/integrations/webhook.integration.yaml +17 -0
- package/templates/tools/git.tool.yaml +80 -0
- package/templates/tools/repo-manager.tool.yaml +64 -0
- package/templates/tools/search.tool.yaml +22 -0
- package/templates/tools/shell.tool.yaml +19 -0
- package/templates/tools/web-search.tool.yaml +24 -0
- package/tests/anonymization-middleware.test.ts +61 -0
- package/tests/anthropic.test.ts +87 -0
- package/tests/apply-patch.test.ts +355 -0
- package/tests/fixtures/tools/test-builtin.tool.yaml +14 -0
- package/tests/fixtures/tools/test-shell.tool.yaml +19 -0
- package/tests/mock-provider.test.ts +104 -0
- package/tests/openai.test.ts +72 -0
- package/tests/plugin-loader.test.ts +54 -0
- package/tests/prompt-builder.test.ts +468 -0
- package/tests/runner-anonymization.test.ts +89 -0
- package/tests/runner.test.ts +885 -0
- package/tests/studio-run.test.ts +94 -0
- package/tests/tool-executor.test.ts +115 -0
- package/tests/tool-registry.test.ts +84 -0
- package/tests/yaml-executor.test.ts +76 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for the web_search builtin tool
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const web_search_js_1 = require("./web-search.js");
|
|
8
|
+
(0, vitest_1.describe)('createWebSearchTools', () => {
|
|
9
|
+
(0, vitest_1.afterEach)(() => {
|
|
10
|
+
vitest_1.vi.restoreAllMocks();
|
|
11
|
+
delete process.env.TAVILY_API_KEY;
|
|
12
|
+
});
|
|
13
|
+
(0, vitest_1.it)('returns a single tool named web_search-search', () => {
|
|
14
|
+
const tools = (0, web_search_js_1.createWebSearchTools)();
|
|
15
|
+
(0, vitest_1.expect)(tools).toHaveLength(1);
|
|
16
|
+
(0, vitest_1.expect)(tools[0].name).toBe('web_search-search');
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.it)('requires query parameter', () => {
|
|
19
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
20
|
+
const schema = tool.parameters;
|
|
21
|
+
(0, vitest_1.expect)(schema.required).toContain('query');
|
|
22
|
+
});
|
|
23
|
+
(0, vitest_1.it)('returns error when TAVILY_API_KEY is not set', async () => {
|
|
24
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
25
|
+
const result = await tool.execute({ query: 'test' });
|
|
26
|
+
(0, vitest_1.expect)(result.success).toBe(false);
|
|
27
|
+
(0, vitest_1.expect)(result.error).toMatch(/TAVILY_API_KEY/);
|
|
28
|
+
});
|
|
29
|
+
(0, vitest_1.it)('calls Tavily API and returns results', async () => {
|
|
30
|
+
process.env.TAVILY_API_KEY = 'test-key';
|
|
31
|
+
const mockResponse = {
|
|
32
|
+
results: [
|
|
33
|
+
{ title: 'Result 1', url: 'https://example.com/1', content: 'Content 1', score: 0.9 },
|
|
34
|
+
{ title: 'Result 2', url: 'https://example.com/2', content: 'Content 2', score: 0.8 },
|
|
35
|
+
],
|
|
36
|
+
answer: 'A direct answer'
|
|
37
|
+
};
|
|
38
|
+
vitest_1.vi.spyOn(global, 'fetch').mockResolvedValueOnce(new Response(JSON.stringify(mockResponse), { status: 200 }));
|
|
39
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
40
|
+
const result = await tool.execute({ query: 'test query', max_results: 2 });
|
|
41
|
+
(0, vitest_1.expect)(result.success).toBe(true);
|
|
42
|
+
const output = result.output;
|
|
43
|
+
(0, vitest_1.expect)(output.query).toBe('test query');
|
|
44
|
+
(0, vitest_1.expect)(output.results).toHaveLength(2);
|
|
45
|
+
(0, vitest_1.expect)(output.results[0].title).toBe('Result 1');
|
|
46
|
+
(0, vitest_1.expect)(output.answer).toBe('A direct answer');
|
|
47
|
+
(0, vitest_1.expect)(output.count).toBe(2);
|
|
48
|
+
});
|
|
49
|
+
(0, vitest_1.it)('passes max_results to Tavily API', async () => {
|
|
50
|
+
process.env.TAVILY_API_KEY = 'test-key';
|
|
51
|
+
vitest_1.vi.spyOn(global, 'fetch').mockResolvedValueOnce(new Response(JSON.stringify({ results: [], answer: null }), { status: 200 }));
|
|
52
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
53
|
+
await tool.execute({ query: 'test', max_results: 3 });
|
|
54
|
+
const [, options] = fetch.mock.calls[0];
|
|
55
|
+
const body = JSON.parse(options.body);
|
|
56
|
+
(0, vitest_1.expect)(body.max_results).toBe(3);
|
|
57
|
+
});
|
|
58
|
+
(0, vitest_1.it)('defaults max_results to 5 when not provided', async () => {
|
|
59
|
+
process.env.TAVILY_API_KEY = 'test-key';
|
|
60
|
+
vitest_1.vi.spyOn(global, 'fetch').mockResolvedValueOnce(new Response(JSON.stringify({ results: [] }), { status: 200 }));
|
|
61
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
62
|
+
await tool.execute({ query: 'test' });
|
|
63
|
+
const [, options] = fetch.mock.calls[0];
|
|
64
|
+
const body = JSON.parse(options.body);
|
|
65
|
+
(0, vitest_1.expect)(body.max_results).toBe(5);
|
|
66
|
+
});
|
|
67
|
+
(0, vitest_1.it)('returns error on non-ok API response', async () => {
|
|
68
|
+
process.env.TAVILY_API_KEY = 'test-key';
|
|
69
|
+
vitest_1.vi.spyOn(global, 'fetch').mockResolvedValueOnce(new Response('Unauthorized', { status: 401 }));
|
|
70
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
71
|
+
const result = await tool.execute({ query: 'test' });
|
|
72
|
+
(0, vitest_1.expect)(result.success).toBe(false);
|
|
73
|
+
(0, vitest_1.expect)(result.error).toMatch(/401/);
|
|
74
|
+
});
|
|
75
|
+
(0, vitest_1.it)('returns error on network failure', async () => {
|
|
76
|
+
process.env.TAVILY_API_KEY = 'test-key';
|
|
77
|
+
vitest_1.vi.spyOn(global, 'fetch').mockRejectedValueOnce(new Error('Network error'));
|
|
78
|
+
const [tool] = (0, web_search_js_1.createWebSearchTools)();
|
|
79
|
+
const result = await tool.execute({ query: 'test' });
|
|
80
|
+
(0, vitest_1.expect)(result.success).toBe(false);
|
|
81
|
+
(0, vitest_1.expect)(result.error).toMatch(/Network error/);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
(0, vitest_1.describe)('WEB_SEARCH_PROMPT_SNIPPET', () => {
|
|
85
|
+
(0, vitest_1.it)('is a non-empty string', () => {
|
|
86
|
+
(0, vitest_1.expect)(typeof web_search_js_1.WEB_SEARCH_PROMPT_SNIPPET).toBe('string');
|
|
87
|
+
(0, vitest_1.expect)(web_search_js_1.WEB_SEARCH_PROMPT_SNIPPET.length).toBeGreaterThan(0);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=web-search.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.test.js","sourceRoot":"","sources":["../../../src/tools/builtin/web-search.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/tools/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolYamlError = void 0;
|
|
4
|
+
class ToolYamlError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'ToolYamlError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ToolYamlError = ToolYamlError;
|
|
11
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/tools/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AALD,sCAKC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.test.d.ts","sourceRoot":"","sources":["../../src/tools/errors.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// runner/src/tools/errors.test.ts
|
|
4
|
+
const vitest_1 = require("vitest");
|
|
5
|
+
const errors_js_1 = require("./errors.js");
|
|
6
|
+
(0, vitest_1.describe)('ToolYamlError', () => {
|
|
7
|
+
(0, vitest_1.it)('is an Error with name ToolYamlError', () => {
|
|
8
|
+
const err = new errors_js_1.ToolYamlError('bad yaml');
|
|
9
|
+
(0, vitest_1.expect)(err).toBeInstanceOf(Error);
|
|
10
|
+
(0, vitest_1.expect)(err.name).toBe('ToolYamlError');
|
|
11
|
+
(0, vitest_1.expect)(err.message).toBe('bad yaml');
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=errors.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.test.js","sourceRoot":"","sources":["../../src/tools/errors.test.ts"],"names":[],"mappings":";;AAAA,kCAAkC;AAClC,mCAA8C;AAC9C,2CAA4C;AAE5C,IAAA,iBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAA,WAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,GAAG,GAAG,IAAI,yBAAa,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAA,eAAM,EAAC,GAAG,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAClC,IAAA,eAAM,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACvC,IAAA,eAAM,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Tool } from './tool-registry.js';
|
|
2
|
+
export interface LoadedPlugin {
|
|
3
|
+
name: string;
|
|
4
|
+
tools: Tool[];
|
|
5
|
+
promptSnippet?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Load all `.tool.yaml` files from a project's tools directory.
|
|
9
|
+
* Returns an empty array if the directory does not exist.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadProjectTools(toolsDir: string, repoPath: string): Promise<LoadedPlugin[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Names of built-in tool plugins that have bundled installable templates.
|
|
14
|
+
* Mirrors runner/templates/tools/*.tool.yaml.
|
|
15
|
+
* Note: 'patch' is a TypeScript-only builtin with no installable template and is intentionally excluded.
|
|
16
|
+
*/
|
|
17
|
+
export declare const BUILTIN_TOOL_NAMES: Set<string>;
|
|
18
|
+
/**
|
|
19
|
+
* List all tool plugins available for installation from the bundled registry.
|
|
20
|
+
* Returns an array of { name, description } objects.
|
|
21
|
+
*/
|
|
22
|
+
export declare function listAvailableToolTemplates(): Promise<{
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
}[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Return the raw YAML content of a bundled tool template by name.
|
|
28
|
+
* Returns null if the tool does not exist in the bundled registry.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getBundledToolTemplate(name: string): Promise<string | null>;
|
|
31
|
+
//# sourceMappingURL=plugin-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../../src/tools/plugin-loader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAU/C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAoFD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAwCzB;AAOD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAM7B,CAAC;AAEH;;;GAGG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAcnG;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOjF"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BUILTIN_TOOL_NAMES = void 0;
|
|
7
|
+
exports.loadProjectTools = loadProjectTools;
|
|
8
|
+
exports.listAvailableToolTemplates = listAvailableToolTemplates;
|
|
9
|
+
exports.getBundledToolTemplate = getBundledToolTemplate;
|
|
10
|
+
// runner/src/tools/plugin-loader.ts
|
|
11
|
+
const promises_1 = require("node:fs/promises");
|
|
12
|
+
const node_fs_1 = require("node:fs");
|
|
13
|
+
const node_path_1 = require("node:path");
|
|
14
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
15
|
+
const yaml_executor_js_1 = require("./yaml-executor.js");
|
|
16
|
+
const repo_manager_js_1 = require("./builtin/repo-manager.js");
|
|
17
|
+
const shell_js_1 = require("./builtin/shell.js");
|
|
18
|
+
const search_js_1 = require("./builtin/search.js");
|
|
19
|
+
const patch_js_1 = require("./builtin/patch.js");
|
|
20
|
+
const git_js_1 = require("./builtin/git.js");
|
|
21
|
+
const web_search_js_1 = require("./builtin/web-search.js");
|
|
22
|
+
const errors_js_1 = require("./errors.js");
|
|
23
|
+
/** Build a map of tool name → Tool from all builtin factories. */
|
|
24
|
+
function buildBuiltinMap(repoPath) {
|
|
25
|
+
const map = new Map();
|
|
26
|
+
const add = (tools) => tools.forEach(t => map.set(t.name, t));
|
|
27
|
+
add((0, repo_manager_js_1.createRepoManagerTools)(repoPath));
|
|
28
|
+
add((0, shell_js_1.createShellTools)(repoPath));
|
|
29
|
+
add((0, search_js_1.createSearchTools)(repoPath));
|
|
30
|
+
add((0, patch_js_1.createPatchTools)(repoPath));
|
|
31
|
+
add((0, git_js_1.createGitTools)(repoPath));
|
|
32
|
+
add((0, web_search_js_1.createWebSearchTools)());
|
|
33
|
+
return map;
|
|
34
|
+
}
|
|
35
|
+
/** Convert a ParameterDef map to a JSON Schema object for the LLM. */
|
|
36
|
+
function buildJsonSchema(parameters) {
|
|
37
|
+
const properties = {};
|
|
38
|
+
const required = [];
|
|
39
|
+
for (const [key, def] of Object.entries(parameters ?? {})) {
|
|
40
|
+
properties[key] = {
|
|
41
|
+
type: def.type,
|
|
42
|
+
...(def.description ? { description: def.description } : {}),
|
|
43
|
+
...(def.type === 'array' && def.items ? { items: def.items } : {}),
|
|
44
|
+
};
|
|
45
|
+
if (def.required)
|
|
46
|
+
required.push(key);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties,
|
|
51
|
+
...(required.length > 0 ? { required } : {}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Template keywords that appear as {{word}} but are not parameter names.
|
|
55
|
+
* Note: block tags like {{#if}} and {{/if}} are already excluded because
|
|
56
|
+
* '#' and '/' are not matched by [\w-]+. */
|
|
57
|
+
const TEMPLATE_KEYWORDS = new Set(['else']);
|
|
58
|
+
/**
|
|
59
|
+
* Validate that every {{placeholder}} in a shell command template
|
|
60
|
+
* is declared in the command's parameters.
|
|
61
|
+
* Throws ToolYamlError if any undeclared placeholder is found.
|
|
62
|
+
*/
|
|
63
|
+
function validateShellTemplate(fileName, cmd) {
|
|
64
|
+
const exec = cmd.execute;
|
|
65
|
+
if (exec.type !== 'shell' || !exec.command)
|
|
66
|
+
return;
|
|
67
|
+
const declared = new Set(Object.keys(cmd.parameters ?? {}));
|
|
68
|
+
const used = new Set();
|
|
69
|
+
for (const match of exec.command.matchAll(/\{\{([\w-]+)\}\}/g)) {
|
|
70
|
+
const name = match[1];
|
|
71
|
+
if (!TEMPLATE_KEYWORDS.has(name))
|
|
72
|
+
used.add(name);
|
|
73
|
+
}
|
|
74
|
+
const unknown = [...used].filter(p => !declared.has(p));
|
|
75
|
+
if (unknown.length > 0) {
|
|
76
|
+
throw new errors_js_1.ToolYamlError(`${fileName} › command '${cmd.name}':\n` +
|
|
77
|
+
` template uses ${unknown.map(p => `{{${p}}}`).join(', ')} but no such parameter is declared.\n` +
|
|
78
|
+
` Declared parameters: ${[...declared].join(', ') || '(none)'}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Create a Tool that renders the command template and runs it in a shell. */
|
|
82
|
+
function createShellTool(cmd, repoPath, configsDir) {
|
|
83
|
+
const exec = cmd.execute;
|
|
84
|
+
return {
|
|
85
|
+
name: cmd.name,
|
|
86
|
+
description: cmd.description,
|
|
87
|
+
parameters: buildJsonSchema(cmd.parameters),
|
|
88
|
+
async execute(args) {
|
|
89
|
+
const rendered = (0, yaml_executor_js_1.renderTemplate)(exec.command, args);
|
|
90
|
+
return (0, yaml_executor_js_1.executeShellCommand)(rendered, exec.parse_output ?? 'text', repoPath, exec.timeout_ms, { STUDIO_CONFIG_DIR: configsDir });
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Load all `.tool.yaml` files from a project's tools directory.
|
|
96
|
+
* Returns an empty array if the directory does not exist.
|
|
97
|
+
*/
|
|
98
|
+
async function loadProjectTools(toolsDir, repoPath) {
|
|
99
|
+
if (!(0, node_fs_1.existsSync)(toolsDir))
|
|
100
|
+
return [];
|
|
101
|
+
let files;
|
|
102
|
+
try {
|
|
103
|
+
files = (await (0, promises_1.readdir)(toolsDir)).filter(f => f.endsWith('.tool.yaml'));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
if (files.length === 0)
|
|
109
|
+
return [];
|
|
110
|
+
const configsDir = (0, node_path_1.resolve)((0, node_path_1.dirname)(toolsDir));
|
|
111
|
+
const builtinMap = buildBuiltinMap(repoPath);
|
|
112
|
+
const plugins = [];
|
|
113
|
+
for (const file of files.sort()) {
|
|
114
|
+
const content = await (0, promises_1.readFile)((0, node_path_1.resolve)(toolsDir, file), 'utf-8');
|
|
115
|
+
const def = js_yaml_1.default.load(content);
|
|
116
|
+
const tools = [];
|
|
117
|
+
for (const cmd of def.commands ?? []) {
|
|
118
|
+
if (cmd.execute.type === 'builtin') {
|
|
119
|
+
const tool = builtinMap.get(cmd.name);
|
|
120
|
+
if (tool)
|
|
121
|
+
tools.push(tool);
|
|
122
|
+
// If unknown builtin name, skip silently (no crash)
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
validateShellTemplate(file, cmd);
|
|
126
|
+
tools.push(createShellTool(cmd, repoPath, configsDir));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
plugins.push({
|
|
130
|
+
name: def.name,
|
|
131
|
+
tools,
|
|
132
|
+
promptSnippet: def.prompt_snippet,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return plugins;
|
|
136
|
+
}
|
|
137
|
+
const BUNDLED_TOOL_TEMPLATES_DIR = (0, node_path_1.resolve)(__dirname, '../../templates/tools');
|
|
138
|
+
/**
|
|
139
|
+
* Names of built-in tool plugins that have bundled installable templates.
|
|
140
|
+
* Mirrors runner/templates/tools/*.tool.yaml.
|
|
141
|
+
* Note: 'patch' is a TypeScript-only builtin with no installable template and is intentionally excluded.
|
|
142
|
+
*/
|
|
143
|
+
exports.BUILTIN_TOOL_NAMES = new Set([
|
|
144
|
+
'repo-manager',
|
|
145
|
+
'shell',
|
|
146
|
+
'search',
|
|
147
|
+
'git',
|
|
148
|
+
'web-search',
|
|
149
|
+
]);
|
|
150
|
+
/**
|
|
151
|
+
* List all tool plugins available for installation from the bundled registry.
|
|
152
|
+
* Returns an array of { name, description } objects.
|
|
153
|
+
*/
|
|
154
|
+
async function listAvailableToolTemplates() {
|
|
155
|
+
let files;
|
|
156
|
+
try {
|
|
157
|
+
files = (await (0, promises_1.readdir)(BUNDLED_TOOL_TEMPLATES_DIR)).filter(f => f.endsWith('.tool.yaml')).sort();
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
const result = [];
|
|
163
|
+
for (const file of files) {
|
|
164
|
+
const content = await (0, promises_1.readFile)((0, node_path_1.resolve)(BUNDLED_TOOL_TEMPLATES_DIR, file), 'utf-8');
|
|
165
|
+
const def = js_yaml_1.default.load(content);
|
|
166
|
+
result.push({ name: file.replace('.tool.yaml', ''), description: def.description ?? '' });
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Return the raw YAML content of a bundled tool template by name.
|
|
172
|
+
* Returns null if the tool does not exist in the bundled registry.
|
|
173
|
+
*/
|
|
174
|
+
async function getBundledToolTemplate(name) {
|
|
175
|
+
const filePath = (0, node_path_1.resolve)(BUNDLED_TOOL_TEMPLATES_DIR, `${name}.tool.yaml`);
|
|
176
|
+
try {
|
|
177
|
+
return await (0, promises_1.readFile)(filePath, 'utf-8');
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=plugin-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.js","sourceRoot":"","sources":["../../src/tools/plugin-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.test.d.ts","sourceRoot":"","sources":["../../src/tools/plugin-loader.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const node_os_1 = require("node:os");
|
|
7
|
+
const plugin_loader_js_1 = require("./plugin-loader.js");
|
|
8
|
+
const errors_js_1 = require("./errors.js");
|
|
9
|
+
let tmpDir;
|
|
10
|
+
(0, vitest_1.beforeAll)(async () => {
|
|
11
|
+
tmpDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'studio-tool-loader-test-'));
|
|
12
|
+
});
|
|
13
|
+
(0, vitest_1.afterAll)(async () => {
|
|
14
|
+
await (0, promises_1.rm)(tmpDir, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
async function writeToolYaml(name, content) {
|
|
17
|
+
const dir = (0, node_path_1.join)(tmpDir, name);
|
|
18
|
+
await (0, promises_1.mkdir)(dir, { recursive: true });
|
|
19
|
+
const toolsDir = (0, node_path_1.join)(dir, 'tools');
|
|
20
|
+
await (0, promises_1.mkdir)(toolsDir, { recursive: true });
|
|
21
|
+
await (0, promises_1.writeFile)((0, node_path_1.join)(toolsDir, `${name}.tool.yaml`), content);
|
|
22
|
+
return toolsDir;
|
|
23
|
+
}
|
|
24
|
+
(0, vitest_1.describe)('loadProjectTools — shell template validation', () => {
|
|
25
|
+
(0, vitest_1.it)('throws ToolYamlError when template uses undeclared placeholder', async () => {
|
|
26
|
+
const toolsDir = await writeToolYaml('bad-search', `
|
|
27
|
+
name: bad_search
|
|
28
|
+
version: 1
|
|
29
|
+
commands:
|
|
30
|
+
- name: bad_search-search
|
|
31
|
+
description: Search
|
|
32
|
+
parameters:
|
|
33
|
+
query:
|
|
34
|
+
type: string
|
|
35
|
+
required: true
|
|
36
|
+
execute:
|
|
37
|
+
type: shell
|
|
38
|
+
command: 'curl "https://api.example.com?q={{search_query}}"'
|
|
39
|
+
`);
|
|
40
|
+
const promise = (0, plugin_loader_js_1.loadProjectTools)(toolsDir, '/tmp');
|
|
41
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow(errors_js_1.ToolYamlError);
|
|
42
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow(errors_js_1.ToolYamlError);
|
|
43
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow("template uses {{search_query}} but no such parameter is declared");
|
|
44
|
+
});
|
|
45
|
+
(0, vitest_1.it)('loads successfully when all template placeholders are declared', async () => {
|
|
46
|
+
const toolsDir = await writeToolYaml('good-search', `
|
|
47
|
+
name: good_search
|
|
48
|
+
version: 1
|
|
49
|
+
commands:
|
|
50
|
+
- name: good_search-search
|
|
51
|
+
description: Search
|
|
52
|
+
parameters:
|
|
53
|
+
query:
|
|
54
|
+
type: string
|
|
55
|
+
required: true
|
|
56
|
+
execute:
|
|
57
|
+
type: shell
|
|
58
|
+
command: 'curl "https://api.example.com?q={{query}}"'
|
|
59
|
+
`);
|
|
60
|
+
await (0, vitest_1.expect)((0, plugin_loader_js_1.loadProjectTools)(toolsDir, '/tmp')).resolves.toHaveLength(1);
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.it)('does not flag {{else}} as an undeclared placeholder', async () => {
|
|
63
|
+
const toolsDir = await writeToolYaml('conditional-tool', `
|
|
64
|
+
name: conditional_tool
|
|
65
|
+
version: 1
|
|
66
|
+
commands:
|
|
67
|
+
- name: conditional_tool-run
|
|
68
|
+
description: Run with optional flag
|
|
69
|
+
parameters:
|
|
70
|
+
verbose:
|
|
71
|
+
type: boolean
|
|
72
|
+
required: false
|
|
73
|
+
execute:
|
|
74
|
+
type: shell
|
|
75
|
+
command: 'echo {{#if verbose}}--verbose{{else}}--quiet{{/if}}'
|
|
76
|
+
`);
|
|
77
|
+
await (0, vitest_1.expect)((0, plugin_loader_js_1.loadProjectTools)(toolsDir, '/tmp')).resolves.toHaveLength(1);
|
|
78
|
+
});
|
|
79
|
+
(0, vitest_1.it)('error message includes filename, command name, and declared parameters', async () => {
|
|
80
|
+
const toolsDir = await writeToolYaml('err-msg', `
|
|
81
|
+
name: err_msg
|
|
82
|
+
version: 1
|
|
83
|
+
commands:
|
|
84
|
+
- name: err_msg-run
|
|
85
|
+
description: Run
|
|
86
|
+
parameters:
|
|
87
|
+
query:
|
|
88
|
+
type: string
|
|
89
|
+
required: true
|
|
90
|
+
execute:
|
|
91
|
+
type: shell
|
|
92
|
+
command: 'curl {{typo}}'
|
|
93
|
+
`);
|
|
94
|
+
const promise = (0, plugin_loader_js_1.loadProjectTools)(toolsDir, '/tmp');
|
|
95
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow(errors_js_1.ToolYamlError);
|
|
96
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow("err-msg.tool.yaml › command 'err_msg-run'");
|
|
97
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow("Declared parameters: query");
|
|
98
|
+
});
|
|
99
|
+
(0, vitest_1.it)('error message shows (none) when command has no parameters declared', async () => {
|
|
100
|
+
const toolsDir = await writeToolYaml('no-params', `
|
|
101
|
+
name: no_params
|
|
102
|
+
version: 1
|
|
103
|
+
commands:
|
|
104
|
+
- name: no_params-run
|
|
105
|
+
description: Run
|
|
106
|
+
parameters: {}
|
|
107
|
+
execute:
|
|
108
|
+
type: shell
|
|
109
|
+
command: 'curl {{typo}}'
|
|
110
|
+
`);
|
|
111
|
+
const promise = (0, plugin_loader_js_1.loadProjectTools)(toolsDir, '/tmp');
|
|
112
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow(errors_js_1.ToolYamlError);
|
|
113
|
+
await (0, vitest_1.expect)(promise).rejects.toThrow("Declared parameters: (none)");
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=plugin-loader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-loader.test.js","sourceRoot":"","sources":["../../src/tools/plugin-loader.test.ts"],"names":[],"mappings":";;AAAA,mCAAmE;AACnE,+CAAiE;AACjE,yCAAiC;AACjC,qCAAiC;AACjC,yDAAsD;AACtD,2CAA4C;AAE5C,IAAI,MAAc,CAAC;AAEnB,IAAA,kBAAS,EAAC,KAAK,IAAI,EAAE;IACnB,MAAM,GAAG,MAAM,IAAA,kBAAO,EAAC,IAAA,gBAAI,EAAC,IAAA,gBAAM,GAAE,EAAE,0BAA0B,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,KAAK,IAAI,EAAE;IAClB,MAAM,IAAA,aAAE,EAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACxD,MAAM,GAAG,GAAG,IAAA,gBAAI,EAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAA,gBAAK,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,IAAA,gBAAK,EAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,IAAA,oBAAS,EAAC,IAAA,gBAAI,EAAC,QAAQ,EAAE,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9D,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,IAAA,iBAAQ,EAAC,8CAA8C,EAAE,GAAG,EAAE;IAC5D,IAAA,WAAE,EAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE;;;;;;;;;;;;;CAatD,CAAC,CAAC;QACC,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAa,CAAC,CAAC;QACrD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAa,CAAC,CAAC;QACrD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CACnC,kEAAkE,CACnE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,aAAa,EAAE;;;;;;;;;;;;;CAavD,CAAC,CAAC;QACC,MAAM,IAAA,eAAM,EAAC,IAAA,mCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,kBAAkB,EAAE;;;;;;;;;;;;;CAa5D,CAAC,CAAC;QACC,MAAM,IAAA,eAAM,EAAC,IAAA,mCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE;;;;;;;;;;;;;CAanD,CAAC,CAAC;QACC,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAa,CAAC,CAAC;QACrD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CACnC,2CAA2C,CAC5C,CAAC;QACF,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CACnC,4BAA4B,CAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE;;;;;;;;;;CAUrD,CAAC,CAAC;QACC,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAa,CAAC,CAAC;QACrD,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CACnC,6BAA6B,CAC9B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SkillContent } from '../../plugins/plugin-loader.js';
|
|
2
|
+
export type { SkillContent };
|
|
3
|
+
/** Minimal structure required for a valid skill manifest */
|
|
4
|
+
export interface SkillManifest {
|
|
5
|
+
name: string;
|
|
6
|
+
content: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Load multiple `.skill.md` files by name from `.studio/skills/`.
|
|
10
|
+
* Missing files are skipped with a warning (non-fatal).
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadSkills(skillNames: string[], studioDir: string): Promise<SkillContent[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Load a single `.skill.md` file by name from `<studioDir>/skills/`.
|
|
15
|
+
* Returns null if the file does not exist.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadSkill(name: string, studioDir: string): Promise<SkillContent | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Validate that a skill manifest has the required structure.
|
|
20
|
+
* Throws a descriptive error if invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateSkillManifest(manifest: unknown): boolean;
|
|
23
|
+
//# sourceMappingURL=skill-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../../../src/tools/skills/skill-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAOjG;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAa7F;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAYhE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadSkills = loadSkills;
|
|
4
|
+
exports.loadSkill = loadSkill;
|
|
5
|
+
exports.validateSkillManifest = validateSkillManifest;
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
/**
|
|
10
|
+
* Load multiple `.skill.md` files by name from `.studio/skills/`.
|
|
11
|
+
* Missing files are skipped with a warning (non-fatal).
|
|
12
|
+
*/
|
|
13
|
+
async function loadSkills(skillNames, studioDir) {
|
|
14
|
+
const results = [];
|
|
15
|
+
for (const name of skillNames) {
|
|
16
|
+
const skill = await loadSkill(name, studioDir);
|
|
17
|
+
if (skill)
|
|
18
|
+
results.push(skill);
|
|
19
|
+
}
|
|
20
|
+
return results;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Load a single `.skill.md` file by name from `<studioDir>/skills/`.
|
|
24
|
+
* Returns null if the file does not exist.
|
|
25
|
+
*/
|
|
26
|
+
async function loadSkill(name, studioDir) {
|
|
27
|
+
const filePath = (0, node_path_1.join)(studioDir, 'skills', `${name}.skill.md`);
|
|
28
|
+
if (!(0, node_fs_1.existsSync)(filePath)) {
|
|
29
|
+
console.warn(`[studio] Skill '${name}' not found at ${filePath} — skipping.`);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const content = await (0, promises_1.readFile)(filePath, 'utf-8');
|
|
34
|
+
return { name, content };
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
console.warn(`[studio] Failed to load skill '${name}' — skipping.`);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate that a skill manifest has the required structure.
|
|
43
|
+
* Throws a descriptive error if invalid.
|
|
44
|
+
*/
|
|
45
|
+
function validateSkillManifest(manifest) {
|
|
46
|
+
if (!manifest || typeof manifest !== 'object') {
|
|
47
|
+
throw new Error('Skill manifest must be an object');
|
|
48
|
+
}
|
|
49
|
+
const m = manifest;
|
|
50
|
+
if (typeof m.name !== 'string') {
|
|
51
|
+
throw new Error('Skill manifest must have a string "name" field');
|
|
52
|
+
}
|
|
53
|
+
if (typeof m.content !== 'string') {
|
|
54
|
+
throw new Error('Skill manifest must have a string "content" field');
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=skill-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../../../src/tools/skills/skill-loader.ts"],"names":[],"mappings":";;AAiBA,gCAOC;AAMD,8BAaC;AAMD,sDAYC;AA7DD,+CAA4C;AAC5C,qCAAqC;AACrC,yCAAiC;AAWjC;;;GAGG;AACI,KAAK,UAAU,UAAU,CAAC,UAAoB,EAAE,SAAiB;IACtE,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,SAAiB;IAC7D,MAAM,QAAQ,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC;IAC/D,IAAI,CAAC,IAAA,oBAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,mBAAmB,IAAI,kBAAkB,QAAQ,cAAc,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,kCAAkC,IAAI,eAAe,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,QAAiB;IACrD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,CAAC,GAAG,QAAmC,CAAC;IAC9C,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.test.d.ts","sourceRoot":"","sources":["../../../src/tools/skills/skill-loader.test.ts"],"names":[],"mappings":""}
|