@magic-ingredients/tiny-brain-local 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/core/mcp-server.d.ts.map +1 -1
  2. package/dist/core/mcp-server.js +12 -8
  3. package/dist/core/repo-registration.d.ts +30 -0
  4. package/dist/core/repo-registration.d.ts.map +1 -0
  5. package/dist/core/repo-registration.js +34 -0
  6. package/dist/prompts/persona/persona.prompt.js +1 -1
  7. package/dist/prompts/planning/planning.prompt.d.ts +0 -8
  8. package/dist/prompts/planning/planning.prompt.d.ts.map +1 -1
  9. package/dist/prompts/planning/planning.prompt.js +0 -193
  10. package/dist/prompts/prompt-registry.d.ts.map +1 -1
  11. package/dist/prompts/prompt-registry.js +0 -2
  12. package/dist/services/analyse-service.d.ts +15 -29
  13. package/dist/services/analyse-service.d.ts.map +1 -1
  14. package/dist/services/analyse-service.js +99 -236
  15. package/dist/services/dashboard-launcher.service.d.ts +1 -0
  16. package/dist/services/dashboard-launcher.service.d.ts.map +1 -1
  17. package/dist/services/dashboard-launcher.service.js +4 -0
  18. package/dist/services/repo-service.d.ts +5 -0
  19. package/dist/services/repo-service.d.ts.map +1 -1
  20. package/dist/services/repo-service.js +67 -42
  21. package/dist/storage/local-filesystem-adapter.d.ts.map +1 -1
  22. package/dist/storage/local-filesystem-adapter.js +0 -3
  23. package/dist/tools/dashboard/dashboard.tool.d.ts +15 -0
  24. package/dist/tools/dashboard/dashboard.tool.d.ts.map +1 -0
  25. package/dist/tools/dashboard/dashboard.tool.js +81 -0
  26. package/dist/tools/plan/plan.tool.d.ts +0 -1
  27. package/dist/tools/plan/plan.tool.d.ts.map +1 -1
  28. package/dist/tools/plan/plan.tool.js +10 -56
  29. package/dist/tools/quality/quality.tool.js +1 -1
  30. package/dist/tools/recommendations/recommendations.tool.d.ts +13 -0
  31. package/dist/tools/recommendations/recommendations.tool.d.ts.map +1 -0
  32. package/dist/tools/recommendations/recommendations.tool.js +178 -0
  33. package/dist/tools/tool-registry.d.ts.map +1 -1
  34. package/dist/tools/tool-registry.js +8 -0
  35. package/dist/types/local-context.d.ts +2 -0
  36. package/dist/types/local-context.d.ts.map +1 -1
  37. package/package.json +4 -10
