@sylix/coworker 1.3.0 → 1.3.1
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/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +145 -292
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/slash/advanced.d.ts +3 -0
- package/dist/commands/slash/advanced.d.ts.map +1 -0
- package/dist/commands/slash/advanced.js +225 -0
- package/dist/commands/slash/advanced.js.map +1 -0
- package/dist/commands/slash/config.d.ts +3 -0
- package/dist/commands/slash/config.d.ts.map +1 -0
- package/dist/commands/slash/config.js +161 -0
- package/dist/commands/slash/config.js.map +1 -0
- package/dist/commands/slash/context.d.ts +3 -0
- package/dist/commands/slash/context.d.ts.map +1 -0
- package/dist/commands/slash/context.js +127 -0
- package/dist/commands/slash/context.js.map +1 -0
- package/dist/commands/slash/core.d.ts +3 -0
- package/dist/commands/slash/core.d.ts.map +1 -0
- package/dist/commands/slash/core.js +112 -0
- package/dist/commands/slash/core.js.map +1 -0
- package/dist/commands/slash/developer.d.ts +3 -0
- package/dist/commands/slash/developer.d.ts.map +1 -0
- package/dist/commands/slash/developer.js +174 -0
- package/dist/commands/slash/developer.js.map +1 -0
- package/dist/commands/slash/files.d.ts +3 -0
- package/dist/commands/slash/files.d.ts.map +1 -0
- package/dist/commands/slash/files.js +216 -0
- package/dist/commands/slash/files.js.map +1 -0
- package/dist/commands/slash/registry.d.ts +36 -0
- package/dist/commands/slash/registry.d.ts.map +1 -0
- package/dist/commands/slash/registry.js +69 -0
- package/dist/commands/slash/registry.js.map +1 -0
- package/dist/commands/slash/session.d.ts +3 -0
- package/dist/commands/slash/session.d.ts.map +1 -0
- package/dist/commands/slash/session.js +144 -0
- package/dist/commands/slash/session.js.map +1 -0
- package/dist/core/CoWorkerAgent.d.ts +8 -3
- package/dist/core/CoWorkerAgent.d.ts.map +1 -1
- package/dist/core/CoWorkerAgent.js +99 -32
- package/dist/core/CoWorkerAgent.js.map +1 -1
- package/dist/session/SessionManager.js +10 -5
- package/dist/session/SessionManager.js.map +1 -1
- package/dist/skills/HookAndSkillManager.js +2 -1
- package/dist/skills/HookAndSkillManager.js.map +1 -1
- package/dist/utils/conversations.d.ts +14 -0
- package/dist/utils/conversations.d.ts.map +1 -0
- package/dist/utils/conversations.js +100 -0
- package/dist/utils/conversations.js.map +1 -0
- package/dist/utils/inputbar.d.ts +87 -0
- package/dist/utils/inputbar.d.ts.map +1 -0
- package/dist/utils/inputbar.js +263 -0
- package/dist/utils/inputbar.js.map +1 -0
- package/dist/utils/output.d.ts +48 -42
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +233 -186
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/palette.d.ts +25 -0
- package/dist/utils/palette.d.ts.map +1 -0
- package/dist/utils/palette.js +92 -0
- package/dist/utils/palette.js.map +1 -0
- package/dist/utils/welcome.d.ts +2 -0
- package/dist/utils/welcome.d.ts.map +1 -0
- package/dist/utils/welcome.js +130 -0
- package/dist/utils/welcome.js.map +1 -0
- package/package.json +1 -1
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AA0PA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkKvD"}
|
package/dist/cli/index.js
CHANGED
|
@@ -40,18 +40,20 @@ const AuthManager_1 = require("../config/AuthManager");
|
|
|
40
40
|
const child_process_1 = require("child_process");
|
|
41
41
|
const http = __importStar(require("http"));
|
|
42
42
|
const ws_1 = require("ws");
|
|
43
|
-
const readline = __importStar(require("readline"));
|
|
44
43
|
const fs = __importStar(require("fs"));
|
|
45
44
|
const path = __importStar(require("path"));
|
|
46
45
|
const os = __importStar(require("os"));
|
|
47
46
|
const output_1 = require("../utils/output");
|
|
47
|
+
const welcome_1 = require("../utils/welcome");
|
|
48
|
+
const palette_1 = require("../utils/palette");
|
|
49
|
+
const inputbar_1 = require("../utils/inputbar");
|
|
50
|
+
const registry_1 = require("../commands/slash/registry");
|
|
51
|
+
const conversations_1 = require("../utils/conversations");
|
|
48
52
|
/**
|
|
49
|
-
* CoWorker CLI v1.3.0 —
|
|
50
|
-
* Premium interactive REPL with animated UI, /review, /commit,
|
|
51
|
-
* history, slash command autocomplete, markdown-aware rendering.
|
|
53
|
+
* CoWorker CLI v1.3.0 — Premium Input Bar + Full Slash Commands
|
|
52
54
|
*/
|
|
53
55
|
// ============================================================================
|
|
54
|
-
// COMMAND HISTORY
|
|
56
|
+
// COMMAND HISTORY
|
|
55
57
|
// ============================================================================
|
|
56
58
|
const HISTORY_PATH = path.join(os.homedir(), '.coworker', 'history.json');
|
|
57
59
|
const MAX_HISTORY = 100;
|
|
@@ -62,224 +64,66 @@ function loadHistory() {
|
|
|
62
64
|
return Array.isArray(data) ? data.slice(-MAX_HISTORY) : [];
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
|
-
catch {
|
|
67
|
+
catch { }
|
|
66
68
|
return [];
|
|
67
69
|
}
|
|
68
70
|
function saveHistory(history) {
|
|
69
71
|
try {
|
|
70
72
|
const dir = path.dirname(HISTORY_PATH);
|
|
71
|
-
if (!fs.existsSync(dir))
|
|
73
|
+
if (!fs.existsSync(dir))
|
|
72
74
|
fs.mkdirSync(dir, { recursive: true });
|
|
73
|
-
}
|
|
74
75
|
fs.writeFileSync(HISTORY_PATH, JSON.stringify(history.slice(-MAX_HISTORY), null, 2));
|
|
75
76
|
}
|
|
76
|
-
catch {
|
|
77
|
-
}
|
|
78
|
-
// ============================================================================
|
|
79
|
-
// /REVIEW COMMAND — Code review with score cards
|
|
80
|
-
// ============================================================================
|
|
81
|
-
async function handleReviewCommand(agent, arg) {
|
|
82
|
-
// If arg is a file path, review that file; otherwise review the branch
|
|
83
|
-
const thinking = new output_1.ThinkingAnimation('reviewing');
|
|
84
|
-
thinking.start();
|
|
85
|
-
try {
|
|
86
|
-
if (arg) {
|
|
87
|
-
// Review a specific file
|
|
88
|
-
const filePath = path.resolve(arg);
|
|
89
|
-
if (!fs.existsSync(filePath)) {
|
|
90
|
-
thinking.stop();
|
|
91
|
-
(0, output_1.printError)('File not found', filePath);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
95
|
-
const prompt = `Do a thorough code review of this file. Score quality, security, performance, readability each out of 10. List bugs, improvements, and critical issues.\n\nFile: ${arg}\n\`\`\`\n${content.substring(0, 8000)}\n\`\`\``;
|
|
96
|
-
const startTime = Date.now();
|
|
97
|
-
let responseText = '';
|
|
98
|
-
let headerPrinted = false;
|
|
99
|
-
for await (const chunk of agent.chat(prompt)) {
|
|
100
|
-
if (!headerPrinted) {
|
|
101
|
-
thinking.stop();
|
|
102
|
-
(0, output_1.printResponseHeader)();
|
|
103
|
-
headerPrinted = true;
|
|
104
|
-
}
|
|
105
|
-
(0, output_1.streamResponseChunk)(chunk);
|
|
106
|
-
responseText += chunk;
|
|
107
|
-
}
|
|
108
|
-
if (!headerPrinted)
|
|
109
|
-
thinking.stop();
|
|
110
|
-
const elapsed = Date.now() - startTime;
|
|
111
|
-
if (headerPrinted) {
|
|
112
|
-
console.log('');
|
|
113
|
-
(0, output_1.printResponseFooter)(elapsed, Math.ceil(responseText.length / 4));
|
|
114
|
-
}
|
|
115
|
-
// Try to parse scores from response
|
|
116
|
-
const scores = parseScores(responseText);
|
|
117
|
-
if (scores.length > 0) {
|
|
118
|
-
(0, output_1.printScoreCard)(arg, scores);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
// Review the entire branch using CodeReviewEngine
|
|
123
|
-
thinking.stop();
|
|
124
|
-
const { CodeReviewEngine } = await Promise.resolve().then(() => __importStar(require('../review/CodeReviewEngine')));
|
|
125
|
-
const engine = new CodeReviewEngine();
|
|
126
|
-
const result = await engine.review();
|
|
127
|
-
console.log(CodeReviewEngine.formatForTerminal(result));
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
thinking.stop();
|
|
132
|
-
(0, output_1.printError)('Review failed', err.message);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
function parseScores(text) {
|
|
136
|
-
const scores = [];
|
|
137
|
-
const patterns = [
|
|
138
|
-
{ label: 'quality', regex: /quality[:\s]*(\d+)/i },
|
|
139
|
-
{ label: 'security', regex: /security[:\s]*(\d+)/i },
|
|
140
|
-
{ label: 'performance', regex: /performance[:\s]*(\d+)/i },
|
|
141
|
-
{ label: 'readability', regex: /readability[:\s]*(\d+)/i },
|
|
142
|
-
];
|
|
143
|
-
for (const { label, regex } of patterns) {
|
|
144
|
-
const match = text.match(regex);
|
|
145
|
-
if (match) {
|
|
146
|
-
scores.push({ label, score: Math.min(10, parseInt(match[1], 10)) });
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return scores;
|
|
150
|
-
}
|
|
151
|
-
// ============================================================================
|
|
152
|
-
// /COMMIT COMMAND — AI-generated commit messages
|
|
153
|
-
// ============================================================================
|
|
154
|
-
async function handleCommitCommand(agent) {
|
|
155
|
-
const thinking = new output_1.ThinkingAnimation('analyzing changes');
|
|
156
|
-
thinking.start();
|
|
157
|
-
try {
|
|
158
|
-
// Get the diff
|
|
159
|
-
let diff = '';
|
|
160
|
-
try {
|
|
161
|
-
diff = (0, child_process_1.execSync)('git diff --staged', { encoding: 'utf8', maxBuffer: 1024 * 1024 * 5 }).trim();
|
|
162
|
-
}
|
|
163
|
-
catch { /* no staged changes */ }
|
|
164
|
-
if (!diff) {
|
|
165
|
-
try {
|
|
166
|
-
diff = (0, child_process_1.execSync)('git diff HEAD', { encoding: 'utf8', maxBuffer: 1024 * 1024 * 5 }).trim();
|
|
167
|
-
}
|
|
168
|
-
catch { /* no changes */ }
|
|
169
|
-
}
|
|
170
|
-
if (!diff) {
|
|
171
|
-
thinking.stop();
|
|
172
|
-
(0, output_1.printError)('No changes to commit', 'Stage files with git add, or make changes first.');
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
// Send to AI for commit message generation
|
|
176
|
-
const prompt = `Generate a conventional commit message for this diff. Format: type(scope): description\nTypes: feat/fix/refactor/docs/style/test/chore. Be concise, one line only.\n\nDiff:\n${diff.substring(0, 6000)}`;
|
|
177
|
-
let commitMessage = '';
|
|
178
|
-
for await (const chunk of agent.chat(prompt)) {
|
|
179
|
-
if (!commitMessage)
|
|
180
|
-
thinking.stop();
|
|
181
|
-
commitMessage += chunk;
|
|
182
|
-
}
|
|
183
|
-
// Clean up the message — extract the actual commit line
|
|
184
|
-
commitMessage = commitMessage
|
|
185
|
-
.split('\n')
|
|
186
|
-
.find(line => /^(feat|fix|refactor|docs|style|test|chore|build|ci|perf)\(/.test(line.trim()))
|
|
187
|
-
|| commitMessage.split('\n')[0];
|
|
188
|
-
commitMessage = commitMessage.replace(/^[`'"]+|[`'"]+$/g, '').trim();
|
|
189
|
-
// Show commit box
|
|
190
|
-
(0, output_1.printCommitBox)(commitMessage);
|
|
191
|
-
// Ask user to confirm
|
|
192
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
193
|
-
const answer = await new Promise((resolve) => {
|
|
194
|
-
rl.question(` ${output_1.theme.dim('use this commit?')} ${output_1.theme.brand('›')} `, (a) => {
|
|
195
|
-
resolve(a.trim().toLowerCase());
|
|
196
|
-
rl.close();
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
if (answer === 'y' || answer === 'yes') {
|
|
200
|
-
try {
|
|
201
|
-
// Stage all if nothing was staged
|
|
202
|
-
try {
|
|
203
|
-
const stagedCheck = (0, child_process_1.execSync)('git diff --staged --name-only', { encoding: 'utf8' }).trim();
|
|
204
|
-
if (!stagedCheck) {
|
|
205
|
-
(0, child_process_1.execSync)('git add -A', { encoding: 'utf8' });
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
catch { /* ignore */ }
|
|
209
|
-
(0, child_process_1.execSync)(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { encoding: 'utf8' });
|
|
210
|
-
(0, output_1.printSuccess)('Committed successfully');
|
|
211
|
-
}
|
|
212
|
-
catch (e) {
|
|
213
|
-
(0, output_1.printError)('Commit failed', e.stderr?.toString() || e.message);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
else if (answer === 'n' || answer === 'no') {
|
|
217
|
-
const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
218
|
-
const customMsg = await new Promise((resolve) => {
|
|
219
|
-
rl2.question(` ${output_1.theme.dim('edit message?')} ${output_1.theme.brand('›')} `, (a) => {
|
|
220
|
-
resolve(a.trim());
|
|
221
|
-
rl2.close();
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
if (customMsg) {
|
|
225
|
-
try {
|
|
226
|
-
try {
|
|
227
|
-
const stagedCheck = (0, child_process_1.execSync)('git diff --staged --name-only', { encoding: 'utf8' }).trim();
|
|
228
|
-
if (!stagedCheck)
|
|
229
|
-
(0, child_process_1.execSync)('git add -A', { encoding: 'utf8' });
|
|
230
|
-
}
|
|
231
|
-
catch { /* */ }
|
|
232
|
-
(0, child_process_1.execSync)(`git commit -m "${customMsg.replace(/"/g, '\\"')}"`, { encoding: 'utf8' });
|
|
233
|
-
(0, output_1.printSuccess)('Committed successfully');
|
|
234
|
-
}
|
|
235
|
-
catch (e) {
|
|
236
|
-
(0, output_1.printError)('Commit failed', e.stderr?.toString() || e.message);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
catch (err) {
|
|
242
|
-
thinking.stop();
|
|
243
|
-
(0, output_1.printError)('Commit command failed', err.message);
|
|
244
|
-
}
|
|
77
|
+
catch { }
|
|
245
78
|
}
|
|
246
79
|
// ============================================================================
|
|
247
|
-
// INTERACTIVE CHAT REPL — Premium
|
|
80
|
+
// INTERACTIVE CHAT REPL — Premium framed input bar
|
|
248
81
|
// ============================================================================
|
|
249
82
|
async function runInteractiveChat(agent, opts) {
|
|
250
83
|
const history = loadHistory();
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
historySize: MAX_HISTORY,
|
|
257
|
-
});
|
|
258
|
-
// Graceful exit
|
|
84
|
+
const sessionStartTime = Date.now();
|
|
85
|
+
let firstUserMessage = '';
|
|
86
|
+
const inputBar = new inputbar_1.InputBarManager();
|
|
87
|
+
// Set global command context
|
|
88
|
+
(0, registry_1.setCommandContext)({ agent, startTime: sessionStartTime });
|
|
259
89
|
process.on('SIGINT', () => {
|
|
260
90
|
saveHistory(history);
|
|
91
|
+
if (firstUserMessage) {
|
|
92
|
+
(0, conversations_1.updateConversation)(agent.sessions.currentSessionId, {
|
|
93
|
+
messageCount: agent.sessions.state.messages.length,
|
|
94
|
+
lastActive: new Date().toISOString(),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
inputBar.destroy();
|
|
261
98
|
(0, output_1.printExit)();
|
|
262
|
-
rl.close();
|
|
263
99
|
process.exit(0);
|
|
264
100
|
});
|
|
265
|
-
//
|
|
266
|
-
|
|
101
|
+
// Register conversation
|
|
102
|
+
(0, conversations_1.addConversation)({
|
|
103
|
+
id: agent.sessions.currentSessionId,
|
|
104
|
+
name: 'new session',
|
|
105
|
+
startedAt: new Date().toISOString(),
|
|
106
|
+
lastActive: new Date().toISOString(),
|
|
107
|
+
cwd: process.cwd(),
|
|
108
|
+
messageCount: 0,
|
|
109
|
+
});
|
|
110
|
+
// Show welcome screen or banner
|
|
111
|
+
if (!opts.skipBanner && !opts.skipWelcome) {
|
|
112
|
+
const token = await AuthManager_1.AuthManager.getToken();
|
|
113
|
+
const authData = token ? await AuthManager_1.AuthManager.loadAuthPublic() : null;
|
|
114
|
+
(0, welcome_1.showWelcomeScreen)(authData?.user?.email, opts.model, process.cwd());
|
|
115
|
+
}
|
|
116
|
+
else if (!opts.skipBanner) {
|
|
267
117
|
const token = await AuthManager_1.AuthManager.getToken();
|
|
268
118
|
const authData = token ? await AuthManager_1.AuthManager.loadAuthPublic() : null;
|
|
269
119
|
await (0, output_1.showBanner)(output_1.CW_VERSION, authData?.user?.email, opts.model);
|
|
120
|
+
await (0, output_1.showSessionInfo)(process.cwd(), agent.sessions.currentSessionId);
|
|
270
121
|
}
|
|
271
|
-
// Session info with delay
|
|
272
|
-
await (0, output_1.showSessionInfo)(process.cwd(), agent.sessions.currentSessionId);
|
|
273
|
-
const askPrompt = () => {
|
|
274
|
-
return new Promise((resolve) => {
|
|
275
|
-
rl.question(` ${output_1.theme.dim('you')} ${output_1.theme.brand('›')} `, (answer) => {
|
|
276
|
-
resolve(answer.trim());
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
};
|
|
280
122
|
// Main REPL loop
|
|
281
123
|
while (true) {
|
|
282
|
-
|
|
124
|
+
// ── Draw framed input bar and get user input ──
|
|
125
|
+
(0, inputbar_1.drawTopBorder)();
|
|
126
|
+
const input = await inputBar.ask(history);
|
|
283
127
|
if (!input)
|
|
284
128
|
continue;
|
|
285
129
|
// Save to history
|
|
@@ -287,59 +131,64 @@ async function runInteractiveChat(agent, opts) {
|
|
|
287
131
|
if (history.length > MAX_HISTORY)
|
|
288
132
|
history.shift();
|
|
289
133
|
saveHistory(history);
|
|
290
|
-
//
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
(0,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
if (input === '/clear') {
|
|
297
|
-
console.clear();
|
|
298
|
-
(0, output_1.showStaticBanner)(output_1.CW_VERSION);
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
if (input === '/status') {
|
|
302
|
-
await AuthManager_1.AuthManager.status();
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
if (input === '/help') {
|
|
306
|
-
(0, output_1.printHelp)();
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
if (input === '/compact') {
|
|
310
|
-
const msgCount = agent.sessions.state.messages.length;
|
|
311
|
-
const totalChars = agent.sessions.state.messages.reduce((a, m) => a + (m.content?.length || 0), 0);
|
|
312
|
-
(0, output_1.printCompact)(msgCount, Math.ceil(totalChars / 4), agent.sessions.currentSessionId);
|
|
313
|
-
continue;
|
|
134
|
+
// Track first user message for conversation naming
|
|
135
|
+
if (!firstUserMessage) {
|
|
136
|
+
firstUserMessage = input;
|
|
137
|
+
(0, conversations_1.updateConversation)(agent.sessions.currentSessionId, {
|
|
138
|
+
name: (0, conversations_1.autoNameConversation)(input),
|
|
139
|
+
});
|
|
314
140
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
141
|
+
// ── "/" alone → show palette ──
|
|
142
|
+
if (input === '/') {
|
|
143
|
+
(0, palette_1.printStaticPalette)();
|
|
318
144
|
continue;
|
|
319
145
|
}
|
|
320
|
-
|
|
321
|
-
|
|
146
|
+
// ── Slash commands → route through registry ──
|
|
147
|
+
if (input.startsWith('/')) {
|
|
148
|
+
const cmdName = input.slice(1).split(' ')[0];
|
|
149
|
+
const cmdArgs = input.slice(1 + cmdName.length).trim() || undefined;
|
|
150
|
+
const cmd = (0, registry_1.resolveCommand)(input);
|
|
151
|
+
if (cmd) {
|
|
152
|
+
try {
|
|
153
|
+
await cmd.handler(agent, cmdArgs);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
(0, output_1.printError)(`/${cmd.name} failed`, err.message);
|
|
157
|
+
}
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
// Unknown command — suggest closest
|
|
161
|
+
const suggestions = (0, registry_1.filterCommands)(cmdName);
|
|
162
|
+
if (suggestions.length > 0) {
|
|
163
|
+
console.log(output_1.theme.dim(` Unknown command. Did you mean:`));
|
|
164
|
+
for (const s of suggestions.slice(0, 3)) {
|
|
165
|
+
console.log(` ${output_1.theme.brand(`/${s.name}`)} ${output_1.theme.dim(s.description)}`);
|
|
166
|
+
}
|
|
167
|
+
console.log('');
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
console.log(output_1.theme.dim(` Unknown command. Type / for all commands.`));
|
|
171
|
+
console.log('');
|
|
172
|
+
}
|
|
322
173
|
continue;
|
|
323
174
|
}
|
|
324
|
-
// ──
|
|
325
|
-
|
|
326
|
-
|
|
175
|
+
// ── Regular chat message ──
|
|
176
|
+
// Update status to "sending"
|
|
177
|
+
inputBar.showSending(input);
|
|
178
|
+
// Thinking animation
|
|
327
179
|
const thinking = new output_1.ThinkingAnimation();
|
|
328
180
|
thinking.start();
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
let
|
|
181
|
+
// Stream the AI response
|
|
182
|
+
const renderer = new output_1.StreamRenderer();
|
|
183
|
+
let hasContent = false;
|
|
332
184
|
try {
|
|
333
185
|
for await (const chunk of agent.chat(input)) {
|
|
334
|
-
|
|
335
|
-
if (!headerPrinted) {
|
|
186
|
+
if (!hasContent) {
|
|
336
187
|
thinking.stop();
|
|
337
|
-
|
|
338
|
-
|
|
188
|
+
inputBar.showReceiving();
|
|
189
|
+
hasContent = true;
|
|
339
190
|
}
|
|
340
|
-
|
|
341
|
-
(0, output_1.streamResponseChunk)(chunk);
|
|
342
|
-
responseText += chunk;
|
|
191
|
+
renderer.write(chunk);
|
|
343
192
|
}
|
|
344
193
|
}
|
|
345
194
|
catch (err) {
|
|
@@ -347,19 +196,17 @@ async function runInteractiveChat(agent, opts) {
|
|
|
347
196
|
(0, output_1.printError)(`Error: ${err.message}`, undefined, 'Check your network connection or try again');
|
|
348
197
|
continue;
|
|
349
198
|
}
|
|
350
|
-
if (!
|
|
199
|
+
if (!hasContent)
|
|
351
200
|
thinking.stop();
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
201
|
+
renderer.finish();
|
|
202
|
+
// Show success briefly, then reset
|
|
203
|
+
inputBar.showSuccess();
|
|
204
|
+
inputBar.reset();
|
|
205
|
+
// Update conversation message count
|
|
206
|
+
(0, conversations_1.updateConversation)(agent.sessions.currentSessionId, {
|
|
207
|
+
messageCount: agent.sessions.state.messages.length,
|
|
208
|
+
});
|
|
360
209
|
}
|
|
361
|
-
rl.close();
|
|
362
|
-
process.exit(0);
|
|
363
210
|
}
|
|
364
211
|
// ============================================================================
|
|
365
212
|
// ONE-SHOT MODE
|
|
@@ -371,19 +218,19 @@ async function runOneShot(agent, prompt, format) {
|
|
|
371
218
|
process.stdout.write(chunk);
|
|
372
219
|
outputText += chunk;
|
|
373
220
|
}
|
|
374
|
-
if (format === 'json')
|
|
221
|
+
if (format === 'json')
|
|
375
222
|
console.log(JSON.stringify({ response: outputText }));
|
|
376
|
-
}
|
|
377
223
|
process.exit(0);
|
|
378
224
|
}
|
|
379
225
|
// ============================================================================
|
|
380
|
-
// HEADLESS
|
|
226
|
+
// HEADLESS SERVER
|
|
381
227
|
// ============================================================================
|
|
382
228
|
function startHeadlessServer(port) {
|
|
383
229
|
const server = http.createServer();
|
|
384
230
|
const wss = new ws_1.WebSocketServer({ server });
|
|
385
231
|
wss.on('connection', (ws) => {
|
|
386
|
-
|
|
232
|
+
if (process.env.CW_VERBOSE)
|
|
233
|
+
console.log('[Remote-Control] IDE Connected');
|
|
387
234
|
const remoteAgent = new CoWorkerAgent_1.CoWorkerAgent({ model: 'helix-1.2', role: 'General' });
|
|
388
235
|
ws.on('message', async (data) => {
|
|
389
236
|
const { prompt, sessionId } = JSON.parse(data.toString());
|
|
@@ -395,12 +242,10 @@ function startHeadlessServer(port) {
|
|
|
395
242
|
ws.send(JSON.stringify({ type: 'done' }));
|
|
396
243
|
});
|
|
397
244
|
});
|
|
398
|
-
server.listen(port, () => {
|
|
399
|
-
console.log(`[Remote-Control] Listening on port ${port}...`);
|
|
400
|
-
});
|
|
245
|
+
server.listen(port, () => console.log(`[Remote-Control] Listening on port ${port}...`));
|
|
401
246
|
}
|
|
402
247
|
// ============================================================================
|
|
403
|
-
// CLI MAIN
|
|
248
|
+
// CLI MAIN
|
|
404
249
|
// ============================================================================
|
|
405
250
|
async function bootstrapCoWorker() {
|
|
406
251
|
const args = process.argv.slice(2);
|
|
@@ -437,6 +282,8 @@ async function bootstrapCoWorker() {
|
|
|
437
282
|
console.log(` ${output_1.theme.code('status')} ${output_1.theme.dim('Show auth & account status')}`);
|
|
438
283
|
console.log(` ${output_1.theme.code('review [file]')} ${output_1.theme.dim('Code review a file or current branch')}`);
|
|
439
284
|
console.log(` ${output_1.theme.code('commit')} ${output_1.theme.dim('AI-generated conventional commit')}`);
|
|
285
|
+
console.log(` ${output_1.theme.code('doctor')} ${output_1.theme.dim('Diagnose installation')}`);
|
|
286
|
+
console.log(` ${output_1.theme.code('init')} ${output_1.theme.dim('Create .coworker.md')}`);
|
|
440
287
|
console.log(` ${output_1.theme.code('update')} ${output_1.theme.dim('Auto-update the CoWorker CLI')}\n`);
|
|
441
288
|
console.log(` ${output_1.theme.brand('Options:')}`);
|
|
442
289
|
console.log(` ${output_1.theme.code('-p, --print')} ${output_1.theme.dim('One-shot mode (process and exit)')}`);
|
|
@@ -446,9 +293,15 @@ async function bootstrapCoWorker() {
|
|
|
446
293
|
console.log(` ${output_1.theme.code('--model <name>')} ${output_1.theme.dim('Override model (default: helix-1.2)')}`);
|
|
447
294
|
console.log(` ${output_1.theme.code('--dangerously-skip-permissions')} ${output_1.theme.dim('Bypass all security policies')}`);
|
|
448
295
|
console.log(` ${output_1.theme.code('--remote-control <port>')} ${output_1.theme.dim('Start WebSocket server for IDE')}`);
|
|
449
|
-
console.log(` ${output_1.theme.code('--no-banner')} ${output_1.theme.dim('Skip the
|
|
296
|
+
console.log(` ${output_1.theme.code('--no-banner')} ${output_1.theme.dim('Skip the startup screen')}`);
|
|
450
297
|
console.log(` ${output_1.theme.code('-V, --version')} ${output_1.theme.dim('Output version number')}`);
|
|
451
298
|
console.log(` ${output_1.theme.code('-h, --help')} ${output_1.theme.dim('Display help')}\n`);
|
|
299
|
+
console.log(` ${output_1.theme.brand('Slash Commands (in REPL):')}`);
|
|
300
|
+
for (const cmd of registry_1.COMMANDS.slice(0, 10)) {
|
|
301
|
+
const pad = ' '.repeat(Math.max(1, 20 - cmd.name.length));
|
|
302
|
+
console.log(` ${output_1.theme.code(`/${cmd.name}`)}${pad}${output_1.theme.dim(cmd.description)}`);
|
|
303
|
+
}
|
|
304
|
+
console.log(` ${output_1.theme.dim(`... and ${registry_1.COMMANDS.length - 10} more. Type / in REPL for full list.`)}\n`);
|
|
452
305
|
return;
|
|
453
306
|
}
|
|
454
307
|
// ── Parse flags ──
|
|
@@ -511,9 +364,16 @@ async function bootstrapCoWorker() {
|
|
|
511
364
|
return;
|
|
512
365
|
}
|
|
513
366
|
}
|
|
367
|
+
// ── Workspace Trust Check ──
|
|
368
|
+
const cwd = process.cwd();
|
|
369
|
+
const trusted = await (0, output_1.checkWorkspaceTrust)(cwd);
|
|
370
|
+
if (!trusted) {
|
|
371
|
+
console.log(output_1.theme.dim('\n Exiting — workspace not trusted.\n'));
|
|
372
|
+
process.exit(0);
|
|
373
|
+
}
|
|
514
374
|
// ── Worktree isolation ──
|
|
515
375
|
if (worktree) {
|
|
516
|
-
console.log(output_1.theme.dim('
|
|
376
|
+
console.log(output_1.theme.dim(' Creating Git Worktree...'));
|
|
517
377
|
try {
|
|
518
378
|
(0, child_process_1.spawnSync)('git', ['worktree', 'add', '../coworker-task', '-b', `coworker/temp-${Date.now()}`]);
|
|
519
379
|
process.chdir('../coworker-task');
|
|
@@ -531,22 +391,19 @@ async function bootstrapCoWorker() {
|
|
|
531
391
|
}
|
|
532
392
|
// ── Boot agent ──
|
|
533
393
|
const agent = new CoWorkerAgent_1.CoWorkerAgent({ model, role: 'General' });
|
|
534
|
-
if (resumeSession)
|
|
394
|
+
if (resumeSession)
|
|
535
395
|
agent.sessions.currentSessionId = resumeSession;
|
|
536
|
-
}
|
|
537
396
|
await agent.boot();
|
|
538
397
|
if (skipPermissions) {
|
|
539
398
|
console.log(output_1.theme.error(' ⚠️ WARNING: All permission checks are DISABLED.'));
|
|
540
399
|
agent.permissions = { intercept: async () => true };
|
|
541
400
|
}
|
|
542
|
-
// ──
|
|
543
|
-
if (command === 'review') {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (command === 'commit') {
|
|
549
|
-
await handleCommitCommand(agent);
|
|
401
|
+
// ── Direct subcommands ──
|
|
402
|
+
if (command === 'review' || command === 'commit' || command === 'doctor' || command === 'init') {
|
|
403
|
+
(0, registry_1.setCommandContext)({ agent, startTime: Date.now() });
|
|
404
|
+
const cmd = (0, registry_1.resolveCommand)(`/${command}`);
|
|
405
|
+
if (cmd)
|
|
406
|
+
await cmd.handler(agent, args[1]);
|
|
550
407
|
process.exit(0);
|
|
551
408
|
}
|
|
552
409
|
// ── Execute ──
|
|
@@ -555,43 +412,39 @@ async function bootstrapCoWorker() {
|
|
|
555
412
|
await runOneShot(agent, initialPrompt, outputFormat);
|
|
556
413
|
}
|
|
557
414
|
else if (initialPrompt) {
|
|
558
|
-
//
|
|
415
|
+
// Show welcome, run initial prompt, then drop into REPL
|
|
559
416
|
if (!noBanner) {
|
|
560
417
|
const token = await AuthManager_1.AuthManager.getToken();
|
|
561
418
|
const authData = token ? await AuthManager_1.AuthManager.loadAuthPublic() : null;
|
|
562
|
-
|
|
419
|
+
(0, welcome_1.showWelcomeScreen)(authData?.user?.email, model, process.cwd());
|
|
563
420
|
}
|
|
564
|
-
|
|
421
|
+
// Run the initial prompt with framed display
|
|
422
|
+
(0, inputbar_1.drawTopBorder)();
|
|
423
|
+
console.log(output_1.theme.brand(' ◆ ') + output_1.theme.white(initialPrompt));
|
|
424
|
+
(0, inputbar_1.drawBottomBorder)();
|
|
425
|
+
(0, inputbar_1.drawStatusLine)('sending');
|
|
565
426
|
const thinking = new output_1.ThinkingAnimation();
|
|
566
427
|
thinking.start();
|
|
567
|
-
const
|
|
568
|
-
let
|
|
569
|
-
let headerPrinted = false;
|
|
428
|
+
const renderer = new output_1.StreamRenderer();
|
|
429
|
+
let hasContent = false;
|
|
570
430
|
for await (const chunk of agent.chat(initialPrompt)) {
|
|
571
|
-
if (!
|
|
431
|
+
if (!hasContent) {
|
|
572
432
|
thinking.stop();
|
|
573
|
-
|
|
574
|
-
headerPrinted = true;
|
|
433
|
+
hasContent = true;
|
|
575
434
|
}
|
|
576
|
-
|
|
577
|
-
responseText += chunk;
|
|
435
|
+
renderer.write(chunk);
|
|
578
436
|
}
|
|
579
|
-
if (!
|
|
437
|
+
if (!hasContent)
|
|
580
438
|
thinking.stop();
|
|
581
|
-
|
|
582
|
-
if (headerPrinted) {
|
|
583
|
-
console.log('');
|
|
584
|
-
(0, output_1.printResponseFooter)(elapsed, Math.ceil(responseText.length / 4));
|
|
585
|
-
}
|
|
439
|
+
renderer.finish();
|
|
586
440
|
console.log('');
|
|
587
|
-
await runInteractiveChat(agent, { model, skipBanner: true });
|
|
441
|
+
await runInteractiveChat(agent, { model, skipBanner: true, skipWelcome: true });
|
|
588
442
|
}
|
|
589
443
|
else {
|
|
590
|
-
// DEFAULT: No args → interactive
|
|
444
|
+
// DEFAULT: No args → interactive REPL
|
|
591
445
|
await runInteractiveChat(agent, { model, skipBanner: noBanner });
|
|
592
446
|
}
|
|
593
447
|
}
|
|
594
|
-
// Self-execute
|
|
595
448
|
if (require.main === module) {
|
|
596
449
|
bootstrapCoWorker();
|
|
597
450
|
}
|