tlc-claude-code 1.4.4 → 1.4.6

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 (72) hide show
  1. package/dashboard/dist/App.js +28 -2
  2. package/dashboard/dist/api/health-diagnostics.d.ts +26 -0
  3. package/dashboard/dist/api/health-diagnostics.js +85 -0
  4. package/dashboard/dist/api/health-diagnostics.test.d.ts +1 -0
  5. package/dashboard/dist/api/health-diagnostics.test.js +126 -0
  6. package/dashboard/dist/api/index.d.ts +5 -0
  7. package/dashboard/dist/api/index.js +5 -0
  8. package/dashboard/dist/api/notes-api.d.ts +18 -0
  9. package/dashboard/dist/api/notes-api.js +68 -0
  10. package/dashboard/dist/api/notes-api.test.d.ts +1 -0
  11. package/dashboard/dist/api/notes-api.test.js +113 -0
  12. package/dashboard/dist/api/safeFetch.d.ts +50 -0
  13. package/dashboard/dist/api/safeFetch.js +135 -0
  14. package/dashboard/dist/api/safeFetch.test.d.ts +1 -0
  15. package/dashboard/dist/api/safeFetch.test.js +215 -0
  16. package/dashboard/dist/api/tasks-api.d.ts +32 -0
  17. package/dashboard/dist/api/tasks-api.js +98 -0
  18. package/dashboard/dist/api/tasks-api.test.d.ts +1 -0
  19. package/dashboard/dist/api/tasks-api.test.js +383 -0
  20. package/dashboard/dist/components/BugsPane.d.ts +20 -0
  21. package/dashboard/dist/components/BugsPane.js +210 -0
  22. package/dashboard/dist/components/BugsPane.test.d.ts +1 -0
  23. package/dashboard/dist/components/BugsPane.test.js +256 -0
  24. package/dashboard/dist/components/HealthPane.d.ts +3 -1
  25. package/dashboard/dist/components/HealthPane.js +44 -6
  26. package/dashboard/dist/components/HealthPane.test.js +105 -2
  27. package/dashboard/dist/components/RouterPane.d.ts +4 -3
  28. package/dashboard/dist/components/RouterPane.js +60 -57
  29. package/dashboard/dist/components/RouterPane.test.js +150 -96
  30. package/dashboard/dist/components/UpdateBanner.d.ts +26 -0
  31. package/dashboard/dist/components/UpdateBanner.js +30 -0
  32. package/dashboard/dist/components/UpdateBanner.test.d.ts +1 -0
  33. package/dashboard/dist/components/UpdateBanner.test.js +96 -0
  34. package/dashboard/dist/components/ui/EmptyState.d.ts +14 -0
  35. package/dashboard/dist/components/ui/EmptyState.js +58 -0
  36. package/dashboard/dist/components/ui/EmptyState.test.d.ts +1 -0
  37. package/dashboard/dist/components/ui/EmptyState.test.js +97 -0
  38. package/dashboard/dist/components/ui/ErrorState.d.ts +17 -0
  39. package/dashboard/dist/components/ui/ErrorState.js +80 -0
  40. package/dashboard/dist/components/ui/ErrorState.test.d.ts +1 -0
  41. package/dashboard/dist/components/ui/ErrorState.test.js +166 -0
  42. package/dashboard/package.json +3 -0
  43. package/package.json +4 -1
  44. package/server/dashboard/index.html +284 -13
  45. package/server/dashboard/login.html +262 -0
  46. package/server/index.js +304 -0
  47. package/server/lib/api-provider.js +104 -186
  48. package/server/lib/api-provider.test.js +238 -336
  49. package/server/lib/cli-detector.js +90 -166
  50. package/server/lib/cli-detector.test.js +114 -269
  51. package/server/lib/cli-provider.js +142 -212
  52. package/server/lib/cli-provider.test.js +196 -349
  53. package/server/lib/debug.test.js +3 -3
  54. package/server/lib/devserver-router-api.js +54 -249
  55. package/server/lib/devserver-router-api.test.js +126 -426
  56. package/server/lib/introspect.js +309 -0
  57. package/server/lib/introspect.test.js +286 -0
  58. package/server/lib/model-router.js +107 -245
  59. package/server/lib/model-router.test.js +122 -313
  60. package/server/lib/output-schemas.js +146 -269
  61. package/server/lib/output-schemas.test.js +106 -307
  62. package/server/lib/plan-parser.js +59 -16
  63. package/server/lib/provider-interface.js +99 -153
  64. package/server/lib/provider-interface.test.js +228 -394
  65. package/server/lib/provider-queue.js +164 -158
  66. package/server/lib/provider-queue.test.js +186 -315
  67. package/server/lib/router-config.js +99 -221
  68. package/server/lib/router-config.test.js +83 -237
  69. package/server/lib/router-setup-command.js +94 -419
  70. package/server/lib/router-setup-command.test.js +96 -375
  71. package/server/lib/router-status-api.js +93 -0
  72. package/server/lib/router-status-api.test.js +270 -0
