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,251 @@
1
+ /**
2
+ * Skill Index Manager
3
+ *
4
+ * Manages the BM25 index for skill files, handling indexing, caching,
5
+ * and automatic re-indexing when skills change.
6
+ */
7
+ import * as fs from 'fs/promises';
8
+ import * as path from 'path';
9
+ import { BM25Index } from './bm25.js';
10
+ const SKILLS_DIR = '.skills';
11
+ class SkillIndexManager {
12
+ constructor() {
13
+ Object.defineProperty(this, "index", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: void 0
18
+ });
19
+ Object.defineProperty(this, "skillCache", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: new Map()
24
+ });
25
+ Object.defineProperty(this, "lastIndexTime", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: 0
30
+ });
31
+ Object.defineProperty(this, "indexedDir", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: ''
36
+ });
37
+ this.index = new BM25Index({ k1: 1.5, b: 0.75 });
38
+ }
39
+ /**
40
+ * Parse a skill file and extract all searchable content
41
+ */
42
+ parseSkillFile(content, filePath) {
43
+ const skill = {
44
+ name: '',
45
+ title: '',
46
+ description: '',
47
+ tags: [],
48
+ triggers: [],
49
+ keywords: [],
50
+ path: filePath,
51
+ lastModified: Date.now(),
52
+ };
53
+ // Parse frontmatter
54
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
55
+ if (frontmatterMatch && frontmatterMatch[1]) {
56
+ const lines = frontmatterMatch[1].split('\n');
57
+ for (const line of lines) {
58
+ const colonIndex = line.indexOf(':');
59
+ if (colonIndex === -1)
60
+ continue;
61
+ const key = line.substring(0, colonIndex).trim();
62
+ const value = line.substring(colonIndex + 1).trim();
63
+ if (key === 'name')
64
+ skill.name = value;
65
+ if (key === 'title')
66
+ skill.title = value;
67
+ if (key === 'tags') {
68
+ const tagsMatch = value.match(/\[(.*)\]/);
69
+ if (tagsMatch && tagsMatch[1]) {
70
+ skill.tags = tagsMatch[1]
71
+ .split(',')
72
+ .map(t => t.trim().replace(/"/g, ''))
73
+ .filter(Boolean);
74
+ }
75
+ }
76
+ if (key === 'keywords') {
77
+ const keywordsMatch = value.match(/\[(.*)\]/);
78
+ if (keywordsMatch && keywordsMatch[1]) {
79
+ skill.keywords = keywordsMatch[1]
80
+ .split(',')
81
+ .map(k => k.trim().replace(/"/g, ''))
82
+ .filter(Boolean);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ // Parse description section
88
+ const descMatch = content.match(/## Description\n\n([\s\S]*?)(?=\n## |$)/);
89
+ if (descMatch && descMatch[1]) {
90
+ skill.description = descMatch[1].trim();
91
+ }
92
+ // Parse triggers section
93
+ const triggersMatch = content.match(/## Triggers\n\n([\s\S]*?)(?=\n## |$)/);
94
+ if (triggersMatch && triggersMatch[1]) {
95
+ const triggerLines = triggersMatch[1]
96
+ .split('\n')
97
+ .filter(l => l.startsWith('- '));
98
+ for (const line of triggerLines) {
99
+ const match = line.match(/- "(.*)"/);
100
+ if (match && match[1]) {
101
+ skill.triggers.push(match[1]);
102
+ }
103
+ }
104
+ }
105
+ // If no name from frontmatter, derive from filename
106
+ if (!skill.name) {
107
+ skill.name = path.basename(filePath, '.skill.md');
108
+ }
109
+ if (!skill.title) {
110
+ skill.title = skill.name;
111
+ }
112
+ return skill;
113
+ }
114
+ /**
115
+ * Build searchable content for BM25 indexing
116
+ * Weights different fields by repeating important terms
117
+ */
118
+ buildSearchableContent(skill) {
119
+ const parts = [];
120
+ // Name and title are highly weighted (repeat 3x)
121
+ parts.push(skill.name, skill.name, skill.name);
122
+ parts.push(skill.title, skill.title, skill.title);
123
+ // Tags and keywords are weighted (repeat 2x)
124
+ for (const tag of skill.tags) {
125
+ parts.push(tag, tag);
126
+ }
127
+ for (const keyword of skill.keywords) {
128
+ parts.push(keyword, keyword);
129
+ }
130
+ // Triggers are weighted (repeat 2x)
131
+ for (const trigger of skill.triggers) {
132
+ parts.push(trigger, trigger);
133
+ }
134
+ // Description is included once
135
+ parts.push(skill.description);
136
+ return parts.join(' ');
137
+ }
138
+ /**
139
+ * Index all skills in the .skills directory
140
+ */
141
+ async indexSkills(workspaceRoot) {
142
+ const cwd = workspaceRoot || process.cwd();
143
+ const skillsDir = path.join(cwd, SKILLS_DIR);
144
+ // Check if .skills directory exists
145
+ try {
146
+ await fs.access(skillsDir);
147
+ }
148
+ catch {
149
+ this.index.clear();
150
+ this.skillCache.clear();
151
+ return 0;
152
+ }
153
+ // Check if we need to re-index
154
+ const dirStat = await fs.stat(skillsDir);
155
+ if (this.indexedDir === skillsDir &&
156
+ dirStat.mtimeMs <= this.lastIndexTime) {
157
+ // Directory hasn't changed, check individual files
158
+ let needsReindex = false;
159
+ const files = await fs.readdir(skillsDir);
160
+ for (const file of files) {
161
+ if (!file.endsWith('.skill.md'))
162
+ continue;
163
+ const filePath = path.join(skillsDir, file);
164
+ const fileStat = await fs.stat(filePath);
165
+ const cached = this.skillCache.get(file);
166
+ if (!cached || fileStat.mtimeMs > cached.lastModified) {
167
+ needsReindex = true;
168
+ break;
169
+ }
170
+ }
171
+ if (!needsReindex) {
172
+ return this.index.size;
173
+ }
174
+ }
175
+ // Clear and rebuild index
176
+ this.index.clear();
177
+ this.skillCache.clear();
178
+ const files = await fs.readdir(skillsDir);
179
+ const skillFiles = files.filter(f => f.endsWith('.skill.md'));
180
+ for (const file of skillFiles) {
181
+ const filePath = path.join(skillsDir, file);
182
+ const content = await fs.readFile(filePath, 'utf-8');
183
+ const fileStat = await fs.stat(filePath);
184
+ const skill = this.parseSkillFile(content, filePath);
185
+ skill.lastModified = fileStat.mtimeMs;
186
+ // Add to cache
187
+ this.skillCache.set(file, skill);
188
+ // Add to BM25 index
189
+ this.index.addDocument({
190
+ id: skill.name,
191
+ content: this.buildSearchableContent(skill),
192
+ fields: {
193
+ name: skill.name,
194
+ title: skill.title,
195
+ description: skill.description,
196
+ tags: skill.tags,
197
+ triggers: skill.triggers,
198
+ keywords: skill.keywords,
199
+ },
200
+ });
201
+ }
202
+ this.lastIndexTime = Date.now();
203
+ this.indexedDir = skillsDir;
204
+ return this.index.size;
205
+ }
206
+ /**
207
+ * Search for skills matching the query
208
+ */
209
+ async search(query, limit = 5, workspaceRoot) {
210
+ // Ensure index is up to date
211
+ await this.indexSkills(workspaceRoot);
212
+ if (this.index.size === 0) {
213
+ return [];
214
+ }
215
+ const results = this.index.search(query, limit);
216
+ // Enrich results with full skill data
217
+ return results.map(result => {
218
+ const skillFile = `${result.id}.skill.md`;
219
+ const skill = this.skillCache.get(skillFile) || {
220
+ name: result.id,
221
+ title: result.fields['title'] || result.id,
222
+ description: result.fields['description'] || '',
223
+ tags: result.fields['tags'] || [],
224
+ triggers: result.fields['triggers'] || [],
225
+ keywords: result.fields['keywords'] || [],
226
+ path: '',
227
+ lastModified: 0,
228
+ };
229
+ return {
230
+ ...result,
231
+ skill,
232
+ };
233
+ });
234
+ }
235
+ /**
236
+ * Get the number of indexed skills
237
+ */
238
+ get size() {
239
+ return this.index.size;
240
+ }
241
+ /**
242
+ * Force a full re-index
243
+ */
244
+ async reindex(workspaceRoot) {
245
+ this.lastIndexTime = 0;
246
+ this.indexedDir = '';
247
+ return this.indexSkills(workspaceRoot);
248
+ }
249
+ }
250
+ // Singleton instance for the skill index
251
+ export const skillIndex = new SkillIndexManager();
@@ -0,0 +1,2 @@
1
+ import { ToolDefinition } from 'toolpack-sdk';
2
+ export declare const skillUpdateTool: ToolDefinition;
@@ -0,0 +1,115 @@
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 newTitle = args['title'];
8
+ const newDescription = args['description'];
9
+ const newTriggers = args['triggers'];
10
+ const newInstructions = args['instructions'];
11
+ const addExamples = args['addExamples'];
12
+ const addTags = args['addTags'];
13
+ const skillPath = path.join(process.cwd(), SKILLS_DIR, `${skillName}.skill.md`);
14
+ // Check if skill exists
15
+ let content;
16
+ try {
17
+ content = await fs.readFile(skillPath, 'utf-8');
18
+ }
19
+ catch {
20
+ return JSON.stringify({
21
+ error: 'skill_not_found',
22
+ message: `Skill "${skillName}" not found. Use skill.create to create it first.`,
23
+ }, null, 2);
24
+ }
25
+ // Parse existing frontmatter
26
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
27
+ let existingTags = [];
28
+ let existingTitle = '';
29
+ if (frontmatterMatch && frontmatterMatch[1]) {
30
+ const lines = frontmatterMatch[1].split('\n');
31
+ for (const line of lines) {
32
+ if (line.startsWith('title:')) {
33
+ existingTitle = line.replace('title:', '').trim();
34
+ }
35
+ if (line.startsWith('tags:')) {
36
+ const tagsMatch = line.match(/\[(.*)\]/);
37
+ if (tagsMatch && tagsMatch[1]) {
38
+ existingTags = tagsMatch[1]
39
+ .split(',')
40
+ .map(t => t.trim().replace(/"/g, ''))
41
+ .filter(Boolean);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ // Update frontmatter
47
+ const now = new Date().toISOString();
48
+ const finalTitle = newTitle || existingTitle;
49
+ const finalTags = addTags
50
+ ? [...new Set([...existingTags, ...addTags])]
51
+ : existingTags;
52
+ // Update sections
53
+ if (newDescription) {
54
+ content = content.replace(/## Description\n\n[\s\S]*?(?=\n## )/, `## Description\n\n${newDescription}\n\n`);
55
+ }
56
+ if (newTriggers) {
57
+ const triggersContent = newTriggers.map(t => `- "${t}"`).join('\n');
58
+ content = content.replace(/## Triggers\n\n[\s\S]*?(?=\n## )/, `## Triggers\n\n${triggersContent}\n\n`);
59
+ }
60
+ if (newInstructions) {
61
+ content = content.replace(/## Instructions\n\n[\s\S]*?(?=\n## )/, `## Instructions\n\n${newInstructions}\n\n`);
62
+ }
63
+ if (addExamples && addExamples.length > 0) {
64
+ // Find existing examples section and append
65
+ const examplesMatch = content.match(/## Examples\n\n([\s\S]*?)(?=\n## |$)/);
66
+ if (examplesMatch) {
67
+ const existingExamples = examplesMatch[1] || '';
68
+ const existingCount = (existingExamples.match(/### Example \d+/g) || [])
69
+ .length;
70
+ const newExamplesContent = addExamples
71
+ .map((ex, i) => `### Example ${existingCount + i + 1}\n\n${ex}`)
72
+ .join('\n\n');
73
+ content = content.replace(/## Examples\n\n[\s\S]*?(?=\n## |$)/, `## Examples\n\n${existingExamples}\n\n${newExamplesContent}\n\n`);
74
+ }
75
+ }
76
+ // Update frontmatter with new values
77
+ content = content.replace(/^---\n[\s\S]*?\n---/, `---
78
+ name: ${skillName}
79
+ title: ${finalTitle}
80
+ version: 1.0.0
81
+ created: ${content.match(/created: (.*)/)?.[1] || now}
82
+ updated: ${now}
83
+ tags: [${finalTags.map(t => `"${t}"`).join(', ')}]
84
+ ---`);
85
+ // Write updated content
86
+ await fs.writeFile(skillPath, content, 'utf-8');
87
+ const updates = [];
88
+ if (newTitle)
89
+ updates.push('title');
90
+ if (newDescription)
91
+ updates.push('description');
92
+ if (newTriggers)
93
+ updates.push('triggers');
94
+ if (newInstructions)
95
+ updates.push('instructions');
96
+ if (addExamples)
97
+ updates.push(`${addExamples.length} examples`);
98
+ if (addTags)
99
+ updates.push(`${addTags.length} tags`);
100
+ return JSON.stringify({
101
+ success: true,
102
+ skill: skillName,
103
+ path: skillPath,
104
+ updated: updates,
105
+ message: `Skill "${skillName}" updated successfully`,
106
+ }, null, 2);
107
+ }
108
+ export const skillUpdateTool = {
109
+ name,
110
+ displayName,
111
+ description,
112
+ parameters,
113
+ category,
114
+ execute,
115
+ };
@@ -0,0 +1,6 @@
1
+ import { ToolParameters } from 'toolpack-sdk';
2
+ export declare const name = "skill.update";
3
+ export declare const displayName = "Update Skill";
4
+ export declare const description = "Update an existing SKILL.md file. Can update specific sections like description, triggers, instructions, or examples.";
5
+ export declare const category = "productivity";
6
+ export declare const parameters: ToolParameters;
@@ -0,0 +1,41 @@
1
+ export const name = 'skill.update';
2
+ export const displayName = 'Update Skill';
3
+ export const description = 'Update an existing SKILL.md file. Can update specific sections like description, triggers, instructions, or examples.';
4
+ export const category = 'productivity';
5
+ export const parameters = {
6
+ type: 'object',
7
+ properties: {
8
+ name: {
9
+ type: 'string',
10
+ description: 'The skill name to update (e.g., "code-review")',
11
+ },
12
+ title: {
13
+ type: 'string',
14
+ description: 'New title for the skill (optional)',
15
+ },
16
+ description: {
17
+ type: 'string',
18
+ description: 'New description (optional)',
19
+ },
20
+ triggers: {
21
+ type: 'array',
22
+ description: 'New list of triggers (replaces existing)',
23
+ items: { type: 'string' },
24
+ },
25
+ instructions: {
26
+ type: 'string',
27
+ description: 'New instructions (optional)',
28
+ },
29
+ addExamples: {
30
+ type: 'array',
31
+ description: 'Examples to add to existing examples',
32
+ items: { type: 'string' },
33
+ },
34
+ addTags: {
35
+ type: 'array',
36
+ description: 'Tags to add to existing tags',
37
+ items: { type: 'string' },
38
+ },
39
+ },
40
+ required: ['name'],
41
+ };
@@ -0,0 +1 @@
1
+ export declare function ChatScreen(): import("react/jsx-runtime").JSX.Element;