@ebowwa/coder 0.7.64 → 0.7.65
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/dist/index.js +36168 -32
- package/dist/interfaces/ui/terminal/cli/index.js +34253 -158
- package/dist/interfaces/ui/terminal/native/README.md +53 -0
- package/dist/interfaces/ui/terminal/native/claude_code_native.darwin-x64.node +0 -0
- package/dist/interfaces/ui/terminal/native/claude_code_native.dylib +0 -0
- package/dist/interfaces/ui/terminal/native/index.d.ts +0 -0
- package/dist/interfaces/ui/terminal/native/index.darwin-arm64.node +0 -0
- package/dist/interfaces/ui/terminal/native/index.js +43 -0
- package/dist/interfaces/ui/terminal/native/index.node +0 -0
- package/dist/interfaces/ui/terminal/native/package.json +34 -0
- package/dist/native/README.md +53 -0
- package/dist/native/claude_code_native.darwin-x64.node +0 -0
- package/dist/native/claude_code_native.dylib +0 -0
- package/dist/native/index.d.ts +0 -480
- package/dist/native/index.darwin-arm64.node +0 -0
- package/dist/native/index.js +43 -1625
- package/dist/native/index.node +0 -0
- package/dist/native/package.json +34 -0
- package/native/index.darwin-arm64.node +0 -0
- package/native/index.js +33 -19
- package/package.json +3 -2
- package/packages/src/core/agent-loop/__tests__/compaction.test.ts +17 -14
- package/packages/src/core/agent-loop/compaction.ts +6 -2
- package/packages/src/core/agent-loop/index.ts +2 -0
- package/packages/src/core/agent-loop/loop-state.ts +1 -1
- package/packages/src/core/agent-loop/turn-executor.ts +4 -0
- package/packages/src/core/agent-loop/types.ts +4 -0
- package/packages/src/core/api-client-impl.ts +283 -173
- package/packages/src/core/cognitive-security/hooks.ts +2 -1
- package/packages/src/core/config/todo +7 -0
- package/packages/src/core/context/__tests__/integration.test.ts +334 -0
- package/packages/src/core/context/compaction.ts +170 -0
- package/packages/src/core/context/constants.ts +58 -0
- package/packages/src/core/context/extraction.ts +85 -0
- package/packages/src/core/context/index.ts +66 -0
- package/packages/src/core/context/summarization.ts +251 -0
- package/packages/src/core/context/token-estimation.ts +98 -0
- package/packages/src/core/context/types.ts +59 -0
- package/packages/src/core/models.ts +81 -4
- package/packages/src/core/normalizers/todo +5 -1
- package/packages/src/core/providers/README.md +230 -0
- package/packages/src/core/providers/__tests__/providers.test.ts +135 -0
- package/packages/src/core/providers/index.ts +419 -0
- package/packages/src/core/providers/types.ts +132 -0
- package/packages/src/core/retry.ts +10 -0
- package/packages/src/ecosystem/tools/index.ts +174 -0
- package/packages/src/index.ts +23 -2
- package/packages/src/interfaces/ui/index.ts +17 -20
- package/packages/src/interfaces/ui/spinner.ts +2 -2
- package/packages/src/interfaces/ui/terminal/bridge/index.ts +370 -0
- package/packages/src/interfaces/ui/terminal/bridge/ipc.ts +829 -0
- package/packages/src/interfaces/ui/terminal/bridge/screen-export.ts +968 -0
- package/packages/src/interfaces/ui/terminal/bridge/types.ts +226 -0
- package/packages/src/interfaces/ui/terminal/bridge/useBridge.ts +210 -0
- package/packages/src/interfaces/ui/terminal/cli/bootstrap.ts +132 -0
- package/packages/src/interfaces/ui/terminal/cli/index.ts +200 -13
- package/packages/src/interfaces/ui/terminal/cli/interactive/index.ts +110 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/input-handler.ts +393 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/interactive-runner.ts +820 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/message-store.ts +299 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/types.ts +274 -0
- package/packages/src/interfaces/ui/terminal/shared/index.ts +13 -0
- package/packages/src/interfaces/ui/terminal/shared/query.ts +9 -3
- package/packages/src/interfaces/ui/terminal/shared/setup.ts +5 -1
- package/packages/src/interfaces/ui/terminal/shared/spinner-frames.ts +73 -0
- package/packages/src/interfaces/ui/terminal/shared/status-line.ts +10 -2
- package/packages/src/native/index.ts +404 -27
- package/packages/src/native/tui_v2_types.ts +39 -0
- package/packages/src/teammates/coordination.test.ts +279 -0
- package/packages/src/teammates/coordination.ts +646 -0
- package/packages/src/teammates/index.ts +95 -25
- package/packages/src/teammates/integration.test.ts +272 -0
- package/packages/src/teammates/runner.test.ts +235 -0
- package/packages/src/teammates/runner.ts +750 -0
- package/packages/src/teammates/schemas.ts +673 -0
- package/packages/src/types/index.ts +1 -0
- package/packages/src/core/context-compaction.ts +0 -578
- package/packages/src/interfaces/ui/Screenshot 2026-03-02 at 9.23.10/342/200/257PM.png +0 -0
- package/packages/src/interfaces/ui/Screenshot 2026-03-03 at 10.55.11/342/200/257AM.png +0 -0
- package/packages/src/interfaces/ui/terminal/tui/HelpPanel.tsx +0 -262
- package/packages/src/interfaces/ui/terminal/tui/InputContext.tsx +0 -232
- package/packages/src/interfaces/ui/terminal/tui/InputField.tsx +0 -62
- package/packages/src/interfaces/ui/terminal/tui/InteractiveTUI.tsx +0 -537
- package/packages/src/interfaces/ui/terminal/tui/MessageArea.tsx +0 -107
- package/packages/src/interfaces/ui/terminal/tui/MessageStore.tsx +0 -240
- package/packages/src/interfaces/ui/terminal/tui/StatusBar.tsx +0 -54
- package/packages/src/interfaces/ui/terminal/tui/commands.ts +0 -438
- package/packages/src/interfaces/ui/terminal/tui/components/InteractiveElements.tsx +0 -584
- package/packages/src/interfaces/ui/terminal/tui/components/MultilineInput.tsx +0 -614
- package/packages/src/interfaces/ui/terminal/tui/components/PaneManager.tsx +0 -333
- package/packages/src/interfaces/ui/terminal/tui/components/Sidebar.tsx +0 -604
- package/packages/src/interfaces/ui/terminal/tui/components/index.ts +0 -118
- package/packages/src/interfaces/ui/terminal/tui/console.ts +0 -49
- package/packages/src/interfaces/ui/terminal/tui/index.ts +0 -90
- package/packages/src/interfaces/ui/terminal/tui/run.tsx +0 -42
- package/packages/src/interfaces/ui/terminal/tui/spinner.ts +0 -69
- package/packages/src/interfaces/ui/terminal/tui/tui-app.tsx +0 -390
- package/packages/src/interfaces/ui/terminal/tui/tui-footer.ts +0 -422
- package/packages/src/interfaces/ui/terminal/tui/types.ts +0 -186
- package/packages/src/interfaces/ui/terminal/tui/useInputHandler.ts +0 -104
- package/packages/src/interfaces/ui/terminal/tui/useNativeInput.ts +0 -239
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Coordination Callbacks
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
|
6
|
+
import { existsSync, rmSync, mkdirSync } from "fs";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import { TeammateManager } from "./index.js";
|
|
9
|
+
import {
|
|
10
|
+
CoordinationManager,
|
|
11
|
+
createCoordinationMessage,
|
|
12
|
+
parseCoordinationMessage,
|
|
13
|
+
type CoordinationEvent,
|
|
14
|
+
type ProgressReport,
|
|
15
|
+
type FileClaim,
|
|
16
|
+
} from "./coordination.js";
|
|
17
|
+
|
|
18
|
+
// Helper to clean up claims directory
|
|
19
|
+
const CLAIMS_PATH = join(process.env.HOME || "", ".claude", "teams", "_coordination", "claims");
|
|
20
|
+
|
|
21
|
+
function cleanupClaims(): void {
|
|
22
|
+
if (existsSync(CLAIMS_PATH)) {
|
|
23
|
+
try {
|
|
24
|
+
rmSync(CLAIMS_PATH, { recursive: true, force: true });
|
|
25
|
+
} catch {
|
|
26
|
+
// Ignore errors
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe("Coordination Callbacks", () => {
|
|
32
|
+
let manager: TeammateManager;
|
|
33
|
+
let coordination: CoordinationManager;
|
|
34
|
+
const events: CoordinationEvent[] = [];
|
|
35
|
+
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
// Clean up any stale claims before each test
|
|
38
|
+
cleanupClaims();
|
|
39
|
+
|
|
40
|
+
manager = new TeammateManager();
|
|
41
|
+
coordination = new CoordinationManager(manager, {
|
|
42
|
+
enableFileLocking: true,
|
|
43
|
+
enableHeartbeat: false,
|
|
44
|
+
onCoordinationEvent: (event) => {
|
|
45
|
+
events.push(event);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
events.length = 0;
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
coordination.shutdown();
|
|
53
|
+
// Clean up claims after each test
|
|
54
|
+
cleanupClaims();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("Progress Reporting", () => {
|
|
58
|
+
it("should report progress to team", () => {
|
|
59
|
+
coordination.initialize("teammate-1", "test-team");
|
|
60
|
+
|
|
61
|
+
const progress: ProgressReport = {
|
|
62
|
+
step: "Building CSS styles",
|
|
63
|
+
stepNumber: 2,
|
|
64
|
+
totalSteps: 5,
|
|
65
|
+
percentage: 40,
|
|
66
|
+
files: ["styles.css"],
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
coordination.reportProgress(progress);
|
|
70
|
+
|
|
71
|
+
expect(events.length).toBe(1);
|
|
72
|
+
expect(events[0]!.type).toBe("task_progress");
|
|
73
|
+
expect(events[0]!.payload.progress).toEqual(progress);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should track current progress", () => {
|
|
77
|
+
coordination.initialize("teammate-1", "test-team");
|
|
78
|
+
|
|
79
|
+
const progress: ProgressReport = {
|
|
80
|
+
step: "Writing tests",
|
|
81
|
+
stepNumber: 3,
|
|
82
|
+
totalSteps: 4,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
coordination.reportProgress(progress);
|
|
86
|
+
|
|
87
|
+
// Progress should be emitted
|
|
88
|
+
const progressEvents = events.filter((e) => e.type === "task_progress");
|
|
89
|
+
expect(progressEvents.length).toBe(1);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe("Blocked/Unblocked", () => {
|
|
94
|
+
it("should report blocked status", () => {
|
|
95
|
+
coordination.initialize("teammate-1", "test-team");
|
|
96
|
+
|
|
97
|
+
coordination.reportBlocked("Waiting for CSS file", "css-builder");
|
|
98
|
+
|
|
99
|
+
expect(events.length).toBe(1);
|
|
100
|
+
expect(events[0]!.type).toBe("blocked");
|
|
101
|
+
expect(events[0]!.payload.reason).toBe("Waiting for CSS file");
|
|
102
|
+
expect(events[0]!.payload.blockedBy).toBe("css-builder");
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should report unblocked status", () => {
|
|
106
|
+
coordination.initialize("teammate-1", "test-team");
|
|
107
|
+
|
|
108
|
+
coordination.reportBlocked("Waiting for CSS file");
|
|
109
|
+
coordination.reportUnblocked();
|
|
110
|
+
|
|
111
|
+
const blockedEvents = events.filter((e) => e.type === "blocked");
|
|
112
|
+
const unblockedEvents = events.filter((e) => e.type === "unblocked");
|
|
113
|
+
|
|
114
|
+
expect(blockedEvents.length).toBe(1);
|
|
115
|
+
expect(unblockedEvents.length).toBe(1);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe("File Locking", () => {
|
|
120
|
+
it("should claim a file", () => {
|
|
121
|
+
coordination.initialize("teammate-1", "test-team");
|
|
122
|
+
|
|
123
|
+
const claimed = coordination.claimFile("/path/to/file.ts", "Writing code");
|
|
124
|
+
|
|
125
|
+
expect(claimed).toBe(true);
|
|
126
|
+
expect(coordination.isFileClaimed("/path/to/file.ts")).toBe(false); // We own it
|
|
127
|
+
expect(coordination.getFileClaim("/path/to/file.ts")?.reason).toBe("Writing code");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("should prevent other teammates from claiming", () => {
|
|
131
|
+
coordination.initialize("teammate-1", "test-team");
|
|
132
|
+
|
|
133
|
+
coordination.claimFile("/path/to/file.ts", "Writing code");
|
|
134
|
+
|
|
135
|
+
// Simulate another teammate trying to claim
|
|
136
|
+
const coordination2 = new CoordinationManager(manager, {
|
|
137
|
+
enableFileLocking: true,
|
|
138
|
+
});
|
|
139
|
+
coordination2.initialize("teammate-2", "test-team");
|
|
140
|
+
|
|
141
|
+
const claimed = coordination2.claimFile("/path/to/file.ts", "Also writing");
|
|
142
|
+
|
|
143
|
+
expect(claimed).toBe(false);
|
|
144
|
+
expect(coordination2.isFileClaimed("/path/to/file.ts")).toBe(true);
|
|
145
|
+
|
|
146
|
+
coordination2.shutdown();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("should release a file claim", () => {
|
|
150
|
+
coordination.initialize("teammate-1", "test-team");
|
|
151
|
+
|
|
152
|
+
coordination.claimFile("/path/to/file.ts");
|
|
153
|
+
coordination.releaseFile("/path/to/file.ts");
|
|
154
|
+
|
|
155
|
+
// Create another coordination and try to claim
|
|
156
|
+
const coordination2 = new CoordinationManager(manager, {
|
|
157
|
+
enableFileLocking: true,
|
|
158
|
+
});
|
|
159
|
+
coordination2.initialize("teammate-2", "test-team");
|
|
160
|
+
|
|
161
|
+
const claimed = coordination2.claimFile("/path/to/file.ts");
|
|
162
|
+
expect(claimed).toBe(true);
|
|
163
|
+
|
|
164
|
+
coordination2.shutdown();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("should release all claims on shutdown", () => {
|
|
168
|
+
coordination.initialize("teammate-1", "test-team");
|
|
169
|
+
|
|
170
|
+
coordination.claimFile("/file1.ts");
|
|
171
|
+
coordination.claimFile("/file2.ts");
|
|
172
|
+
|
|
173
|
+
coordination.shutdown();
|
|
174
|
+
|
|
175
|
+
// Re-create and check if files are available
|
|
176
|
+
const coordination2 = new CoordinationManager(manager, {
|
|
177
|
+
enableFileLocking: true,
|
|
178
|
+
});
|
|
179
|
+
coordination2.initialize("teammate-2", "test-team");
|
|
180
|
+
|
|
181
|
+
expect(coordination2.isFileClaimed("/file1.ts")).toBe(false);
|
|
182
|
+
expect(coordination2.isFileClaimed("/file2.ts")).toBe(false);
|
|
183
|
+
|
|
184
|
+
coordination2.shutdown();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("should list all claims", () => {
|
|
188
|
+
coordination.initialize("teammate-1", "test-team");
|
|
189
|
+
|
|
190
|
+
coordination.claimFile("/file1.ts", "Working on file 1");
|
|
191
|
+
coordination.claimFile("/file2.ts", "Working on file 2");
|
|
192
|
+
|
|
193
|
+
const claims = coordination.getAllClaims();
|
|
194
|
+
|
|
195
|
+
expect(claims.length).toBe(2);
|
|
196
|
+
expect(claims.some((c) => c.filePath === "/file1.ts")).toBe(true);
|
|
197
|
+
expect(claims.some((c) => c.filePath === "/file2.ts")).toBe(true);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("should support expiring claims", () => {
|
|
201
|
+
coordination.initialize("teammate-1", "test-team");
|
|
202
|
+
|
|
203
|
+
// Claim with 100ms expiration
|
|
204
|
+
coordination.claimFile("/file.ts", "Quick edit", 100);
|
|
205
|
+
|
|
206
|
+
// Should be claimed initially
|
|
207
|
+
expect(coordination.getFileClaim("/file.ts")).toBeDefined();
|
|
208
|
+
|
|
209
|
+
// Wait for expiration
|
|
210
|
+
// Note: In real tests, we'd use fake timers
|
|
211
|
+
// For now, just test the claim exists
|
|
212
|
+
const claim = coordination.getFileClaim("/file.ts");
|
|
213
|
+
expect(claim?.expiresAt).toBeDefined();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe("Coordination Messages", () => {
|
|
218
|
+
it("should create coordination messages", () => {
|
|
219
|
+
const msg = createCoordinationMessage("task_progress", "50% complete");
|
|
220
|
+
expect(msg).toBe("[COORD:TASK_PROGRESS] 50% complete");
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("should parse coordination messages", () => {
|
|
224
|
+
const result = parseCoordinationMessage("[COORD:FILE_CLAIM] /path/to/file.ts");
|
|
225
|
+
expect(result.isCoordination).toBe(true);
|
|
226
|
+
expect(result.type).toBe("file_claim");
|
|
227
|
+
expect(result.content).toBe("/path/to/file.ts");
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("should return false for non-coordination messages", () => {
|
|
231
|
+
const result = parseCoordinationMessage("Hello teammates!");
|
|
232
|
+
expect(result.isCoordination).toBe(false);
|
|
233
|
+
expect(result.type).toBeUndefined();
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe("Event Callbacks", () => {
|
|
238
|
+
it("should call onProgress callback", () => {
|
|
239
|
+
const progressReports: Array<{ id: string; progress: ProgressReport }> = [];
|
|
240
|
+
|
|
241
|
+
const coordWithCallbacks = new CoordinationManager(manager, {
|
|
242
|
+
enableProgressReporting: true,
|
|
243
|
+
onProgress: (teammateId, progress) => {
|
|
244
|
+
progressReports.push({ id: teammateId, progress });
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
coordWithCallbacks.initialize("teammate-1", "test-team");
|
|
249
|
+
coordWithCallbacks.reportProgress({
|
|
250
|
+
step: "Test",
|
|
251
|
+
stepNumber: 1,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
expect(progressReports.length).toBe(1);
|
|
255
|
+
expect(progressReports[0]!.progress.step).toBe("Test");
|
|
256
|
+
|
|
257
|
+
coordWithCallbacks.shutdown();
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it("should call onFileClaimed callback", () => {
|
|
261
|
+
const claims: FileClaim[] = [];
|
|
262
|
+
|
|
263
|
+
const coordWithCallbacks = new CoordinationManager(manager, {
|
|
264
|
+
enableFileLocking: true,
|
|
265
|
+
onFileClaimed: (claim) => {
|
|
266
|
+
claims.push(claim);
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
coordWithCallbacks.initialize("teammate-1", "test-team");
|
|
271
|
+
coordWithCallbacks.claimFile("/test.ts", "Testing");
|
|
272
|
+
|
|
273
|
+
expect(claims.length).toBe(1);
|
|
274
|
+
expect(claims[0]!.filePath).toBe("/test.ts");
|
|
275
|
+
|
|
276
|
+
coordWithCallbacks.shutdown();
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|