toolpack-cli 0.1.0-SNAPSHOT

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.
Files changed (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +131 -0
  3. package/dist/app.d.ts +1 -0
  4. package/dist/app.js +15 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +29 -0
  7. package/dist/commands/clear.d.ts +3 -0
  8. package/dist/commands/clear.js +15 -0
  9. package/dist/commands/help.d.ts +3 -0
  10. package/dist/commands/help.js +29 -0
  11. package/dist/commands/index.d.ts +15 -0
  12. package/dist/commands/index.js +16 -0
  13. package/dist/commands/info.d.ts +3 -0
  14. package/dist/commands/info.js +24 -0
  15. package/dist/commands/mode.d.ts +3 -0
  16. package/dist/commands/mode.js +51 -0
  17. package/dist/commands/model.d.ts +3 -0
  18. package/dist/commands/model.js +14 -0
  19. package/dist/commands/registry.d.ts +32 -0
  20. package/dist/commands/registry.js +86 -0
  21. package/dist/commands/tool-log.d.ts +3 -0
  22. package/dist/commands/tool-log.js +17 -0
  23. package/dist/commands/tool-search.d.ts +3 -0
  24. package/dist/commands/tool-search.js +57 -0
  25. package/dist/commands/tools.d.ts +3 -0
  26. package/dist/commands/tools.js +45 -0
  27. package/dist/commands/types.d.ts +25 -0
  28. package/dist/commands/types.js +4 -0
  29. package/dist/commands/version.d.ts +3 -0
  30. package/dist/commands/version.js +25 -0
  31. package/dist/components/AppInfo.d.ts +1 -0
  32. package/dist/components/AppInfo.js +10 -0
  33. package/dist/components/HomeInput.d.ts +11 -0
  34. package/dist/components/HomeInput.js +328 -0
  35. package/dist/components/Logo.d.ts +1 -0
  36. package/dist/components/Logo.js +15 -0
  37. package/dist/components/Markdown.d.ts +5 -0
  38. package/dist/components/Markdown.js +121 -0
  39. package/dist/components/ProviderBar.d.ts +12 -0
  40. package/dist/components/ProviderBar.js +32 -0
  41. package/dist/components/ShimmerText.d.ts +8 -0
  42. package/dist/components/ShimmerText.js +20 -0
  43. package/dist/components/ToolLogPopup.d.ts +7 -0
  44. package/dist/components/ToolLogPopup.js +87 -0
  45. package/dist/components/common/HistorySelect.d.ts +6 -0
  46. package/dist/components/common/HistorySelect.js +57 -0
  47. package/dist/components/common/Modal.d.ts +10 -0
  48. package/dist/components/common/Modal.js +13 -0
  49. package/dist/components/common/ModeSelect.d.ts +6 -0
  50. package/dist/components/common/ModeSelect.js +13 -0
  51. package/dist/components/common/ModelSelect.d.ts +9 -0
  52. package/dist/components/common/ModelSelect.js +45 -0
  53. package/dist/context/ConversationContext.d.ts +44 -0
  54. package/dist/context/ConversationContext.js +113 -0
  55. package/dist/context/ToolpackContext.d.ts +55 -0
  56. package/dist/context/ToolpackContext.js +221 -0
  57. package/dist/custom-providers/AnthropicCustomAdapter.d.ts +49 -0
  58. package/dist/custom-providers/AnthropicCustomAdapter.js +297 -0
  59. package/dist/custom-providers/XAIAdapter.d.ts +40 -0
  60. package/dist/custom-providers/XAIAdapter.js +295 -0
  61. package/dist/custom-tools/skill-tools/index.d.ts +33 -0
  62. package/dist/custom-tools/skill-tools/index.js +63 -0
  63. package/dist/custom-tools/skill-tools/tools/create/index.d.ts +2 -0
  64. package/dist/custom-tools/skill-tools/tools/create/index.js +93 -0
  65. package/dist/custom-tools/skill-tools/tools/create/schema.d.ts +6 -0
  66. package/dist/custom-tools/skill-tools/tools/create/schema.js +41 -0
  67. package/dist/custom-tools/skill-tools/tools/list/index.d.ts +2 -0
  68. package/dist/custom-tools/skill-tools/tools/list/index.js +113 -0
  69. package/dist/custom-tools/skill-tools/tools/list/schema.d.ts +6 -0
  70. package/dist/custom-tools/skill-tools/tools/list/schema.js +19 -0
  71. package/dist/custom-tools/skill-tools/tools/read/index.d.ts +2 -0
  72. package/dist/custom-tools/skill-tools/tools/read/index.js +124 -0
  73. package/dist/custom-tools/skill-tools/tools/read/schema.d.ts +6 -0
  74. package/dist/custom-tools/skill-tools/tools/read/schema.js +27 -0
  75. package/dist/custom-tools/skill-tools/tools/search/bm25.d.ts +71 -0
  76. package/dist/custom-tools/skill-tools/tools/search/bm25.js +305 -0
  77. package/dist/custom-tools/skill-tools/tools/search/index.d.ts +8 -0
  78. package/dist/custom-tools/skill-tools/tools/search/index.js +63 -0
  79. package/dist/custom-tools/skill-tools/tools/search/schema.d.ts +6 -0
  80. package/dist/custom-tools/skill-tools/tools/search/schema.js +19 -0
  81. package/dist/custom-tools/skill-tools/tools/search/skill-index.d.ts +54 -0
  82. package/dist/custom-tools/skill-tools/tools/search/skill-index.js +251 -0
  83. package/dist/custom-tools/skill-tools/tools/update/index.d.ts +2 -0
  84. package/dist/custom-tools/skill-tools/tools/update/index.js +115 -0
  85. package/dist/custom-tools/skill-tools/tools/update/schema.d.ts +6 -0
  86. package/dist/custom-tools/skill-tools/tools/update/schema.js +41 -0
  87. package/dist/screens/ChatScreen.d.ts +1 -0
  88. package/dist/screens/ChatScreen.js +327 -0
  89. package/dist/screens/HomeScreen.d.ts +1 -0
  90. package/dist/screens/HomeScreen.js +68 -0
  91. package/dist/screens/SettingsScreen.d.ts +1 -0
  92. package/dist/screens/SettingsScreen.js +35 -0
  93. package/dist/services/db.d.ts +31 -0
  94. package/dist/services/db.js +108 -0
  95. package/dist/theme/ThemeContext.d.ts +11 -0
  96. package/dist/theme/ThemeContext.js +31 -0
  97. package/dist/theme/theme.d.ts +17 -0
  98. package/dist/theme/theme.js +82 -0
  99. package/package.json +101 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * xAI Adapter - Custom Provider Example
3
+ *
4
+ * Demonstrates how to create a custom provider adapter for the Toolpack SDK.
5
+ * xAI provides Grok models for fast, intelligent AI responses.
6
+ *
7
+ * API Docs: https://docs.x.ai/api
8
+ */
9
+ export class XAIAdapter {
10
+ constructor(config = {}) {
11
+ Object.defineProperty(this, "name", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: 'xai'
16
+ });
17
+ Object.defineProperty(this, "apiKey", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ Object.defineProperty(this, "baseUrl", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: void 0
28
+ });
29
+ Object.defineProperty(this, "defaultModel", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: void 0
34
+ });
35
+ // Resolve API key from config or environment (defer error to usage time)
36
+ this.apiKey =
37
+ config.apiKey ||
38
+ process.env['XAI_API_KEY'] ||
39
+ process.env['TOOLPACK_XAI_KEY'] ||
40
+ null;
41
+ this.baseUrl = config.baseUrl || 'https://api.x.ai/v1';
42
+ this.defaultModel = config.defaultModel || 'grok-3-latest';
43
+ }
44
+ getDisplayName() {
45
+ return 'xAI (Grok)';
46
+ }
47
+ async getModels() {
48
+ return [
49
+ {
50
+ id: 'grok-3-latest',
51
+ displayName: 'Grok 3 (Latest)',
52
+ capabilities: {
53
+ chat: true,
54
+ streaming: true,
55
+ toolCalling: true,
56
+ embeddings: false,
57
+ vision: false,
58
+ },
59
+ contextWindow: 131072,
60
+ },
61
+ {
62
+ id: 'grok-beta',
63
+ displayName: 'Grok Beta',
64
+ capabilities: {
65
+ chat: true,
66
+ streaming: true,
67
+ toolCalling: true,
68
+ embeddings: false,
69
+ vision: false,
70
+ },
71
+ contextWindow: 131072,
72
+ },
73
+ {
74
+ id: 'grok-vision-beta',
75
+ displayName: 'Grok Vision Beta',
76
+ capabilities: {
77
+ chat: true,
78
+ streaming: true,
79
+ toolCalling: true,
80
+ embeddings: false,
81
+ vision: true,
82
+ },
83
+ contextWindow: 8192,
84
+ },
85
+ ];
86
+ }
87
+ ensureApiKey() {
88
+ if (!this.apiKey) {
89
+ throw new Error('No API key found for xAI. Set XAI_API_KEY or TOOLPACK_XAI_KEY environment variable, ' +
90
+ 'or pass apiKey in config.');
91
+ }
92
+ return this.apiKey;
93
+ }
94
+ async generate(request) {
95
+ const apiKey = this.ensureApiKey();
96
+ const model = request.model || this.defaultModel;
97
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
98
+ method: 'POST',
99
+ headers: {
100
+ Authorization: `Bearer ${apiKey}`,
101
+ 'Content-Type': 'application/json',
102
+ },
103
+ body: JSON.stringify({
104
+ model,
105
+ messages: request.messages.map(m => ({
106
+ role: m.role,
107
+ content: m.content,
108
+ ...(m.tool_call_id ? { tool_call_id: m.tool_call_id } : {}),
109
+ ...(m.tool_calls ? { tool_calls: m.tool_calls } : {}),
110
+ })),
111
+ tools: request.tools?.map(t => ({
112
+ type: 'function',
113
+ function: {
114
+ name: t.function.name,
115
+ description: t.function.description,
116
+ parameters: t.function.parameters,
117
+ },
118
+ })),
119
+ tool_choice: request.tool_choice,
120
+ temperature: request.temperature ?? 0.7,
121
+ max_tokens: request.max_tokens ?? 4096,
122
+ top_p: request.top_p,
123
+ }),
124
+ });
125
+ if (!response.ok) {
126
+ const error = await response.text();
127
+ throw new Error(`xAI API error: ${response.status} - ${error}`);
128
+ }
129
+ const data = (await response.json());
130
+ const choice = data.choices[0];
131
+ // Extract tool calls if present
132
+ let toolCalls = undefined;
133
+ if (choice.message.tool_calls) {
134
+ toolCalls = choice.message.tool_calls.map((tc) => ({
135
+ id: tc.id,
136
+ name: tc.function.name,
137
+ arguments: typeof tc.function.arguments === 'string'
138
+ ? JSON.parse(tc.function.arguments)
139
+ : tc.function.arguments,
140
+ }));
141
+ }
142
+ return {
143
+ content: choice.message.content,
144
+ usage: data.usage
145
+ ? {
146
+ prompt_tokens: data.usage.prompt_tokens,
147
+ completion_tokens: data.usage.completion_tokens,
148
+ total_tokens: data.usage.total_tokens,
149
+ }
150
+ : undefined,
151
+ finish_reason: choice.finish_reason === 'tool_calls'
152
+ ? 'tool_calls'
153
+ : choice.finish_reason === 'length'
154
+ ? 'length'
155
+ : 'stop',
156
+ tool_calls: toolCalls,
157
+ raw: data,
158
+ };
159
+ }
160
+ async *stream(request) {
161
+ const apiKey = this.ensureApiKey();
162
+ const model = request.model || this.defaultModel;
163
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
164
+ method: 'POST',
165
+ headers: {
166
+ Authorization: `Bearer ${apiKey}`,
167
+ 'Content-Type': 'application/json',
168
+ },
169
+ body: JSON.stringify({
170
+ model,
171
+ messages: request.messages.map(m => ({
172
+ role: m.role,
173
+ content: m.content,
174
+ ...(m.tool_call_id ? { tool_call_id: m.tool_call_id } : {}),
175
+ ...(m.tool_calls ? { tool_calls: m.tool_calls } : {}),
176
+ })),
177
+ tools: request.tools?.map(t => ({
178
+ type: 'function',
179
+ function: {
180
+ name: t.function.name,
181
+ description: t.function.description,
182
+ parameters: t.function.parameters,
183
+ },
184
+ })),
185
+ tool_choice: request.tool_choice,
186
+ temperature: request.temperature ?? 0.7,
187
+ max_tokens: request.max_tokens ?? 4096,
188
+ stream: true,
189
+ }),
190
+ });
191
+ if (!response.ok) {
192
+ const error = await response.text();
193
+ throw new Error(`xAI API error: ${response.status} - ${error}`);
194
+ }
195
+ const reader = response.body.getReader();
196
+ const decoder = new TextDecoder();
197
+ let buffer = '';
198
+ // Accumulate tool calls across chunks
199
+ const toolCallsAccumulator = new Map();
200
+ while (true) {
201
+ const { done, value } = await reader.read();
202
+ if (done)
203
+ break;
204
+ buffer += decoder.decode(value, { stream: true });
205
+ const lines = buffer.split('\n');
206
+ buffer = lines.pop() || '';
207
+ for (const line of lines) {
208
+ if (!line.startsWith('data: '))
209
+ continue;
210
+ const data = line.slice(6).trim();
211
+ if (data === '[DONE]') {
212
+ // Emit accumulated tool calls if any
213
+ if (toolCallsAccumulator.size > 0) {
214
+ const toolCalls = Array.from(toolCallsAccumulator.values()).map(tc => ({
215
+ id: tc.id,
216
+ name: tc.name,
217
+ arguments: JSON.parse(tc.arguments || '{}'),
218
+ }));
219
+ yield {
220
+ delta: '',
221
+ finish_reason: 'tool_calls',
222
+ tool_calls: toolCalls,
223
+ };
224
+ }
225
+ return;
226
+ }
227
+ try {
228
+ const chunk = JSON.parse(data);
229
+ const delta = chunk.choices[0]?.delta;
230
+ const finishReason = chunk.choices[0]?.finish_reason;
231
+ // Handle text content
232
+ if (delta?.content) {
233
+ yield { delta: delta.content };
234
+ }
235
+ // Accumulate tool calls (they come in fragments)
236
+ if (delta?.tool_calls) {
237
+ for (const tc of delta.tool_calls) {
238
+ const idx = tc.index ?? 0;
239
+ if (!toolCallsAccumulator.has(idx)) {
240
+ toolCallsAccumulator.set(idx, {
241
+ id: '',
242
+ name: '',
243
+ arguments: '',
244
+ });
245
+ }
246
+ const acc = toolCallsAccumulator.get(idx);
247
+ if (tc.id)
248
+ acc.id = tc.id;
249
+ if (tc.function?.name)
250
+ acc.name = tc.function.name;
251
+ if (tc.function?.arguments)
252
+ acc.arguments += tc.function.arguments;
253
+ }
254
+ }
255
+ // Handle finish reasons
256
+ if (finishReason === 'stop') {
257
+ yield { delta: '', finish_reason: 'stop' };
258
+ }
259
+ else if (finishReason === 'tool_calls') {
260
+ const toolCalls = Array.from(toolCallsAccumulator.values()).map(tc => ({
261
+ id: tc.id,
262
+ name: tc.name,
263
+ arguments: JSON.parse(tc.arguments || '{}'),
264
+ }));
265
+ yield {
266
+ delta: '',
267
+ finish_reason: 'tool_calls',
268
+ tool_calls: toolCalls,
269
+ };
270
+ }
271
+ else if (finishReason === 'length') {
272
+ yield { delta: '', finish_reason: 'length' };
273
+ }
274
+ }
275
+ catch {
276
+ // Ignore parse errors from partial lines
277
+ }
278
+ }
279
+ }
280
+ }
281
+ async embed(_request) {
282
+ // xAI doesn't support embeddings - throw a clear error
283
+ throw new Error('xAI does not support embeddings. Use OpenAI or another provider for embeddings.');
284
+ }
285
+ // File upload is not supported by xAI
286
+ supportsFileUpload() {
287
+ return false;
288
+ }
289
+ async uploadFile(_request) {
290
+ throw new Error('xAI does not support file uploads.');
291
+ }
292
+ async deleteFile(_fileId) {
293
+ throw new Error('xAI does not support file operations.');
294
+ }
295
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Skill Tools Project
3
+ *
4
+ * Tools for managing SKILL.md files - structured documentation for AI agent
5
+ * skills, capabilities, and learned behaviors.
6
+ *
7
+ * Skills are stored in .skills/ directory and follow a structured markdown
8
+ * format with:
9
+ * - Frontmatter metadata (name, title, version, tags)
10
+ * - Description section
11
+ * - Triggers (phrases that activate the skill)
12
+ * - Instructions (how the AI should behave)
13
+ * - Examples (sample interactions)
14
+ *
15
+ * Structure:
16
+ * skill-tools/
17
+ * ├── toolproject.json
18
+ * ├── index.ts (this file)
19
+ * └── tools/
20
+ * ├── create/
21
+ * ├── read/
22
+ * ├── update/
23
+ * ├── list/
24
+ * └── search/ (BM25-powered skill search)
25
+ */
26
+ import { ToolProject } from 'toolpack-sdk';
27
+ export { skillCreateTool } from './tools/create/index.js';
28
+ export { skillReadTool } from './tools/read/index.js';
29
+ export { skillUpdateTool } from './tools/update/index.js';
30
+ export { skillListTool } from './tools/list/index.js';
31
+ export { skillSearchTool } from './tools/search/index.js';
32
+ export declare const skillToolsProject: ToolProject;
33
+ export default skillToolsProject;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Skill Tools Project
3
+ *
4
+ * Tools for managing SKILL.md files - structured documentation for AI agent
5
+ * skills, capabilities, and learned behaviors.
6
+ *
7
+ * Skills are stored in .skills/ directory and follow a structured markdown
8
+ * format with:
9
+ * - Frontmatter metadata (name, title, version, tags)
10
+ * - Description section
11
+ * - Triggers (phrases that activate the skill)
12
+ * - Instructions (how the AI should behave)
13
+ * - Examples (sample interactions)
14
+ *
15
+ * Structure:
16
+ * skill-tools/
17
+ * ├── toolproject.json
18
+ * ├── index.ts (this file)
19
+ * └── tools/
20
+ * ├── create/
21
+ * ├── read/
22
+ * ├── update/
23
+ * ├── list/
24
+ * └── search/ (BM25-powered skill search)
25
+ */
26
+ import { skillCreateTool } from './tools/create/index.js';
27
+ import { skillReadTool } from './tools/read/index.js';
28
+ import { skillUpdateTool } from './tools/update/index.js';
29
+ import { skillListTool } from './tools/list/index.js';
30
+ import { skillSearchTool } from './tools/search/index.js';
31
+ // Re-export individual tools for direct access
32
+ export { skillCreateTool } from './tools/create/index.js';
33
+ export { skillReadTool } from './tools/read/index.js';
34
+ export { skillUpdateTool } from './tools/update/index.js';
35
+ export { skillListTool } from './tools/list/index.js';
36
+ export { skillSearchTool } from './tools/search/index.js';
37
+ // Export the complete ToolProject
38
+ export const skillToolsProject = {
39
+ manifest: {
40
+ key: 'skill',
41
+ name: 'skill-tools',
42
+ displayName: 'Skill Tools',
43
+ version: '1.0.0',
44
+ description: 'Tools for managing SKILL.md files - structured documentation for AI agent skills, capabilities, and learned behaviors.',
45
+ author: 'Toolpack Team',
46
+ tools: [
47
+ 'skill.create',
48
+ 'skill.read',
49
+ 'skill.update',
50
+ 'skill.list',
51
+ 'skill.search',
52
+ ],
53
+ category: 'productivity',
54
+ },
55
+ tools: [
56
+ skillCreateTool,
57
+ skillReadTool,
58
+ skillUpdateTool,
59
+ skillListTool,
60
+ skillSearchTool,
61
+ ],
62
+ };
63
+ export default skillToolsProject;
@@ -0,0 +1,2 @@
1
+ import { ToolDefinition } from 'toolpack-sdk';
2
+ export declare const skillCreateTool: ToolDefinition;
@@ -0,0 +1,93 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { name, displayName, description, parameters, category, } from './schema.js';
4
+ const SKILLS_DIR = '.skills';
5
+ async function execute(args) {
6
+ const skillName = args['name'];
7
+ const title = args['title'];
8
+ const desc = args['description'];
9
+ const triggers = args['triggers'] || [];
10
+ const instructions = args['instructions'];
11
+ const examples = args['examples'] || [];
12
+ const tags = args['tags'] || [];
13
+ // Validate skill name (kebab-case)
14
+ if (!/^[a-z][a-z0-9-]*$/.test(skillName)) {
15
+ return JSON.stringify({
16
+ error: 'invalid_name',
17
+ message: 'Skill name must be kebab-case (lowercase letters, numbers, hyphens, starting with a letter)',
18
+ }, null, 2);
19
+ }
20
+ // Ensure .skills directory exists
21
+ const skillsDir = path.join(process.cwd(), SKILLS_DIR);
22
+ try {
23
+ await fs.mkdir(skillsDir, { recursive: true });
24
+ }
25
+ catch (e) {
26
+ // Directory might already exist
27
+ }
28
+ // Check if skill already exists
29
+ const skillPath = path.join(skillsDir, `${skillName}.skill.md`);
30
+ try {
31
+ await fs.access(skillPath);
32
+ return JSON.stringify({
33
+ error: 'skill_exists',
34
+ message: `Skill "${skillName}" already exists at ${skillPath}. Use skill.update to modify it.`,
35
+ }, null, 2);
36
+ }
37
+ catch {
38
+ // File doesn't exist, we can create it
39
+ }
40
+ // Generate SKILL.md content
41
+ const now = new Date().toISOString();
42
+ const content = `---
43
+ name: ${skillName}
44
+ title: ${title}
45
+ version: 1.0.0
46
+ created: ${now}
47
+ updated: ${now}
48
+ tags: [${tags.map(t => `"${t}"`).join(', ')}]
49
+ ---
50
+
51
+ # ${title}
52
+
53
+ ## Description
54
+
55
+ ${desc}
56
+
57
+ ## Triggers
58
+
59
+ ${triggers.length > 0
60
+ ? triggers.map(t => `- "${t}"`).join('\n')
61
+ : '_No specific triggers defined_'}
62
+
63
+ ## Instructions
64
+
65
+ ${instructions}
66
+
67
+ ## Examples
68
+
69
+ ${examples.length > 0
70
+ ? examples.map((ex, i) => `### Example ${i + 1}\n\n${ex}`).join('\n\n')
71
+ : '_No examples provided_'}
72
+
73
+ ## Usage Notes
74
+
75
+ _Add any additional notes about when and how to use this skill._
76
+ `;
77
+ // Write the skill file
78
+ await fs.writeFile(skillPath, content, 'utf-8');
79
+ return JSON.stringify({
80
+ success: true,
81
+ skill: skillName,
82
+ path: skillPath,
83
+ message: `Skill "${title}" created successfully`,
84
+ }, null, 2);
85
+ }
86
+ export const skillCreateTool = {
87
+ name,
88
+ displayName,
89
+ description,
90
+ parameters,
91
+ category,
92
+ execute,
93
+ };
@@ -0,0 +1,6 @@
1
+ import { ToolParameters } from 'toolpack-sdk';
2
+ export declare const name = "skill.create";
3
+ export declare const displayName = "Create Skill";
4
+ export declare const description = "Create a new SKILL.md file documenting an AI agent skill or capability. Skills are stored in .skills/ directory and follow a structured markdown format with metadata, description, examples, and usage guidelines.";
5
+ export declare const category = "productivity";
6
+ export declare const parameters: ToolParameters;
@@ -0,0 +1,41 @@
1
+ export const name = 'skill.create';
2
+ export const displayName = 'Create Skill';
3
+ export const description = 'Create a new SKILL.md file documenting an AI agent skill or capability. Skills are stored in .skills/ directory and follow a structured markdown format with metadata, description, examples, and usage guidelines.';
4
+ export const category = 'productivity';
5
+ export const parameters = {
6
+ type: 'object',
7
+ properties: {
8
+ name: {
9
+ type: 'string',
10
+ description: 'Unique skill name in kebab-case (e.g., "code-review", "data-analysis", "api-integration")',
11
+ },
12
+ title: {
13
+ type: 'string',
14
+ description: 'Human-readable title for the skill (e.g., "Code Review Assistant")',
15
+ },
16
+ description: {
17
+ type: 'string',
18
+ description: 'Brief description of what this skill enables the AI to do',
19
+ },
20
+ triggers: {
21
+ type: 'array',
22
+ description: 'List of phrases or keywords that should activate this skill',
23
+ items: { type: 'string' },
24
+ },
25
+ instructions: {
26
+ type: 'string',
27
+ description: 'Detailed instructions for how the AI should behave when using this skill',
28
+ },
29
+ examples: {
30
+ type: 'array',
31
+ description: 'Example prompts and expected behaviors',
32
+ items: { type: 'string' },
33
+ },
34
+ tags: {
35
+ type: 'array',
36
+ description: 'Tags for categorizing the skill (e.g., ["coding", "review", "quality"])',
37
+ items: { type: 'string' },
38
+ },
39
+ },
40
+ required: ['name', 'title', 'description', 'instructions'],
41
+ };
@@ -0,0 +1,2 @@
1
+ import { ToolDefinition } from 'toolpack-sdk';
2
+ export declare const skillListTool: ToolDefinition;
@@ -0,0 +1,113 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { name, displayName, description, parameters, category, } from './schema.js';
4
+ const SKILLS_DIR = '.skills';
5
+ async function execute(args) {
6
+ const filterTag = args['tag'];
7
+ const verbose = args['verbose'] || false;
8
+ const skillsDir = path.join(process.cwd(), SKILLS_DIR);
9
+ // Check if .skills directory exists
10
+ try {
11
+ await fs.access(skillsDir);
12
+ }
13
+ catch {
14
+ return JSON.stringify({
15
+ skills: [],
16
+ count: 0,
17
+ message: 'No .skills directory found. Use skill.create to create your first skill.',
18
+ }, null, 2);
19
+ }
20
+ // Read all .skill.md files
21
+ const files = await fs.readdir(skillsDir);
22
+ const skillFiles = files.filter(f => f.endsWith('.skill.md'));
23
+ if (skillFiles.length === 0) {
24
+ return JSON.stringify({
25
+ skills: [],
26
+ count: 0,
27
+ message: 'No skills found. Use skill.create to create your first skill.',
28
+ }, null, 2);
29
+ }
30
+ const skills = [];
31
+ for (const file of skillFiles) {
32
+ const filePath = path.join(skillsDir, file);
33
+ const content = await fs.readFile(filePath, 'utf-8');
34
+ // Parse frontmatter
35
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
36
+ let skillName = file.replace('.skill.md', '');
37
+ let title = skillName;
38
+ let tags = [];
39
+ if (frontmatterMatch && frontmatterMatch[1]) {
40
+ const lines = frontmatterMatch[1].split('\n');
41
+ for (const line of lines) {
42
+ if (line.startsWith('name:')) {
43
+ skillName = line.replace('name:', '').trim();
44
+ }
45
+ if (line.startsWith('title:')) {
46
+ title = line.replace('title:', '').trim();
47
+ }
48
+ if (line.startsWith('tags:')) {
49
+ const tagsMatch = line.match(/\[(.*)\]/);
50
+ if (tagsMatch && tagsMatch[1]) {
51
+ tags = tagsMatch[1]
52
+ .split(',')
53
+ .map(t => t.trim().replace(/"/g, ''))
54
+ .filter(Boolean);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ // Filter by tag if specified
60
+ if (filterTag && !tags.includes(filterTag)) {
61
+ continue;
62
+ }
63
+ skills.push({
64
+ name: skillName,
65
+ title,
66
+ tags,
67
+ path: filePath,
68
+ });
69
+ }
70
+ if (verbose) {
71
+ // Return full details for each skill
72
+ const detailedSkills = [];
73
+ for (const skill of skills) {
74
+ const content = await fs.readFile(skill.path, 'utf-8');
75
+ const descMatch = content.match(/## Description\n\n([\s\S]*?)(?=\n## |$)/);
76
+ const triggersMatch = content.match(/## Triggers\n\n([\s\S]*?)(?=\n## |$)/);
77
+ const triggers = [];
78
+ if (triggersMatch && triggersMatch[1]) {
79
+ const triggerLines = triggersMatch[1]
80
+ .split('\n')
81
+ .filter(l => l.startsWith('- '));
82
+ for (const line of triggerLines) {
83
+ const match = line.match(/- "(.*)"/);
84
+ if (match && match[1])
85
+ triggers.push(match[1]);
86
+ }
87
+ }
88
+ detailedSkills.push({
89
+ ...skill,
90
+ description: descMatch && descMatch[1] ? descMatch[1].trim() : '',
91
+ triggers,
92
+ });
93
+ }
94
+ return JSON.stringify({
95
+ skills: detailedSkills,
96
+ count: detailedSkills.length,
97
+ filtered: filterTag ? `by tag: ${filterTag}` : null,
98
+ }, null, 2);
99
+ }
100
+ return JSON.stringify({
101
+ skills: skills.map(s => ({ name: s.name, title: s.title, tags: s.tags })),
102
+ count: skills.length,
103
+ filtered: filterTag ? `by tag: ${filterTag}` : null,
104
+ }, null, 2);
105
+ }
106
+ export const skillListTool = {
107
+ name,
108
+ displayName,
109
+ description,
110
+ parameters,
111
+ category,
112
+ execute,
113
+ };
@@ -0,0 +1,6 @@
1
+ import { ToolParameters } from 'toolpack-sdk';
2
+ export declare const name = "skill.list";
3
+ export declare const displayName = "List Skills";
4
+ export declare const description = "List all available SKILL.md files in the .skills directory with their metadata.";
5
+ export declare const category = "productivity";
6
+ export declare const parameters: ToolParameters;
@@ -0,0 +1,19 @@
1
+ export const name = 'skill.list';
2
+ export const displayName = 'List Skills';
3
+ export const description = 'List all available SKILL.md files in the .skills directory with their metadata.';
4
+ export const category = 'productivity';
5
+ export const parameters = {
6
+ type: 'object',
7
+ properties: {
8
+ tag: {
9
+ type: 'string',
10
+ description: 'Optional: filter skills by tag',
11
+ },
12
+ verbose: {
13
+ type: 'boolean',
14
+ description: 'Include full metadata for each skill. Default: false',
15
+ default: false,
16
+ },
17
+ },
18
+ required: [],
19
+ };
@@ -0,0 +1,2 @@
1
+ import { ToolDefinition } from 'toolpack-sdk';
2
+ export declare const skillReadTool: ToolDefinition;