@@ -0,0 +1,178 @@
1
+ import { z } from 'zod';
2
+ import { createSuccessResult, createErrorResult } from '../index.js';
3
+ import { RecommendationService } from '@magic-ingredients/tiny-brain-core';
4
+ const RecommendationsArgsSchema = z.object({
5
+ operation: z.enum(['list', 'accept', 'dismiss', 'restore', 'graduated']),
6
+ items: z.array(z.string()).optional(),
7
+ });
8
+ export class RecommendationsTool {
9
+ static getToolDefinition() {
10
+ return {
11
+ name: 'recommendations',
12
+ description: `Manage skill, agent, and hook recommendations for your repository.
13
+
14
+ Operations:
15
+ - list: Show pending recommendations grouped by type
16
+ - accept: Accept recommendations by name (installs them)
17
+ - dismiss: Dismiss recommendations by name
18
+ - restore: Restore previously dismissed recommendations
19
+ - graduated: Show all accepted/installed recommendations with provenance`,
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ operation: {
24
+ type: 'string',
25
+ enum: ['list', 'accept', 'dismiss', 'restore', 'graduated'],
26
+ description: 'The recommendations operation to perform',
27
+ },
28
+ items: {
29
+ type: 'array',
30
+ items: { type: 'string' },
31
+ description: 'Recommendation names (required for accept, dismiss, restore)',
32
+ },
33
+ },
34
+ required: ['operation'],
35
+ },
36
+ };
37
+ }
38
+ static async execute(args, context) {
39
+ try {
40
+ const validatedArgs = RecommendationsArgsSchema.parse(args);
41
+ if (!context.repositoryRoot) {
42
+ return createErrorResult('Repository root is required for recommendations');
43
+ }
44
+ const service = new RecommendationService(context.repositoryRoot);
45
+ switch (validatedArgs.operation) {
46
+ case 'list':
47
+ return await RecommendationsTool.handleList(service);
48
+ case 'accept':
49
+ return await RecommendationsTool.handleAccept(validatedArgs, service);
50
+ case 'dismiss':
51
+ return await RecommendationsTool.handleDismiss(validatedArgs, service);
52
+ case 'restore':
53
+ return await RecommendationsTool.handleRestore(validatedArgs, service);
54
+ case 'graduated':
55
+ return await RecommendationsTool.handleGraduated(service);
56
+ default:
57
+ return createErrorResult(`Unknown operation: ${validatedArgs.operation}`);
58
+ }
59
+ }
60
+ catch (error) {
61
+ if (error instanceof z.ZodError) {
62
+ return createErrorResult(`Invalid arguments: ${error.errors.map((e) => e.message).join(', ')}`);
63
+ }
64
+ return createErrorResult(error instanceof Error ? error.message : 'Unknown error occurred');
65
+ }
66
+ }
67
+ static async handleList(service) {
68
+ const pending = await service.getPendingRecommendations();
69
+ if (pending.length === 0) {
70
+ return createSuccessResult('No pending recommendations. Run `analyse` to fetch new recommendations.');
71
+ }
72
+ const grouped = {};
73
+ for (const rec of pending) {
74
+ const typeLabel = rec.type === 'skill' ? 'Skills' : rec.type === 'agent' ? 'Agents' : 'Hooks';
75
+ if (!grouped[typeLabel]) {
76
+ grouped[typeLabel] = [];
77
+ }
78
+ grouped[typeLabel].push(rec);
79
+ }
80
+ const lines = ['# Pending Recommendations', ''];
81
+ for (const [type, recs] of Object.entries(grouped)) {
82
+ lines.push(`## ${type}`, '');
83
+ for (const rec of recs) {
84
+ lines.push(`- **${rec.name}**: ${rec.description}`);
85
+ lines.push(` _Reason: ${rec.reason}_`);
86
+ }
87
+ lines.push('');
88
+ }
89
+ lines.push('---', '', 'Use `accept` with item names to install recommendations.');
90
+ return createSuccessResult(lines.join('\n'));
91
+ }
92
+ static async handleAccept(args, service) {
93
+ if (!args.items || args.items.length === 0) {
94
+ return createErrorResult('`items` is required for accept operation');
95
+ }
96
+ const recsFile = await service.readRecommendations();
97
+ if (!recsFile) {
98
+ return createErrorResult('No recommendations file found. Run `analyse` first.');
99
+ }
100
+ const results = ['# Accept Results', ''];
101
+ for (const name of args.items) {
102
+ const match = recsFile.recommendations.find((r) => r.name.toLowerCase() === name.toLowerCase());
103
+ if (!match) {
104
+ results.push(`- **${name}**: Not found (unrecognized name)`);
105
+ continue;
106
+ }
107
+ try {
108
+ await service.acceptRecommendation(match);
109
+ results.push(`- **${match.name}**: Accepted`);
110
+ }
111
+ catch (error) {
112
+ const msg = error instanceof Error ? error.message : 'Unknown error';
113
+ results.push(`- **${match.name}**: Failed - ${msg}`);
114
+ }
115
+ }
116
+ return createSuccessResult(results.join('\n'));
117
+ }
118
+ static async handleDismiss(args, service) {
119
+ if (!args.items || args.items.length === 0) {
120
+ return createErrorResult('`items` is required for dismiss operation');
121
+ }
122
+ const recsFile = await service.readRecommendations();
123
+ if (!recsFile) {
124
+ return createErrorResult('No recommendations file found. Run `analyse` first.');
125
+ }
126
+ const results = ['# Dismiss Results', ''];
127
+ for (const name of args.items) {
128
+ const match = recsFile.recommendations.find((r) => r.name.toLowerCase() === name.toLowerCase());
129
+ if (!match) {
130
+ results.push(`- **${name}**: Not found (unrecognized name)`);
131
+ continue;
132
+ }
133
+ await service.dismissRecommendation(match.id);
134
+ results.push(`- **${match.name}**: Dismissed`);
135
+ }
136
+ return createSuccessResult(results.join('\n'));
137
+ }
138
+ static async handleRestore(args, service) {
139
+ if (!args.items || args.items.length === 0) {
140
+ return createErrorResult('`items` is required for restore operation');
141
+ }
142
+ const recsFile = await service.readRecommendations();
143
+ if (!recsFile) {
144
+ return createErrorResult('No recommendations file found. Run `analyse` first.');
145
+ }
146
+ const dismissed = await service.readDismissedRecommendations();
147
+ const dismissedIds = new Set(dismissed.map((d) => d.recommendationId));
148
+ const results = ['# Restore Results', ''];
149
+ for (const name of args.items) {
150
+ const match = recsFile.recommendations.find((r) => r.name.toLowerCase() === name.toLowerCase());
151
+ if (!match) {
152
+ results.push(`- **${name}**: Not found (unrecognized name)`);
153
+ continue;
154
+ }
155
+ if (!dismissedIds.has(match.id)) {
156
+ results.push(`- **${match.name}**: Not dismissed (nothing to restore)`);
157
+ continue;
158
+ }
159
+ await service.restoreRecommendation(match.id);
160
+ results.push(`- **${match.name}**: Restored`);
161
+ }
162
+ return createSuccessResult(results.join('\n'));
163
+ }
164
+ static async handleGraduated(service) {
165
+ const installed = await service.readInstalledRecommendations();
166
+ if (installed.length === 0) {
167
+ return createSuccessResult('No graduated recommendations yet. Use `accept` to install recommendations.');
168
+ }
169
+ const lines = ['# Graduated Recommendations', ''];
170
+ for (const item of installed) {
171
+ const { origin } = item;
172
+ lines.push(`- **${origin.recommendationName}** (${origin.type})`);
173
+ lines.push(` Source: ${origin.source}`);
174
+ lines.push(` Accepted: ${origin.acceptedAt}`);
175
+ }
176
+ return createSuccessResult(lines.join('\n'));
177
+ }
178
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../src/tools/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,OAAO,KAAK,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,qBAAa,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,QAAQ,IAAI,OAAO,EAAE;IAoC5B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CAmB9D;AAGD,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,8BAAqC,CAAC;AAChF,eAAO,MAAM,eAAe,gBAAyD,CAAC"}
1
+ {"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../src/tools/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,OAAO,KAAK,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,qBAAa,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,QAAQ,IAAI,OAAO,EAAE;IA0C5B;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CAqB9D;AAGD,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,8BAAqC,CAAC;AAChF,eAAO,MAAM,eAAe,gBAAyD,CAAC"}
@@ -15,6 +15,8 @@ import { StrategyTool } from './strategy/strategy.tool.js';
15
15
  import { AnalyseTool } from './analyse.tool.js';