@@ -1,249 +1,54 @@
1
- /**
2
- * Devserver Router API - HTTP endpoints for task execution
3
- */
4
-
5
- import { createRouter } from './model-router.js';
6
- import { createQueue } from './provider-queue.js';
7
-
8
- /**
9
- * Create router API handlers
10
- * @param {Object} options - API options
11
- * @param {string} options.secret - Authentication secret
12
- * @param {Object} [options.routerConfig] - Router configuration
13
- * @param {Object} [options.queueConfig] - Queue configuration
14
- * @returns {Promise<Object>} API handlers
15
- */
16
- export async function createRouterAPI(options = {}) {
17
- const { secret, routerConfig, queueConfig } = options;
18
-
19
- // Initialize router and queue
20
- const router = await createRouter(routerConfig);
21
- const queue = createQueue(queueConfig);
22
-
23
- return {
24
- handleRun: handleRun(router, queue),
25
- handleTaskStatus: handleTaskStatus(queue),
26
- handleReview: handleReview(router),
27
- handleDesign: handleDesign(router),
28
- handleHealth: handleHealth(router),
29
- validateAuth: validateAuth(secret),
30
- router,
31
- queue,
32
- };
33
- }
34
-
35
- /**
36
- * Handle POST /api/run - Queue a task
37
- * @param {Object} router - Router instance
38
- * @param {Object} queue - Queue instance
39
- * @returns {Function} Express handler
40
- */
41
- export function handleRun(router, queue) {
42
- return async (req, res) => {
43
- try {
44
- const { capability, prompt, options = {} } = req.body;
45
-
46
- // Create task function
47
- const taskFn = async () => {
48
- return await router.run(capability, prompt, options);
49
- };
50
-
51
- // Enqueue the task
52
- const taskId = await queue.enqueue(taskFn, {
53
- priority: options.priority || 5,
54
- capability,
55
- });
56
-
57
- res.json({ taskId });
58
- } catch (err) {
59
- res.status(500).json({ error: err.message });
60
- }
61
- };
62
- }
63
-
64
- /**
65
- * Handle GET /api/task/:taskId - Get task status
66
- * @param {Object} queue - Queue instance
67
- * @returns {Function} Express handler
68
- */
69
- export function handleTaskStatus(queue) {
70
- return async (req, res) => {
71
- try {
72
- const { taskId } = req.params;
73
- const task = queue.getTask(taskId);
74
-
75
- if (!task) {
76
- return res.status(404).json({ error: 'Task not found' });
77
- }
78
-
79
- res.json({
80
- status: task.status,
81
- result: task.result,
82
- error: task.error,
83
- createdAt: task.createdAt,
84
- completedAt: task.completedAt,
85
- });
86
- } catch (err) {
87
- res.status(500).json({ error: err.message });
88
- }
89
- };
90
- }
91
-
92
- /**
93
- * Handle POST /api/review - Multi-model review
94
- * @param {Object} router - Router instance
95
- * @returns {Function} Express handler
96
- */
97
- export function handleReview(router) {
98
- return async (req, res) => {
99
- try {
100
- const { code, prompt = 'Review this code', options = {} } = req.body;
101
-
102
- const fullPrompt = code ? `${prompt}\n\n\`\`\`\n${code}\n\`\`\`` : prompt;
103
-
104
- const results = await router.run('review', fullPrompt, options);
105
-
106
- // Calculate consensus
107
- const consensus = calculateConsensus(results);
108
-
109
- res.json({
110
- consensus,
111
- results,
112
- });
113
- } catch (err) {
114
- res.status(500).json({ error: err.message });
115
- }
116
- };
117
- }
118
-
119
- /**
120
- * Handle POST /api/design - Design generation
121
- * @param {Object} router - Router instance
122
- * @returns {Function} Express handler
123
- */
124
- export function handleDesign(router) {
125
- return async (req, res) => {
126
- try {
127
- const { prompt, options = {} } = req.body;
128
-
129
- const results = await router.run('design', prompt, options);
130
-
131
- // Return first successful result
132
- const successful = results.find((r) => r.success);
133
-
134
- res.json({
135
- result: successful?.result || null,
136
- provider: successful?.provider,
137
- error: successful ? null : 'No successful design generated',
138
- });
139
- } catch (err) {
140
- res.status(500).json({ error: err.message });
141
- }
142
- };
143
- }
144
-
145
- /**
146
- * Handle GET /api/health - Provider health
147
- * @param {Object} router - Router instance
148
- * @returns {Function} Express handler
149
- */
150
- export function handleHealth(router) {
151
- return async (req, res) => {
152
- try {
153
- const status = router.getStatus();
154
-
155
- // Check if at least one provider is available
156
- const hasAvailable = Object.values(status.providers || {}).some(
157
- (p) => p.detected || p.type === 'api'
158
- );
159
-
160
- res.json({
161
- healthy: hasAvailable,
162
- providers: status.providers,
163
- devserver: status.devserver,
164
- });
165
- } catch (err) {
166
- res.status(500).json({ error: err.message, healthy: false });
167
- }
168
- };
169
- }
170
-
171
- /**
172
- * Authentication middleware
173
- * @param {string} secret - Expected secret
174
- * @returns {Function} Express middleware
175
- */
176
- export function validateAuth(secret) {
177
- return (req, res, next) => {
178
- const authHeader = req.headers.authorization;
179
-
180
- if (!authHeader) {
181
- return res.status(401).json({ error: 'Authorization header required' });
182
- }
183
-
184
- const token = authHeader.replace('Bearer ', '');
185
-
186
- if (token !== secret) {
187
- return res.status(401).json({ error: 'Invalid authorization token' });
188
- }
189
-
190
- next();
191
- };
192
- }
193
-
194
- /**
195
- * Request body validation middleware
196
- * @param {string[]} requiredFields - Required field names
197
- * @returns {Function} Express middleware
198
- */
199
- export function validateRequestBody(requiredFields) {
200
- return (req, res, next) => {
201
- const body = req.body || {};
202
- const missing = requiredFields.filter((field) => !body[field]);
203
-
204
- if (missing.length > 0) {
205
- return res.status(400).json({
206
- error: `Missing required fields: ${missing.join(', ')}`,
207
- });
208
- }
209
-
210
- next();
211
- };
212
- }
213
-
214
- /**
215
- * Calculate consensus from multiple provider results
216
- * @param {Object[]} results - Provider results
217
- * @returns {Object} Consensus result
218
- */
219
- function calculateConsensus(results) {
220
- const successful = results.filter((r) => r.success);
221
-
222
- if (successful.length === 0) {
223
- return { approved: false, reason: 'No successful reviews' };
224
- }
225
-
226
- // Count approvals
227
- const approvals = successful.filter((r) => r.result?.approved).length;
228
- const total = successful.length;
229
-
230
- // Majority vote
231
- const approved = approvals > total / 2;
232
-
233
- // Average score if available
234
- const scores = successful
235
- .map((r) => r.result?.score)
236
- .filter((s) => typeof s === 'number');
237
-
238
- const averageScore =
239
- scores.length > 0
240
- ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length)
241
- : null;
242
-
243
- return {
244
- approved,
245
- votes: { approve: approvals, reject: total - approvals },
246
- averageScore,
247
- providers: successful.map((r) => r.provider),
248
- };
249
- }
1
+ /**
2
+ * Devserver Router API - HTTP API for devserver task execution
3
+ * Phase 33, Task 7
4
+ */
5
+
6
+ export async function handleRun(req, res, ctx = {}) {
7
+ if (ctx.requireAuth && !req.headers?.authorization) {
8
+ return res.status(401).json({ error: 'Unauthorized' });
9
+ }
10
+
11
+ const { provider, prompt } = req.body || {};
12
+ if (!provider || !prompt) {
13
+ return res.status(400).json({ error: 'provider and prompt required' });
14
+ }
15
+
16
+ const taskId = ctx.queue?.enqueue({ provider, prompt }) || 'task-' + Date.now();
17
+ res.json({ taskId });
18
+ }
19
+
20
+ export async function handleTask(req, res, ctx = {}) {
21
+ const { taskId } = req.params;
22
+ const task = ctx.queue?.getTask(taskId) || { status: 'unknown' };
23
+ res.json(task);
24
+ }
25
+
26
+ export async function handleReview(req, res, ctx = {}) {
27
+ const { code } = req.body;
28
+ const providers = ctx.providers || ['claude'];
29
+ const results = [];
30
+
31
+ for (const provider of providers) {
32
+ const result = await ctx.runProvider(provider, { prompt: 'Review: ' + code });
33
+ results.push(result.parsed);
34
+ }
35
+
36
+ const scores = results.map(r => r?.score || 0);
37
+ const avgScore = scores.reduce((a, b) => a + b, 0) / scores.length;
38
+ const approved = results.filter(r => r?.approved).length > results.length / 2;
39
+
40
+ res.json({ results, consensus: { score: avgScore, approved } });
41
+ }
42
+
43
+ export async function handleDesign(req, res, ctx = {}) {
44
+ const { description } = req.body;
45
+ const result = await ctx.runProvider('gemini', { prompt: 'Design: ' + description });
46
+ res.json(result.parsed || {});
47
+ }
48
+
49
+ export async function handleHealth(req, res, ctx = {}) {
50
+ const providers = ctx.getProviderStatus?.() || {};
51
+ res.json({ status: 'ok', providers });
52
+ }
53
+
54
+ export default { handleRun, handleTask, handleReview, handleDesign, handleHealth };