@sylix/coworker 1.3.0 → 1.4.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.
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +184 -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 -5
- package/dist/core/CoWorkerAgent.d.ts.map +1 -1
- package/dist/core/CoWorkerAgent.js +171 -52
- 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.d.ts +7 -2
- package/dist/skills/HookAndSkillManager.d.ts.map +1 -1
- package/dist/skills/HookAndSkillManager.js +35 -8
- package/dist/skills/HookAndSkillManager.js.map +1 -1
- package/dist/skills/defaults/brainstorming.md +43 -0
- package/dist/skills/defaults/commit.md +37 -0
- package/dist/skills/defaults/executing-plans.md +41 -0
- package/dist/skills/defaults/finishing-a-development-branch.md +35 -0
- package/dist/skills/defaults/receiving-code-review.md +40 -0
- package/dist/skills/defaults/requesting-code-review.md +43 -0
- package/dist/skills/defaults/review.md +50 -0
- package/dist/skills/defaults/subagent-driven-development.md +55 -0
- package/dist/skills/defaults/systematic-debugging.md +93 -0
- package/dist/skills/defaults/test-driven-development.md +97 -0
- package/dist/skills/defaults/using-git-worktrees.md +36 -0
- package/dist/skills/defaults/verification-before-completion.md +47 -0
- package/dist/skills/defaults/writing-plans.md +84 -0
- package/dist/skills/defaults/writing-skills.md +46 -0
- package/dist/tools/NativeTools.d.ts +0 -4
- package/dist/tools/NativeTools.d.ts.map +1 -1
- package/dist/tools/NativeTools.js +50 -10
- package/dist/tools/NativeTools.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 +245 -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 +2 -2
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":";AAgSA,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
|
+
catch { }
|
|
77
78
|
}
|
|
78
79
|
// ============================================================================
|
|
79
|
-
//
|
|
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
|
-
}
|
|
245
|
-
}
|
|
246
|
-
// ============================================================================
|
|
247
|
-
// INTERACTIVE CHAT REPL — Premium v1.3.0
|
|
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,104 @@ 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
|
+
// ── Handle dynamic skills (Superpowers) ──
|
|
161
|
+
const skill = agent.hooks.loadedSkills.get(cmdName);
|
|
162
|
+
if (skill) {
|
|
163
|
+
agent.hooks.activateSkill(cmdName);
|
|
164
|
+
console.log(`\n ${output_1.theme.brand('◈')} ${output_1.theme.brand(`Activating ${skill.name}`)} superpower...`);
|
|
165
|
+
console.log(` ${output_1.theme.dim(skill.description)}`);
|
|
166
|
+
console.log('');
|
|
167
|
+
// Trigger an immediate agent response for the skill
|
|
168
|
+
const initialText = `I have activated the ${skill.name} superpower. How should we proceed?`;
|
|
169
|
+
console.log(` ${output_1.theme.dim('you')} ${output_1.theme.brand('\u203a')} ${output_1.theme.white(`[Skill Activation: ${skill.name}]`)}`);
|
|
170
|
+
console.log('');
|
|
171
|
+
const thinking = new output_1.ThinkingAnimation();
|
|
172
|
+
thinking.start();
|
|
173
|
+
const renderer = new output_1.StreamRenderer();
|
|
174
|
+
let hasContent = false;
|
|
175
|
+
try {
|
|
176
|
+
for await (const chunk of agent.chat(`I just activated the ${skill.name} skill. Please start the workflow.`)) {
|
|
177
|
+
if (!hasContent) {
|
|
178
|
+
thinking.stop();
|
|
179
|
+
hasContent = true;
|
|
180
|
+
}
|
|
181
|
+
renderer.write(chunk);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
thinking.stop();
|
|
186
|
+
(0, output_1.printError)(`Skill execution failed`, err.message);
|
|
187
|
+
}
|
|
188
|
+
if (!hasContent)
|
|
189
|
+
thinking.stop();
|
|
190
|
+
renderer.finish();
|
|
191
|
+
inputBar.reset();
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Unknown command — suggest closest
|
|
195
|
+
const suggestions = (0, registry_1.filterCommands)(cmdName);
|
|
196
|
+
if (suggestions.length > 0) {
|
|
197
|
+
console.log(output_1.theme.dim(` Unknown command. Did you mean:`));
|
|
198
|
+
for (const s of suggestions.slice(0, 3)) {
|
|
199
|
+
console.log(` ${output_1.theme.brand(`/${s.name}`)} ${output_1.theme.dim(s.description)}`);
|
|
200
|
+
}
|
|
201
|
+
console.log('');
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(output_1.theme.dim(` Unknown command. Type / for all commands.`));
|
|
205
|
+
console.log('');
|
|
206
|
+
}
|
|
322
207
|
continue;
|
|
323
208
|
}
|
|
324
|
-
// ──
|
|
325
|
-
(
|
|
326
|
-
//
|
|
209
|
+
// ── Regular chat message ──
|
|
210
|
+
// Clear the input frame drawn by ask() (bottom border + status)
|
|
211
|
+
process.stdout.write('\x1b[1A\x1b[2K'); // clear status line
|
|
212
|
+
process.stdout.write('\x1b[1A\x1b[2K'); // clear bottom border
|
|
213
|
+
process.stdout.write('\x1b[1A\x1b[2K'); // clear input line
|
|
214
|
+
process.stdout.write('\x1b[1A\x1b[2K'); // clear top border
|
|
215
|
+
// Show user message above
|
|
216
|
+
console.log('');
|
|
217
|
+
console.log(` ${output_1.theme.dim('you')} ${output_1.theme.brand('\u203a')} ${input}`);
|
|
218
|
+
console.log('');
|
|
219
|
+
// Thinking animation
|
|
327
220
|
const thinking = new output_1.ThinkingAnimation();
|
|
328
221
|
thinking.start();
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
let
|
|
222
|
+
// Stream the AI response
|
|
223
|
+
const renderer = new output_1.StreamRenderer();
|
|
224
|
+
let hasContent = false;
|
|
332
225
|
try {
|
|
333
226
|
for await (const chunk of agent.chat(input)) {
|
|
334
|
-
|
|
335
|
-
if (!headerPrinted) {
|
|
227
|
+
if (!hasContent) {
|
|
336
228
|
thinking.stop();
|
|
337
|
-
|
|
338
|
-
headerPrinted = true;
|
|
229
|
+
hasContent = true;
|
|
339
230
|
}
|
|
340
|
-
|
|
341
|
-
(0, output_1.streamResponseChunk)(chunk);
|
|
342
|
-
responseText += chunk;
|
|
231
|
+
renderer.write(chunk);
|
|
343
232
|
}
|
|
344
233
|
}
|
|
345
234
|
catch (err) {
|
|
@@ -347,19 +236,16 @@ async function runInteractiveChat(agent, opts) {
|
|
|
347
236
|
(0, output_1.printError)(`Error: ${err.message}`, undefined, 'Check your network connection or try again');
|
|
348
237
|
continue;
|
|
349
238
|
}
|
|
350
|
-
if (!
|
|
239
|
+
if (!hasContent)
|
|
351
240
|
thinking.stop();
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
console.log('');
|
|
241
|
+
renderer.finish();
|
|
242
|
+
// Reset for next input (no "done" message — the ╵ footer is sufficient)
|
|
243
|
+
inputBar.reset();
|
|
244
|
+
// Update conversation message count
|
|
245
|
+
(0, conversations_1.updateConversation)(agent.sessions.currentSessionId, {
|
|
246
|
+
messageCount: agent.sessions.state.messages.length,
|
|
247
|
+
});
|
|
360
248
|
}
|
|
361
|
-
rl.close();
|
|
362
|
-
process.exit(0);
|
|
363
249
|
}
|
|
364
250
|
// ============================================================================
|
|
365
251
|
// ONE-SHOT MODE
|
|
@@ -371,19 +257,19 @@ async function runOneShot(agent, prompt, format) {
|
|
|
371
257
|
process.stdout.write(chunk);
|
|
372
258
|
outputText += chunk;
|
|
373
259
|
}
|
|
374
|
-
if (format === 'json')
|
|
260
|
+
if (format === 'json')
|
|
375
261
|
console.log(JSON.stringify({ response: outputText }));
|
|
376
|
-
}
|
|
377
262
|
process.exit(0);
|
|
378
263
|
}
|
|
379
264
|
// ============================================================================
|
|
380
|
-
// HEADLESS
|
|
265
|
+
// HEADLESS SERVER
|
|
381
266
|
// ============================================================================
|
|
382
267
|
function startHeadlessServer(port) {
|
|
383
268
|
const server = http.createServer();
|
|
384
269
|
const wss = new ws_1.WebSocketServer({ server });
|
|
385
270
|
wss.on('connection', (ws) => {
|
|
386
|
-
|
|
271
|
+
if (process.env.CW_VERBOSE)
|
|
272
|
+
console.log('[Remote-Control] IDE Connected');
|
|
387
273
|
const remoteAgent = new CoWorkerAgent_1.CoWorkerAgent({ model: 'helix-1.2', role: 'General' });
|
|
388
274
|
ws.on('message', async (data) => {
|
|
389
275
|
const { prompt, sessionId } = JSON.parse(data.toString());
|
|
@@ -395,12 +281,10 @@ function startHeadlessServer(port) {
|
|
|
395
281
|
ws.send(JSON.stringify({ type: 'done' }));
|
|
396
282
|
});
|
|
397
283
|
});
|
|
398
|
-
server.listen(port, () => {
|
|
399
|
-
console.log(`[Remote-Control] Listening on port ${port}...`);
|
|
400
|
-
});
|
|
284
|
+
server.listen(port, () => console.log(`[Remote-Control] Listening on port ${port}...`));
|
|
401
285
|
}
|
|
402
286
|
// ============================================================================
|
|
403
|
-
// CLI MAIN
|
|
287
|
+
// CLI MAIN
|
|
404
288
|
// ============================================================================
|
|
405
289
|
async function bootstrapCoWorker() {
|
|
406
290
|
const args = process.argv.slice(2);
|
|
@@ -437,6 +321,8 @@ async function bootstrapCoWorker() {
|
|
|
437
321
|
console.log(` ${output_1.theme.code('status')} ${output_1.theme.dim('Show auth & account status')}`);
|
|
438
322
|
console.log(` ${output_1.theme.code('review [file]')} ${output_1.theme.dim('Code review a file or current branch')}`);
|
|
439
323
|
console.log(` ${output_1.theme.code('commit')} ${output_1.theme.dim('AI-generated conventional commit')}`);
|
|
324
|
+
console.log(` ${output_1.theme.code('doctor')} ${output_1.theme.dim('Diagnose installation')}`);
|
|
325
|
+
console.log(` ${output_1.theme.code('init')} ${output_1.theme.dim('Create .coworker.md')}`);
|
|
440
326
|
console.log(` ${output_1.theme.code('update')} ${output_1.theme.dim('Auto-update the CoWorker CLI')}\n`);
|
|
441
327
|
console.log(` ${output_1.theme.brand('Options:')}`);
|
|
442
328
|
console.log(` ${output_1.theme.code('-p, --print')} ${output_1.theme.dim('One-shot mode (process and exit)')}`);
|
|
@@ -446,9 +332,15 @@ async function bootstrapCoWorker() {
|
|
|
446
332
|
console.log(` ${output_1.theme.code('--model <name>')} ${output_1.theme.dim('Override model (default: helix-1.2)')}`);
|
|
447
333
|
console.log(` ${output_1.theme.code('--dangerously-skip-permissions')} ${output_1.theme.dim('Bypass all security policies')}`);
|
|
448
334
|
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
|
|
335
|
+
console.log(` ${output_1.theme.code('--no-banner')} ${output_1.theme.dim('Skip the startup screen')}`);
|
|
450
336
|
console.log(` ${output_1.theme.code('-V, --version')} ${output_1.theme.dim('Output version number')}`);
|
|
451
337
|
console.log(` ${output_1.theme.code('-h, --help')} ${output_1.theme.dim('Display help')}\n`);
|
|
338
|
+
console.log(` ${output_1.theme.brand('Slash Commands (in REPL):')}`);
|
|
339
|
+
for (const cmd of registry_1.COMMANDS.slice(0, 10)) {
|
|
340
|
+
const pad = ' '.repeat(Math.max(1, 20 - cmd.name.length));
|
|
341
|
+
console.log(` ${output_1.theme.code(`/${cmd.name}`)}${pad}${output_1.theme.dim(cmd.description)}`);
|
|
342
|
+
}
|
|
343
|
+
console.log(` ${output_1.theme.dim(`... and ${registry_1.COMMANDS.length - 10} more. Type / in REPL for full list.`)}\n`);
|
|
452
344
|
return;
|
|
453
345
|
}
|
|
454
346
|
// ── Parse flags ──
|
|
@@ -511,9 +403,16 @@ async function bootstrapCoWorker() {
|
|
|
511
403
|
return;
|
|
512
404
|
}
|
|
513
405
|
}
|
|
406
|
+
// ── Workspace Trust Check ──
|
|
407
|
+
const cwd = process.cwd();
|
|
408
|
+
const trusted = await (0, output_1.checkWorkspaceTrust)(cwd);
|
|
409
|
+
if (!trusted) {
|
|
410
|
+
console.log(output_1.theme.dim('\n Exiting — workspace not trusted.\n'));
|
|
411
|
+
process.exit(0);
|
|
412
|
+
}
|
|
514
413
|
// ── Worktree isolation ──
|
|
515
414
|
if (worktree) {
|
|
516
|
-
console.log(output_1.theme.dim('
|
|
415
|
+
console.log(output_1.theme.dim(' Creating Git Worktree...'));
|
|
517
416
|
try {
|
|
518
417
|
(0, child_process_1.spawnSync)('git', ['worktree', 'add', '../coworker-task', '-b', `coworker/temp-${Date.now()}`]);
|
|
519
418
|
process.chdir('../coworker-task');
|
|
@@ -531,22 +430,19 @@ async function bootstrapCoWorker() {
|
|
|
531
430
|
}
|
|
532
431
|
// ── Boot agent ──
|
|
533
432
|
const agent = new CoWorkerAgent_1.CoWorkerAgent({ model, role: 'General' });
|
|
534
|
-
if (resumeSession)
|
|
433
|
+
if (resumeSession)
|
|
535
434
|
agent.sessions.currentSessionId = resumeSession;
|
|
536
|
-
}
|
|
537
435
|
await agent.boot();
|
|
538
436
|
if (skipPermissions) {
|
|
539
437
|
console.log(output_1.theme.error(' ⚠️ WARNING: All permission checks are DISABLED.'));
|
|
540
438
|
agent.permissions = { intercept: async () => true };
|
|
541
439
|
}
|
|
542
|
-
// ──
|
|
543
|
-
if (command === 'review') {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (command === 'commit') {
|
|
549
|
-
await handleCommitCommand(agent);
|
|
440
|
+
// ── Direct subcommands ──
|
|
441
|
+
if (command === 'review' || command === 'commit' || command === 'doctor' || command === 'init') {
|
|
442
|
+
(0, registry_1.setCommandContext)({ agent, startTime: Date.now() });
|
|
443
|
+
const cmd = (0, registry_1.resolveCommand)(`/${command}`);
|
|
444
|
+
if (cmd)
|
|
445
|
+
await cmd.handler(agent, args[1]);
|
|
550
446
|
process.exit(0);
|
|
551
447
|
}
|
|
552
448
|
// ── Execute ──
|
|
@@ -555,43 +451,39 @@ async function bootstrapCoWorker() {
|
|
|
555
451
|
await runOneShot(agent, initialPrompt, outputFormat);
|
|
556
452
|
}
|
|
557
453
|
else if (initialPrompt) {
|
|
558
|
-
//
|
|
454
|
+
// Show welcome, run initial prompt, then drop into REPL
|
|
559
455
|
if (!noBanner) {
|
|
560
456
|
const token = await AuthManager_1.AuthManager.getToken();
|
|
561
457
|
const authData = token ? await AuthManager_1.AuthManager.loadAuthPublic() : null;
|
|
562
|
-
|
|
458
|
+
(0, welcome_1.showWelcomeScreen)(authData?.user?.email, model, process.cwd());
|
|
563
459
|
}
|
|
564
|
-
|
|
460
|
+
// Run the initial prompt with framed display
|
|
461
|
+
(0, inputbar_1.drawTopBorder)();
|
|
462
|
+
console.log(output_1.theme.brand(' ◆ ') + output_1.theme.white(initialPrompt));
|
|
463
|
+
(0, inputbar_1.drawBottomBorder)();
|
|
464
|
+
(0, inputbar_1.drawStatusLine)('sending');
|
|
565
465
|
const thinking = new output_1.ThinkingAnimation();
|
|
566
466
|
thinking.start();
|
|
567
|
-
const
|
|
568
|
-
let
|
|
569
|
-
let headerPrinted = false;
|
|
467
|
+
const renderer = new output_1.StreamRenderer();
|
|
468
|
+
let hasContent = false;
|
|
570
469
|
for await (const chunk of agent.chat(initialPrompt)) {
|
|
571
|
-
if (!
|
|
470
|
+
if (!hasContent) {
|
|
572
471
|
thinking.stop();
|
|
573
|
-
|
|
574
|
-
headerPrinted = true;
|
|
472
|
+
hasContent = true;
|
|
575
473
|
}
|
|
576
|
-
|
|
577
|
-
responseText += chunk;
|
|
474
|
+
renderer.write(chunk);
|
|
578
475
|
}
|
|
579
|
-
if (!
|
|
476
|
+
if (!hasContent)
|
|
580
477
|
thinking.stop();
|
|
581
|
-
|
|
582
|
-
if (headerPrinted) {
|
|
583
|
-
console.log('');
|
|
584
|
-
(0, output_1.printResponseFooter)(elapsed, Math.ceil(responseText.length / 4));
|
|
585
|
-
}
|
|
478
|
+
renderer.finish();
|
|
586
479
|
console.log('');
|
|
587
|
-
await runInteractiveChat(agent, { model, skipBanner: true });
|
|
480
|
+
await runInteractiveChat(agent, { model, skipBanner: true, skipWelcome: true });
|
|
588
481
|
}
|
|
589
482
|
else {
|
|
590
|
-
// DEFAULT: No args → interactive
|
|
483
|
+
// DEFAULT: No args → interactive REPL
|
|
591
484
|
await runInteractiveChat(agent, { model, skipBanner: noBanner });
|
|
592
485
|
}
|
|
593
486
|
}
|
|
594
|
-
// Self-execute
|
|
595
487
|
if (require.main === module) {
|
|
596
488
|
bootstrapCoWorker();
|
|
597
489
|
}
|