16
16
  import { QualityTool } from './quality/quality.tool.js';
17
17
  import { ConfigTool } from './config/config.tool.js';
18
+ import { DashboardTool } from './dashboard/dashboard.tool.js';
19
+ import { RecommendationsTool } from './recommendations/recommendations.tool.js';
18
20
  export class ToolRegistry {
19
21
  /**
20
22
  * Get all available tool definitions from all tools
@@ -36,6 +38,10 @@ export class ToolRegistry {
36
38
  QualityTool.getToolDefinition(),
37
39
  // Config tool - manages preferences with reactive agent sync
38
40
  ConfigTool.getToolDefinition(),
41
+ // Dashboard tool - restart dashboard server (dev maintenance)
42
+ DashboardTool.getToolDefinition(),
43
+ // Recommendations tool - browse, accept, dismiss recommendations
44
+ RecommendationsTool.getToolDefinition(),
39
45
  // Response tools (disabled for later release)
40
46
  // AnalyseRequestTool.getToolDefinition(),
41
47
  // ValidateResponseTool.getToolDefinition(),
@@ -63,6 +69,8 @@ export class ToolRegistry {
63
69
  update: UpdateTool,
64
70
  quality: QualityTool,
65
71
  config: ConfigTool,
72
+ dev_restart_dashboard: DashboardTool,
73
+ recommendations: RecommendationsTool,
66
74
  };
67
75
  return toolMap[name];
68
76
  }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import type { RequestContext } from '@magic-ingredients/tiny-brain-core';
7
7
  import type { AuthToken } from '../services/remote/auth-token-service.js';
8
+ import type { DashboardLauncher } from '../services/dashboard-launcher.service.js';
8
9
  export interface LocalRequestContext extends RequestContext {
9
10
  authToken?: AuthToken;
10
11
  config?: {
@@ -13,5 +14,6 @@ export interface LocalRequestContext extends RequestContext {
13
14
  clientSecret?: string;
14
15
  };
15
16
  };
17
+ dashboardLauncher?: DashboardLauncher;
16
18
  }
17
19
  //# sourceMappingURL=local-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-context.d.ts","sourceRoot":"","sources":["../../src/types/local-context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0CAA0C,CAAC;AAE1E,MAAM,WAAW,mBAAoB,SAAQ,cAAc;IAEzD,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE;YACR,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC;KACH,CAAC;CACH"}
1
+ {"version":3,"file":"local-context.d.ts","sourceRoot":"","sources":["../../src/types/local-context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAEnF,MAAM,WAAW,mBAAoB,SAAQ,cAAc;IAEzD,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE;YACR,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC;KACH,CAAC;IAGF,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magic-ingredients/tiny-brain-local",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "MCP server for Tiny Brain AI assistant",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "dev": "tsx src/index.ts",
22
22
  "test": "vitest run",
23
23
  "test:coverage": "vitest run --coverage",
24
- "lint": "eslint src",
24
+ "lint": "eslint --cache src",
25
25
  "typecheck": "tsc --noEmit",
26
26
  "prepublishOnly": "npm run build",
27
27
  "dxt:clean": "rm -rf dxt/node_modules dxt/package-lock.json dxt/dist dxt/server/index.js",
@@ -31,7 +31,7 @@
31
31
  "dxt:init": "cd dxt && dxt init"
32
32
  },
33
33
  "dependencies": {
34
- "@magic-ingredients/tiny-brain-core": "^0.20.0",
34
+ "@magic-ingredients/tiny-brain-core": "^0.21.0",
35
35
  "@magic-ingredients/tiny-brain-dashboard": "file:../tiny-brain-dashboard",
36
36
  "@modelcontextprotocol/sdk": "^1.0.6",
37
37
  "chalk": "^5.3.0",
@@ -42,13 +42,7 @@
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/minimatch": "^5.1.2",
45
- "@types/node": "^20.14.2",
46
- "@types/semver": "^7.7.1",
47
- "@vitest/coverage-v8": "^2.1.8",
48
- "eslint": "^8.57.0",
49
- "tsx": "^4.19.2",
50
- "typescript": "^5.4.5",
51
- "vitest": "^2.1.8"
45
+ "@types/semver": "^7.7.1"
52
46
  },
53
47
  "engines": {
54
48
  "node": ">=18.0.0"