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.
- package/dashboard/dist/App.js +28 -2
- package/dashboard/dist/api/health-diagnostics.d.ts +26 -0
- package/dashboard/dist/api/health-diagnostics.js +85 -0
- package/dashboard/dist/api/health-diagnostics.test.d.ts +1 -0
- package/dashboard/dist/api/health-diagnostics.test.js +126 -0
- package/dashboard/dist/api/index.d.ts +5 -0
- package/dashboard/dist/api/index.js +5 -0
- package/dashboard/dist/api/notes-api.d.ts +18 -0
- package/dashboard/dist/api/notes-api.js +68 -0
- package/dashboard/dist/api/notes-api.test.d.ts +1 -0
- package/dashboard/dist/api/notes-api.test.js +113 -0
- package/dashboard/dist/api/safeFetch.d.ts +50 -0
- package/dashboard/dist/api/safeFetch.js +135 -0
- package/dashboard/dist/api/safeFetch.test.d.ts +1 -0
- package/dashboard/dist/api/safeFetch.test.js +215 -0
- package/dashboard/dist/api/tasks-api.d.ts +32 -0
- package/dashboard/dist/api/tasks-api.js +98 -0
- package/dashboard/dist/api/tasks-api.test.d.ts +1 -0
- package/dashboard/dist/api/tasks-api.test.js +383 -0
- package/dashboard/dist/components/BugsPane.d.ts +20 -0
- package/dashboard/dist/components/BugsPane.js +210 -0
- package/dashboard/dist/components/BugsPane.test.d.ts +1 -0
- package/dashboard/dist/components/BugsPane.test.js +256 -0
- package/dashboard/dist/components/HealthPane.d.ts +3 -1
- package/dashboard/dist/components/HealthPane.js +44 -6
- package/dashboard/dist/components/HealthPane.test.js +105 -2
- package/dashboard/dist/components/RouterPane.d.ts +4 -3
- package/dashboard/dist/components/RouterPane.js +60 -57
- package/dashboard/dist/components/RouterPane.test.js +150 -96
- package/dashboard/dist/components/UpdateBanner.d.ts +26 -0
- package/dashboard/dist/components/UpdateBanner.js +30 -0
- package/dashboard/dist/components/UpdateBanner.test.d.ts +1 -0
- package/dashboard/dist/components/UpdateBanner.test.js +96 -0
- package/dashboard/dist/components/ui/EmptyState.d.ts +14 -0
- package/dashboard/dist/components/ui/EmptyState.js +58 -0
- package/dashboard/dist/components/ui/EmptyState.test.d.ts +1 -0
- package/dashboard/dist/components/ui/EmptyState.test.js +97 -0
- package/dashboard/dist/components/ui/ErrorState.d.ts +17 -0
- package/dashboard/dist/components/ui/ErrorState.js +80 -0
- package/dashboard/dist/components/ui/ErrorState.test.d.ts +1 -0
- package/dashboard/dist/components/ui/ErrorState.test.js +166 -0
- package/dashboard/package.json +3 -0
- package/package.json +4 -1
- package/server/dashboard/index.html +284 -13
- package/server/dashboard/login.html +262 -0
- package/server/index.js +304 -0
- package/server/lib/api-provider.js +104 -186
- package/server/lib/api-provider.test.js +238 -336
- package/server/lib/cli-detector.js +90 -166
- package/server/lib/cli-detector.test.js +114 -269
- package/server/lib/cli-provider.js +142 -212
- package/server/lib/cli-provider.test.js +196 -349
- package/server/lib/debug.test.js +3 -3
- package/server/lib/devserver-router-api.js +54 -249
- package/server/lib/devserver-router-api.test.js +126 -426
- package/server/lib/introspect.js +309 -0
- package/server/lib/introspect.test.js +286 -0
- package/server/lib/model-router.js +107 -245
- package/server/lib/model-router.test.js +122 -313
- package/server/lib/output-schemas.js +146 -269
- package/server/lib/output-schemas.test.js +106 -307
- package/server/lib/plan-parser.js +59 -16
- package/server/lib/provider-interface.js +99 -153
- package/server/lib/provider-interface.test.js +228 -394
- package/server/lib/provider-queue.js +164 -158
- package/server/lib/provider-queue.test.js +186 -315
- package/server/lib/router-config.js +99 -221
- package/server/lib/router-config.test.js +83 -237
- package/server/lib/router-setup-command.js +94 -419
- package/server/lib/router-setup-command.test.js +96 -375
- package/server/lib/router-status-api.js +93 -0
- package/server/lib/router-status-api.test.js +270 -0
|
@@ -1,315 +1,186 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
queue
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
expect(
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
execute: async () => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const urgentPromise = enqueue(q, {
|
|
190
|
-
id: 'urgent',
|
|
191
|
-
priority: PRIORITY.URGENT,
|
|
192
|
-
execute: async () => { order.push('urgent'); return 'urgent'; },
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
// Release blocker
|
|
196
|
-
resolver('done');
|
|
197
|
-
await blockerPromise;
|
|
198
|
-
await Promise.all([normalPromise, urgentPromise]);
|
|
199
|
-
|
|
200
|
-
// Urgent should have been processed before normal
|
|
201
|
-
expect(order[0]).toBe('urgent');
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('low priority goes last', async () => {
|
|
205
|
-
const q = createQueue({ maxConcurrent: 1 });
|
|
206
|
-
const order = [];
|
|
207
|
-
|
|
208
|
-
let resolver;
|
|
209
|
-
const blocker = {
|
|
210
|
-
id: 'blocker',
|
|
211
|
-
execute: () => new Promise(r => { resolver = r; }),
|
|
212
|
-
};
|
|
213
|
-
const blockerPromise = enqueue(q, blocker);
|
|
214
|
-
|
|
215
|
-
const lowPromise = enqueue(q, {
|
|
216
|
-
id: 'low',
|
|
217
|
-
priority: PRIORITY.LOW,
|
|
218
|
-
execute: async () => { order.push('low'); return 'low'; },
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
const normalPromise = enqueue(q, {
|
|
222
|
-
id: 'normal',
|
|
223
|
-
priority: PRIORITY.NORMAL,
|
|
224
|
-
execute: async () => { order.push('normal'); return 'normal'; },
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
resolver('done');
|
|
228
|
-
await blockerPromise;
|
|
229
|
-
await Promise.all([lowPromise, normalPromise]);
|
|
230
|
-
|
|
231
|
-
expect(order[order.length - 1]).toBe('low');
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('clearQueue', () => {
|
|
236
|
-
it('removes all pending tasks', async () => {
|
|
237
|
-
const q = createQueue({ maxConcurrent: 1 });
|
|
238
|
-
|
|
239
|
-
// Block the queue
|
|
240
|
-
let resolver;
|
|
241
|
-
enqueue(q, {
|
|
242
|
-
id: 'blocker',
|
|
243
|
-
execute: () => new Promise(r => { resolver = r; }),
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// Add pending tasks
|
|
247
|
-
const pending1 = enqueue(q, { id: 'p1', execute: vi.fn() });
|
|
248
|
-
const pending2 = enqueue(q, { id: 'p2', execute: vi.fn() });
|
|
249
|
-
|
|
250
|
-
clearQueue(q);
|
|
251
|
-
resolver('done');
|
|
252
|
-
|
|
253
|
-
// Pending tasks should be rejected
|
|
254
|
-
await expect(pending1).rejects.toThrow(/cleared/i);
|
|
255
|
-
await expect(pending2).rejects.toThrow(/cleared/i);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
describe('drainQueue', () => {
|
|
260
|
-
it('waits for all tasks to complete', async () => {
|
|
261
|
-
const q = createQueue({ maxConcurrent: 2 });
|
|
262
|
-
const completed = [];
|
|
263
|
-
|
|
264
|
-
enqueue(q, {
|
|
265
|
-
id: 't1',
|
|
266
|
-
execute: async () => {
|
|
267
|
-
await new Promise(r => setTimeout(r, 30));
|
|
268
|
-
completed.push('t1');
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
enqueue(q, {
|
|
273
|
-
id: 't2',
|
|
274
|
-
execute: async () => {
|
|
275
|
-
await new Promise(r => setTimeout(r, 20));
|
|
276
|
-
completed.push('t2');
|
|
277
|
-
},
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
await drainQueue(q);
|
|
281
|
-
|
|
282
|
-
expect(completed).toContain('t1');
|
|
283
|
-
expect(completed).toContain('t2');
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('resolves immediately if queue is empty', async () => {
|
|
287
|
-
const q = createQueue();
|
|
288
|
-
|
|
289
|
-
const start = Date.now();
|
|
290
|
-
await drainQueue(q);
|
|
291
|
-
const elapsed = Date.now() - start;
|
|
292
|
-
|
|
293
|
-
expect(elapsed).toBeLessThan(50);
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
describe('PRIORITY constants', () => {
|
|
298
|
-
it('exports URGENT', () => {
|
|
299
|
-
expect(PRIORITY.URGENT).toBeDefined();
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('exports NORMAL', () => {
|
|
303
|
-
expect(PRIORITY.NORMAL).toBeDefined();
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it('exports LOW', () => {
|
|
307
|
-
expect(PRIORITY.LOW).toBeDefined();
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('URGENT > NORMAL > LOW', () => {
|
|
311
|
-
expect(PRIORITY.URGENT).toBeGreaterThan(PRIORITY.NORMAL);
|
|
312
|
-
expect(PRIORITY.NORMAL).toBeGreaterThan(PRIORITY.LOW);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
ProviderQueue,
|
|
4
|
+
Priority,
|
|
5
|
+
} from './provider-queue.js';
|
|
6
|
+
|
|
7
|
+
describe('Provider Queue', () => {
|
|
8
|
+
let queue;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
queue = new ProviderQueue({ maxConcurrent: 3 });
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('enqueue', () => {
|
|
15
|
+
it('adds task to queue', () => {
|
|
16
|
+
const task = { id: '1', prompt: 'test' };
|
|
17
|
+
queue.enqueue(task);
|
|
18
|
+
|
|
19
|
+
expect(queue.getStatus().pending).toBe(1);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('returns task id', () => {
|
|
23
|
+
const taskId = queue.enqueue({ prompt: 'test' });
|
|
24
|
+
expect(taskId).toBeDefined();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('dequeue', () => {
|
|
29
|
+
it('respects maxConcurrent', async () => {
|
|
30
|
+
const tasks = [];
|
|
31
|
+
for (let i = 0; i < 5; i++) {
|
|
32
|
+
tasks.push(queue.enqueue({
|
|
33
|
+
prompt: `test ${i}`,
|
|
34
|
+
execute: () => new Promise(r => setTimeout(r, 100)),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Start processing
|
|
39
|
+
queue.process();
|
|
40
|
+
|
|
41
|
+
// Should have max 3 running
|
|
42
|
+
expect(queue.getStatus().running).toBeLessThanOrEqual(3);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('processes FIFO', async () => {
|
|
46
|
+
const order = [];
|
|
47
|
+
|
|
48
|
+
queue.enqueue({
|
|
49
|
+
id: 'first',
|
|
50
|
+
execute: async () => { order.push('first'); },
|
|
51
|
+
});
|
|
52
|
+
queue.enqueue({
|
|
53
|
+
id: 'second',
|
|
54
|
+
execute: async () => { order.push('second'); },
|
|
55
|
+
});
|
|
56
|
+
queue.enqueue({
|
|
57
|
+
id: 'third',
|
|
58
|
+
execute: async () => { order.push('third'); },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await queue.drainQueue();
|
|
62
|
+
|
|
63
|
+
expect(order).toEqual(['first', 'second', 'third']);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('timeout', () => {
|
|
68
|
+
it('cancels slow tasks', async () => {
|
|
69
|
+
const slowQueue = new ProviderQueue({ maxConcurrent: 1, timeout: 50 });
|
|
70
|
+
|
|
71
|
+
const taskId = slowQueue.enqueue({
|
|
72
|
+
execute: () => new Promise(r => setTimeout(r, 1000)),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
slowQueue.process();
|
|
76
|
+
await new Promise(r => setTimeout(r, 100));
|
|
77
|
+
|
|
78
|
+
const status = slowQueue.getTaskStatus(taskId);
|
|
79
|
+
expect(status).toBe('cancelled');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('getStatus', () => {
|
|
84
|
+
it('returns queue length', () => {
|
|
85
|
+
queue.enqueue({ prompt: 'test 1' });
|
|
86
|
+
queue.enqueue({ prompt: 'test 2' });
|
|
87
|
+
|
|
88
|
+
const status = queue.getStatus();
|
|
89
|
+
expect(status.pending).toBe(2);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('returns running count', async () => {
|
|
93
|
+
queue.enqueue({
|
|
94
|
+
execute: () => new Promise(r => setTimeout(r, 100)),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
queue.process();
|
|
98
|
+
|
|
99
|
+
const status = queue.getStatus();
|
|
100
|
+
expect(status.running).toBe(1);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('priority', () => {
|
|
105
|
+
it('urgent goes first', async () => {
|
|
106
|
+
const order = [];
|
|
107
|
+
|
|
108
|
+
queue.enqueue({
|
|
109
|
+
priority: Priority.LOW,
|
|
110
|
+
execute: async () => { order.push('low'); },
|
|
111
|
+
});
|
|
112
|
+
queue.enqueue({
|
|
113
|
+
priority: Priority.URGENT,
|
|
114
|
+
execute: async () => { order.push('urgent'); },
|
|
115
|
+
});
|
|
116
|
+
queue.enqueue({
|
|
117
|
+
priority: Priority.NORMAL,
|
|
118
|
+
execute: async () => { order.push('normal'); },
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await queue.drainQueue();
|
|
122
|
+
|
|
123
|
+
expect(order[0]).toBe('urgent');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('affects ordering', async () => {
|
|
127
|
+
const order = [];
|
|
128
|
+
|
|
129
|
+
queue.enqueue({
|
|
130
|
+
priority: Priority.LOW,
|
|
131
|
+
execute: async () => { order.push('low'); },
|
|
132
|
+
});
|
|
133
|
+
queue.enqueue({
|
|
134
|
+
priority: Priority.NORMAL,
|
|
135
|
+
execute: async () => { order.push('normal'); },
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await queue.drainQueue();
|
|
139
|
+
|
|
140
|
+
expect(order.indexOf('normal')).toBeLessThan(order.indexOf('low'));
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('clearQueue', () => {
|
|
145
|
+
it('removes all pending', () => {
|
|
146
|
+
queue.enqueue({ prompt: 'test 1' });
|
|
147
|
+
queue.enqueue({ prompt: 'test 2' });
|
|
148
|
+
queue.enqueue({ prompt: 'test 3' });
|
|
149
|
+
|
|
150
|
+
queue.clearQueue();
|
|
151
|
+
|
|
152
|
+
expect(queue.getStatus().pending).toBe(0);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('drainQueue', () => {
|
|
157
|
+
it('waits for completion', async () => {
|
|
158
|
+
let completed = false;
|
|
159
|
+
|
|
160
|
+
queue.enqueue({
|
|
161
|
+
execute: async () => {
|
|
162
|
+
await new Promise(r => setTimeout(r, 50));
|
|
163
|
+
completed = true;
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await queue.drainQueue();
|
|
168
|
+
|
|
169
|
+
expect(completed).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('Priority', () => {
|
|
175
|
+
it('exports URGENT constant', () => {
|
|
176
|
+
expect(Priority.URGENT).toBe('urgent');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('exports NORMAL constant', () => {
|
|
180
|
+
expect(Priority.NORMAL).toBe('normal');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('exports LOW constant', () => {
|
|
184
|
+
expect(Priority.LOW).toBe('low');
|
|
185
|
+
});
|
|
186
|
+
});
|