@sylix/coworker 1.2.6 → 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 +181 -106
- 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 -2
- package/dist/core/CoWorkerAgent.d.ts.map +1 -1
- package/dist/core/CoWorkerAgent.js +179 -36
- package/dist/core/CoWorkerAgent.js.map +1 -1
- package/dist/review/CodeReviewEngine.d.ts +78 -0
- package/dist/review/CodeReviewEngine.d.ts.map +1 -0
- package/dist/review/CodeReviewEngine.js +449 -0
- package/dist/review/CodeReviewEngine.js.map +1 -0
- package/dist/session/SessionManager.js +10 -5
- package/dist/session/SessionManager.js.map +1 -1
- package/dist/skills/HookAndSkillManager.d.ts +29 -5
- package/dist/skills/HookAndSkillManager.d.ts.map +1 -1
- package/dist/skills/HookAndSkillManager.js +167 -12
- package/dist/skills/HookAndSkillManager.js.map +1 -1
- package/dist/todos/TodoManager.d.ts +19 -0
- package/dist/todos/TodoManager.d.ts.map +1 -0
- package/dist/todos/TodoManager.js +102 -0
- package/dist/todos/TodoManager.js.map +1 -0
- package/dist/tools/NativeTools.d.ts +98 -0
- package/dist/tools/NativeTools.d.ts.map +1 -1
- package/dist/tools/NativeTools.js +571 -0
- package/dist/tools/NativeTools.js.map +1 -1
- package/dist/tools/Schemas.d.ts +1199 -102
- package/dist/tools/Schemas.d.ts.map +1 -1
- package/dist/tools/Schemas.js +358 -40
- package/dist/tools/Schemas.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 +73 -48
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +349 -158
- 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/utils/output.js
CHANGED
|
@@ -33,14 +33,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.Timer = exports.ThinkingAnimation = exports.theme = void 0;
|
|
36
|
+
exports.Timer = exports.StreamRenderer = exports.ThinkingAnimation = exports.theme = exports.CW_VERSION = void 0;
|
|
37
37
|
exports.getTermWidth = getTermWidth;
|
|
38
38
|
exports.showBanner = showBanner;
|
|
39
39
|
exports.showStaticBanner = showStaticBanner;
|
|
40
|
-
exports.
|
|
41
|
-
exports.boxBottom = boxBottom;
|
|
40
|
+
exports.showSessionInfo = showSessionInfo;
|
|
42
41
|
exports.printResponseHeader = printResponseHeader;
|
|
43
42
|
exports.printResponseFooter = printResponseFooter;
|
|
43
|
+
exports.streamResponseChunk = streamResponseChunk;
|
|
44
44
|
exports.printUserPrompt = printUserPrompt;
|
|
45
45
|
exports.printError = printError;
|
|
46
46
|
exports.printSuccess = printSuccess;
|
|
@@ -52,18 +52,21 @@ exports.printToolError = printToolError;
|
|
|
52
52
|
exports.printScoreCard = printScoreCard;
|
|
53
53
|
exports.printCommitBox = printCommitBox;
|
|
54
54
|
exports.printDiff = printDiff;
|
|
55
|
+
exports.checkWorkspaceTrust = checkWorkspaceTrust;
|
|
55
56
|
exports.printHelp = printHelp;
|
|
56
57
|
exports.printCompact = printCompact;
|
|
57
58
|
exports.printBox = printBox;
|
|
59
|
+
exports.renderMarkdown = renderMarkdown;
|
|
58
60
|
const chalk = __importStar(require("chalk"));
|
|
59
61
|
/**
|
|
60
62
|
* ═══════════════════════════════════════════════════════════════════
|
|
61
|
-
* CoWorker by Sylix — Premium Output System
|
|
63
|
+
* CoWorker v1.3.0 by Sylix — Premium Output System
|
|
62
64
|
* ═══════════════════════════════════════════════════════════════════
|
|
63
65
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
+
* Premium terminal rendering with true streaming support.
|
|
67
|
+
* All response text renders inside ╷│╵ borders as it arrives.
|
|
66
68
|
*/
|
|
69
|
+
exports.CW_VERSION = '1.3.1';
|
|
67
70
|
// ============================================================================
|
|
68
71
|
// THEME SYSTEM
|
|
69
72
|
// ============================================================================
|
|
@@ -80,15 +83,17 @@ function hex(color) {
|
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
exports.theme = {
|
|
83
|
-
brand: hex('#00D4FF'),
|
|
84
|
-
accent: hex('#7C3AED'),
|
|
85
|
-
success: hex('#10B981'),
|
|
86
|
-
error: hex('#EF4444'),
|
|
87
|
-
warning: hex('#F59E0B'),
|
|
88
|
-
ai: hex('#A78BFA'),
|
|
89
|
-
dim: hex('#6B7280'),
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
brand: hex('#00D4FF'),
|
|
87
|
+
accent: hex('#7C3AED'),
|
|
88
|
+
success: hex('#10B981'),
|
|
89
|
+
error: hex('#EF4444'),
|
|
90
|
+
warning: hex('#F59E0B'),
|
|
91
|
+
ai: hex('#A78BFA'),
|
|
92
|
+
dim: hex('#6B7280'),
|
|
93
|
+
border: hex('#4B5563'),
|
|
94
|
+
white: hex('#F9FAFB'),
|
|
95
|
+
code: hex('#FCD34D'),
|
|
96
|
+
purple: hex('#A78BFA'),
|
|
92
97
|
};
|
|
93
98
|
// ============================================================================
|
|
94
99
|
// TERMINAL UTILS
|
|
@@ -96,9 +101,6 @@ exports.theme = {
|
|
|
96
101
|
function getTermWidth() {
|
|
97
102
|
return process.stdout.columns || 80;
|
|
98
103
|
}
|
|
99
|
-
function isNarrow() {
|
|
100
|
-
return getTermWidth() < 60;
|
|
101
|
-
}
|
|
102
104
|
function sleep(ms) {
|
|
103
105
|
return new Promise(r => setTimeout(r, ms));
|
|
104
106
|
}
|
|
@@ -111,7 +113,7 @@ function showCursor() {
|
|
|
111
113
|
process.stdout.write('\x1b[?25h');
|
|
112
114
|
}
|
|
113
115
|
// ============================================================================
|
|
114
|
-
//
|
|
116
|
+
// ANIMATED BANNER
|
|
115
117
|
// ============================================================================
|
|
116
118
|
const LOGO_LINES = [
|
|
117
119
|
' ██████╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ',
|
|
@@ -121,60 +123,64 @@ const LOGO_LINES = [
|
|
|
121
123
|
'╚██████╗╚██████╔╝╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗███████╗██║ ██║',
|
|
122
124
|
' ╚═════╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝',
|
|
123
125
|
];
|
|
124
|
-
/**
|
|
125
|
-
* Full animated startup banner.
|
|
126
|
-
* Step 1: Char-by-char typewriter ASCII logo
|
|
127
|
-
* Step 2: Tagline fade-in word by word
|
|
128
|
-
* Step 3: Animated thin line draw
|
|
129
|
-
* Step 4: User/model info in dim text
|
|
130
|
-
*/
|
|
131
126
|
async function showBanner(version, userEmail, model = 'helix-1.2') {
|
|
132
|
-
if (IS_PIPE)
|
|
127
|
+
if (IS_PIPE || process.env.CW_NO_BANNER === '1')
|
|
133
128
|
return;
|
|
134
129
|
hideCursor();
|
|
135
130
|
console.log('');
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
131
|
+
try {
|
|
132
|
+
// Step 1: Logo — line by line, each types across
|
|
133
|
+
for (const line of LOGO_LINES) {
|
|
134
|
+
const chars = [...line];
|
|
135
|
+
let buffer = '';
|
|
136
|
+
for (let i = 0; i < chars.length; i++) {
|
|
137
|
+
buffer += chars[i];
|
|
138
|
+
if (i % 6 === 5 || i === chars.length - 1) {
|
|
139
|
+
process.stdout.write(exports.theme.brand(buffer));
|
|
140
|
+
buffer = '';
|
|
141
|
+
await sleep(1);
|
|
142
|
+
}
|
|
146
143
|
}
|
|
144
|
+
process.stdout.write('\n');
|
|
145
|
+
await sleep(60);
|
|
147
146
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
147
|
+
// Step 2: Tagline — word by word with semantic colors
|
|
148
|
+
console.log('');
|
|
149
|
+
const taglineWords = [
|
|
150
|
+
{ text: 'by', color: exports.theme.dim },
|
|
151
|
+
{ text: 'Sylix', color: exports.theme.brand },
|
|
152
|
+
{ text: '·', color: exports.theme.dim },
|
|
153
|
+
{ text: 'Your', color: exports.theme.white },
|
|
154
|
+
{ text: 'AI', color: exports.theme.purple },
|
|
155
|
+
{ text: 'Coding', color: exports.theme.white },
|
|
156
|
+
{ text: 'Partner', color: exports.theme.white },
|
|
157
|
+
];
|
|
158
|
+
process.stdout.write(' ');
|
|
159
|
+
for (const word of taglineWords) {
|
|
160
|
+
process.stdout.write(word.color(word.text) + ' ');
|
|
161
|
+
await sleep(100);
|
|
162
|
+
}
|
|
163
|
+
console.log('');
|
|
164
|
+
// Step 3: Divider draws left to right
|
|
165
|
+
console.log('');
|
|
166
|
+
const lineWidth = Math.min(getTermWidth() - 4, 60);
|
|
167
|
+
process.stdout.write(' ');
|
|
168
|
+
for (let i = 0; i < lineWidth; i++) {
|
|
169
|
+
process.stdout.write(exports.theme.dim('━'));
|
|
170
|
+
if (i % 3 === 0)
|
|
171
|
+
await sleep(3);
|
|
172
|
+
}
|
|
173
|
+
console.log('');
|
|
174
|
+
// Step 4: Info line
|
|
175
|
+
console.log('');
|
|
176
|
+
const userStr = userEmail ? `Signed in as ${userEmail}` : 'Not signed in';
|
|
177
|
+
console.log(` ${exports.theme.brand('◆')} ${exports.theme.dim(`${userStr} · Model: ${model} · v${version}`)}`);
|
|
178
|
+
console.log('');
|
|
156
179
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
console.log('');
|
|
160
|
-
const lineWidth = Math.min(getTermWidth() - 4, 60);
|
|
161
|
-
process.stdout.write(' ');
|
|
162
|
-
for (let i = 0; i < lineWidth; i++) {
|
|
163
|
-
process.stdout.write(exports.theme.brand('━'));
|
|
164
|
-
if (i % 3 === 0)
|
|
165
|
-
await sleep(3);
|
|
180
|
+
finally {
|
|
181
|
+
showCursor();
|
|
166
182
|
}
|
|
167
|
-
console.log('');
|
|
168
|
-
// Step 4: User + model + version
|
|
169
|
-
console.log('');
|
|
170
|
-
const userStr = userEmail ? `Signed in as ${userEmail}` : 'Not signed in';
|
|
171
|
-
console.log(exports.theme.dim(` ◆ ${userStr} · Model: ${model} · v${version}`));
|
|
172
|
-
console.log('');
|
|
173
|
-
showCursor();
|
|
174
183
|
}
|
|
175
|
-
/**
|
|
176
|
-
* Static banner for non-TTY / piped / --no-banner mode.
|
|
177
|
-
*/
|
|
178
184
|
function showStaticBanner(version) {
|
|
179
185
|
console.log('');
|
|
180
186
|
for (const line of LOGO_LINES) {
|
|
@@ -182,33 +188,51 @@ function showStaticBanner(version) {
|
|
|
182
188
|
}
|
|
183
189
|
console.log(exports.theme.dim(`\n by Sylix · v${version}\n`));
|
|
184
190
|
}
|
|
191
|
+
async function showSessionInfo(cwd, sessionId) {
|
|
192
|
+
if (IS_PIPE) {
|
|
193
|
+
console.log(` cwd: ${cwd}`);
|
|
194
|
+
console.log(` session: ${sessionId.substring(0, 8)}...`);
|
|
195
|
+
console.log(` tips: /help for commands, Ctrl+C to exit\n`);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const lines = [
|
|
199
|
+
exports.theme.dim(` cwd: ${cwd}`),
|
|
200
|
+
exports.theme.dim(` session: ${sessionId.substring(0, 8)}...`),
|
|
201
|
+
exports.theme.dim(` tips: /help for commands, Ctrl+C to exit`),
|
|
202
|
+
];
|
|
203
|
+
for (const line of lines) {
|
|
204
|
+
console.log(line);
|
|
205
|
+
await sleep(50);
|
|
206
|
+
}
|
|
207
|
+
console.log('');
|
|
208
|
+
}
|
|
185
209
|
// ============================================================================
|
|
186
|
-
// THINKING
|
|
210
|
+
// THINKING ANIMATION — Rotating messages with pulsing dots
|
|
187
211
|
// ============================================================================
|
|
188
|
-
const
|
|
189
|
-
'
|
|
190
|
-
'
|
|
191
|
-
'
|
|
192
|
-
'
|
|
193
|
-
'
|
|
194
|
-
'◆ CoWorker is on it...',
|
|
212
|
+
const THINKING_MESSAGES = [
|
|
213
|
+
'working',
|
|
214
|
+
'thinking',
|
|
215
|
+
'reading codebase',
|
|
216
|
+
'analyzing',
|
|
217
|
+
'on it',
|
|
195
218
|
];
|
|
196
219
|
class ThinkingAnimation {
|
|
197
|
-
constructor() {
|
|
220
|
+
constructor(customMessage) {
|
|
198
221
|
this.interval = null;
|
|
199
222
|
this.frame = 0;
|
|
200
|
-
this.message =
|
|
223
|
+
this.message = customMessage || THINKING_MESSAGES[Math.floor(Math.random() * THINKING_MESSAGES.length)];
|
|
201
224
|
}
|
|
202
225
|
start() {
|
|
203
226
|
if (IS_PIPE)
|
|
204
227
|
return;
|
|
205
228
|
hideCursor();
|
|
206
|
-
const dots = ['◉ ○ ○', '○ ◉ ○', '○ ○ ◉'];
|
|
207
229
|
this.interval = setInterval(() => {
|
|
208
|
-
const
|
|
209
|
-
|
|
230
|
+
const dotCount = (this.frame % 4);
|
|
231
|
+
const dots = '.'.repeat(dotCount);
|
|
232
|
+
const pad = ' '.repeat(3 - dotCount);
|
|
233
|
+
process.stdout.write(`\r ${exports.theme.brand('◆')} ${exports.theme.dim(this.message + dots)}${pad}` + ' '.repeat(10));
|
|
210
234
|
this.frame++;
|
|
211
|
-
},
|
|
235
|
+
}, 400);
|
|
212
236
|
}
|
|
213
237
|
stop() {
|
|
214
238
|
if (this.interval) {
|
|
@@ -221,42 +245,126 @@ class ThinkingAnimation {
|
|
|
221
245
|
}
|
|
222
246
|
exports.ThinkingAnimation = ThinkingAnimation;
|
|
223
247
|
// ============================================================================
|
|
224
|
-
//
|
|
248
|
+
// STREAMING RESPONSE RENDERER
|
|
225
249
|
// ============================================================================
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Manages the response box state during streaming.
|
|
252
|
+
*
|
|
253
|
+
* Correct output:
|
|
254
|
+
* ╷
|
|
255
|
+
* │ Hi! I'm CoWorker, your AI coding assistant.
|
|
256
|
+
* │
|
|
257
|
+
* │ I can help you with:
|
|
258
|
+
* │ · Writing and debugging code
|
|
259
|
+
* │
|
|
260
|
+
* ╵ ✦ 1.2s · 34 tokens
|
|
261
|
+
*
|
|
262
|
+
* Rules:
|
|
263
|
+
* - ALL text inside ╷│╵ border
|
|
264
|
+
* - Border chars (╷ │ ╵) in dim gray #4B5563
|
|
265
|
+
* - Response text in purple #A78BFA
|
|
266
|
+
* - Code blocks switch to yellow #FCD34D
|
|
267
|
+
* - On every \n → print "\n │ "
|
|
268
|
+
*/
|
|
269
|
+
class StreamRenderer {
|
|
270
|
+
constructor() {
|
|
271
|
+
this.started = false;
|
|
272
|
+
this.inCodeBlock = false;
|
|
273
|
+
this.charCount = 0;
|
|
274
|
+
this.startTime = Date.now();
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Call this for EACH chunk as it arrives from the SSE stream.
|
|
278
|
+
* Renders immediately — no buffering.
|
|
279
|
+
*/
|
|
280
|
+
write(chunk) {
|
|
281
|
+
if (!this.started) {
|
|
282
|
+
// Open the response border
|
|
283
|
+
console.log(exports.theme.border(' ╷'));
|
|
284
|
+
process.stdout.write(exports.theme.border(' │') + ' ');
|
|
285
|
+
this.started = true;
|
|
286
|
+
}
|
|
287
|
+
for (const char of chunk) {
|
|
288
|
+
this.charCount++;
|
|
289
|
+
if (char === '\n') {
|
|
290
|
+
// Start a new bordered line
|
|
291
|
+
process.stdout.write('\n' + exports.theme.border(' │') + ' ');
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
// Detect code block toggle
|
|
295
|
+
// We track ``` by checking accumulated chars, but simplified:
|
|
296
|
+
// the chunk itself may contain ```. We'll track via state.
|
|
297
|
+
if (char === '`') {
|
|
298
|
+
// Just render it — code block detection is per-line in the final text
|
|
299
|
+
// For streaming, we use simple color: ai color for prose, code color inside ```
|
|
300
|
+
}
|
|
301
|
+
// Choose color based on whether we're in a code block
|
|
302
|
+
const color = this.inCodeBlock ? exports.theme.code : exports.theme.ai;
|
|
303
|
+
process.stdout.write(color(char));
|
|
304
|
+
}
|
|
305
|
+
// Check for code block toggles in the chunk
|
|
306
|
+
const backtickMatches = chunk.match(/```/g);
|
|
307
|
+
if (backtickMatches) {
|
|
308
|
+
for (const _match of backtickMatches) {
|
|
309
|
+
this.inCodeBlock = !this.inCodeBlock;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Close the response box and print footer.
|
|
315
|
+
*/
|
|
316
|
+
finish() {
|
|
317
|
+
if (!this.started)
|
|
318
|
+
return;
|
|
319
|
+
const elapsed = Date.now() - this.startTime;
|
|
320
|
+
const elapsedStr = elapsed < 1000 ? `${elapsed}ms` : `${(elapsed / 1000).toFixed(1)}s`;
|
|
321
|
+
const tokenEst = Math.ceil(this.charCount / 4);
|
|
322
|
+
console.log(''); // end the last │ line
|
|
323
|
+
console.log(exports.theme.border(` ╵`) + exports.theme.dim(` ✦ ${elapsedStr} · ${tokenEst} tokens`));
|
|
324
|
+
console.log('');
|
|
325
|
+
}
|
|
326
|
+
/** Returns the estimated token count. */
|
|
327
|
+
getTokenEstimate() {
|
|
328
|
+
return Math.ceil(this.charCount / 4);
|
|
329
|
+
}
|
|
330
|
+
/** Returns elapsed ms. */
|
|
331
|
+
getElapsed() {
|
|
332
|
+
return Date.now() - this.startTime;
|
|
333
|
+
}
|
|
238
334
|
}
|
|
335
|
+
exports.StreamRenderer = StreamRenderer;
|
|
336
|
+
// ============================================================================
|
|
337
|
+
// LEGACY COMPAT — printResponseHeader/Footer for tool outputs
|
|
338
|
+
// ============================================================================
|
|
239
339
|
function printResponseHeader() {
|
|
240
|
-
console.log(
|
|
241
|
-
|
|
340
|
+
console.log(exports.theme.border(' ╷'));
|
|
341
|
+
process.stdout.write(exports.theme.border(' │') + ' ');
|
|
242
342
|
}
|
|
243
343
|
function printResponseFooter(elapsed, tokenEstimate) {
|
|
244
|
-
console.log(exports.theme.brand(' │'));
|
|
245
|
-
console.log(boxBottom());
|
|
246
|
-
console.log('');
|
|
247
344
|
const elapsedStr = elapsed < 1000 ? `${elapsed}ms` : `${(elapsed / 1000).toFixed(1)}s`;
|
|
248
|
-
const tokenStr = tokenEstimate ? `
|
|
249
|
-
console.log(exports.theme.dim(`
|
|
345
|
+
const tokenStr = tokenEstimate ? ` · ${tokenEstimate} tokens` : '';
|
|
346
|
+
console.log(exports.theme.border(` ╵`) + exports.theme.dim(` ✦ ${elapsedStr}${tokenStr}`));
|
|
347
|
+
}
|
|
348
|
+
function streamResponseChunk(chunk) {
|
|
349
|
+
const parts = chunk.split('\n');
|
|
350
|
+
for (let i = 0; i < parts.length; i++) {
|
|
351
|
+
if (i > 0) {
|
|
352
|
+
process.stdout.write('\n' + exports.theme.border(' │') + ' ');
|
|
353
|
+
}
|
|
354
|
+
process.stdout.write(exports.theme.ai(parts[i]));
|
|
355
|
+
}
|
|
250
356
|
}
|
|
251
357
|
// ============================================================================
|
|
252
|
-
// PROMPT RENDERING
|
|
358
|
+
// PROMPT RENDERING — Only called ONCE after user hits Enter
|
|
253
359
|
// ============================================================================
|
|
254
360
|
function printUserPrompt(input) {
|
|
255
|
-
|
|
256
|
-
|
|
361
|
+
// NOTE: Do NOT call this if readline already echoed the prompt.
|
|
362
|
+
// In the REPL, readline shows "you › input" automatically.
|
|
363
|
+
// This is ONLY for re-printing in non-readline contexts.
|
|
364
|
+
console.log(` ${exports.theme.dim('you')} ${exports.theme.brand('›')} ${input}`);
|
|
257
365
|
}
|
|
258
366
|
// ============================================================================
|
|
259
|
-
// ERROR / SUCCESS / WARNING
|
|
367
|
+
// ERROR / SUCCESS / WARNING
|
|
260
368
|
// ============================================================================
|
|
261
369
|
function printError(title, details, hint) {
|
|
262
370
|
console.log('');
|
|
@@ -282,7 +390,7 @@ function printWarning(message) {
|
|
|
282
390
|
console.log(exports.theme.warning(` ⚠ ${message}`));
|
|
283
391
|
}
|
|
284
392
|
// ============================================================================
|
|
285
|
-
// EXIT
|
|
393
|
+
// EXIT
|
|
286
394
|
// ============================================================================
|
|
287
395
|
function printExit() {
|
|
288
396
|
if (IS_PIPE)
|
|
@@ -305,72 +413,45 @@ function printToolError(toolName, error) {
|
|
|
305
413
|
process.stdout.write(`\r ${exports.theme.error('✗')} ${exports.theme.code(toolName)} ${exports.theme.dim(error.substring(0, 60))}` + ' '.repeat(10) + '\n');
|
|
306
414
|
}
|
|
307
415
|
// ============================================================================
|
|
308
|
-
//
|
|
416
|
+
// SCORE CARD
|
|
309
417
|
// ============================================================================
|
|
310
|
-
/**
|
|
311
|
-
* ┌─────────────────────────────────┐
|
|
312
|
-
* │ Code Review · src/index.ts │
|
|
313
|
-
* ├─────────────────────────────────┤
|
|
314
|
-
* │ Quality ████████░░ 8/10 │
|
|
315
|
-
* │ Security ██████████ 10/10 │
|
|
316
|
-
* └─────────────────────────────────┘
|
|
317
|
-
*/
|
|
318
418
|
function printScoreCard(fileName, scores) {
|
|
319
|
-
const w = Math.min(getTermWidth() - 4, 50);
|
|
320
|
-
const iw = w - 2; // inner width
|
|
321
|
-
const title = `Code Review · ${fileName}`;
|
|
322
419
|
console.log('');
|
|
323
|
-
console.log(exports.theme.
|
|
324
|
-
console.log(exports.theme.brand(` │ `) + exports.theme.white(title) + ' '.repeat(Math.max(0, iw - title.length - 2)) + exports.theme.brand(`│`));
|
|
325
|
-
console.log(exports.theme.brand(` ├${'─'.repeat(iw)}┤`));
|
|
420
|
+
console.log(exports.theme.dim(` ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄`));
|
|
326
421
|
for (const { label, score, max = 10 } of scores) {
|
|
327
422
|
const barWidth = 10;
|
|
328
423
|
const filled = Math.round((score / max) * barWidth);
|
|
329
424
|
const bar = '█'.repeat(filled) + '░'.repeat(barWidth - filled);
|
|
330
|
-
const
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
const content = `${label}${' '.repeat(Math.max(1, pad))}${bar}${scoreStr}`;
|
|
334
|
-
const rowPad = iw - content.length - 2;
|
|
335
|
-
console.log(exports.theme.brand(` │ `) + exports.theme.dim(label) + ' '.repeat(Math.max(1, pad)) + barColor(bar) + exports.theme.dim(scoreStr) + ' '.repeat(Math.max(0, rowPad)) + exports.theme.brand(`│`));
|
|
425
|
+
const barColor = score >= 8 ? exports.theme.brand : score >= 5 ? exports.theme.warning : exports.theme.error;
|
|
426
|
+
const dots = '·'.repeat(Math.max(1, 16 - label.length));
|
|
427
|
+
console.log(` ${exports.theme.dim(label)} ${exports.theme.dim(dots)} ${exports.theme.white(String(score))} ${barColor(bar)}`);
|
|
336
428
|
}
|
|
337
|
-
console.log(exports.theme.
|
|
429
|
+
console.log(exports.theme.dim(` ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄`));
|
|
338
430
|
console.log('');
|
|
339
431
|
}
|
|
340
432
|
// ============================================================================
|
|
341
|
-
//
|
|
433
|
+
// COMMIT BOX
|
|
342
434
|
// ============================================================================
|
|
343
|
-
/**
|
|
344
|
-
* ╭─ Suggested Commit ──────────────────╮
|
|
345
|
-
* │ ✨ feat: add user auth middleware │
|
|
346
|
-
* │ │
|
|
347
|
-
* │ Use this commit message? (y/n) › │
|
|
348
|
-
* ╰─────────────────────────────────────╯
|
|
349
|
-
*/
|
|
350
435
|
function printCommitBox(commitMessage) {
|
|
351
436
|
const w = Math.min(getTermWidth() - 2, 55);
|
|
352
|
-
const label = '
|
|
437
|
+
const label = 'suggested commit';
|
|
353
438
|
const headerPad = w - 6 - label.length;
|
|
354
|
-
const msgLine = `✨ ${commitMessage}`;
|
|
355
|
-
const promptLine = 'Use this commit message? (y/n) ›';
|
|
356
439
|
console.log('');
|
|
357
440
|
console.log(exports.theme.brand(` ╭─ ${label} ${'─'.repeat(Math.max(0, headerPad))}╮`));
|
|
358
|
-
console.log(exports.theme.brand(` │ `) + exports.theme.success(msgLine) + ' '.repeat(Math.max(0, w - 5 - msgLine.length)) + exports.theme.brand(`│`));
|
|
359
441
|
console.log(exports.theme.brand(` │`) + ' '.repeat(w - 2) + exports.theme.brand(`│`));
|
|
360
|
-
|
|
442
|
+
const maxMsgWidth = w - 6;
|
|
443
|
+
const msgLines = commitMessage.match(new RegExp(`.{1,${maxMsgWidth}}`, 'g')) || [commitMessage];
|
|
444
|
+
for (const msgLine of msgLines) {
|
|
445
|
+
const pad = w - 5 - msgLine.length;
|
|
446
|
+
console.log(exports.theme.brand(` │ `) + exports.theme.success(msgLine) + ' '.repeat(Math.max(0, pad)) + exports.theme.brand(`│`));
|
|
447
|
+
}
|
|
448
|
+
console.log(exports.theme.brand(` │`) + ' '.repeat(w - 2) + exports.theme.brand(`│`));
|
|
361
449
|
console.log(exports.theme.brand(` ╰${'─'.repeat(w - 2)}╯`));
|
|
362
450
|
console.log('');
|
|
363
451
|
}
|
|
364
452
|
// ============================================================================
|
|
365
|
-
//
|
|
453
|
+
// DIFF PREVIEW
|
|
366
454
|
// ============================================================================
|
|
367
|
-
/**
|
|
368
|
-
* ── Changes to src/api/sylix.ts ──────────
|
|
369
|
-
* - const url = "old-endpoint" ← red
|
|
370
|
-
* + const url = "new-endpoint" ← green
|
|
371
|
-
* ─────────────────────────────────────────
|
|
372
|
-
* Apply these changes? (y/n) ›
|
|
373
|
-
*/
|
|
374
455
|
function printDiff(fileName, changes) {
|
|
375
456
|
const w = Math.min(getTermWidth() - 4, 60);
|
|
376
457
|
const header = `Changes to ${fileName}`;
|
|
@@ -389,20 +470,94 @@ function printDiff(fileName, changes) {
|
|
|
389
470
|
}
|
|
390
471
|
}
|
|
391
472
|
console.log(exports.theme.dim(` ${'─'.repeat(w)}`));
|
|
392
|
-
console.log(exports.theme.dim(` Apply these changes? (y/n) ›`));
|
|
393
473
|
console.log('');
|
|
394
474
|
}
|
|
395
475
|
// ============================================================================
|
|
396
|
-
//
|
|
476
|
+
// TRUST PROMPT — Branded CoWorker workspace verification
|
|
477
|
+
// ============================================================================
|
|
478
|
+
const fs = __importStar(require("fs"));
|
|
479
|
+
const path = __importStar(require("path"));
|
|
480
|
+
const os = __importStar(require("os"));
|
|
481
|
+
const readline = __importStar(require("readline"));
|
|
482
|
+
const TRUSTED_PATH = path.join(os.homedir(), '.coworker', 'trusted.json');
|
|
483
|
+
function loadTrustedPaths() {
|
|
484
|
+
try {
|
|
485
|
+
if (fs.existsSync(TRUSTED_PATH)) {
|
|
486
|
+
const data = JSON.parse(fs.readFileSync(TRUSTED_PATH, 'utf8'));
|
|
487
|
+
return Array.isArray(data?.trustedPaths) ? data.trustedPaths : [];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch { /* ignore */ }
|
|
491
|
+
return [];
|
|
492
|
+
}
|
|
493
|
+
function saveTrustedPaths(paths) {
|
|
494
|
+
try {
|
|
495
|
+
const dir = path.dirname(TRUSTED_PATH);
|
|
496
|
+
if (!fs.existsSync(dir)) {
|
|
497
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
498
|
+
}
|
|
499
|
+
fs.writeFileSync(TRUSTED_PATH, JSON.stringify({ trustedPaths: paths }, null, 2));
|
|
500
|
+
}
|
|
501
|
+
catch { /* ignore */ }
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Shows the CoWorker branded workspace trust prompt.
|
|
505
|
+
* Returns true if user trusts, false if they want to exit.
|
|
506
|
+
* Skips silently if the directory is already trusted.
|
|
507
|
+
*/
|
|
508
|
+
async function checkWorkspaceTrust(cwd) {
|
|
509
|
+
if (IS_PIPE)
|
|
510
|
+
return true; // Non-interactive mode — skip
|
|
511
|
+
const trustedPaths = loadTrustedPaths();
|
|
512
|
+
const normalizedCwd = cwd.replace(/\\/g, '/').toLowerCase();
|
|
513
|
+
// Check if already trusted
|
|
514
|
+
const isTrusted = trustedPaths.some(p => {
|
|
515
|
+
const normalized = p.replace(/\\/g, '/').toLowerCase();
|
|
516
|
+
return normalizedCwd.startsWith(normalized) || normalizedCwd === normalized;
|
|
517
|
+
});
|
|
518
|
+
if (isTrusted)
|
|
519
|
+
return true;
|
|
520
|
+
// Show the branded trust prompt
|
|
521
|
+
const lineWidth = Math.min(getTermWidth() - 4, 50);
|
|
522
|
+
console.log('');
|
|
523
|
+
console.log(exports.theme.dim(` ${'─'.repeat(lineWidth)}`));
|
|
524
|
+
console.log(` ${exports.theme.brand('◆')} ${exports.theme.brand('Workspace:')} ${exports.theme.white(cwd)}`);
|
|
525
|
+
console.log(exports.theme.dim(` ${'─'.repeat(lineWidth)}`));
|
|
526
|
+
console.log('');
|
|
527
|
+
console.log(exports.theme.dim(' CoWorker can read, edit, and run files here.'));
|
|
528
|
+
console.log(exports.theme.dim(' Only use in folders you own or trust.'));
|
|
529
|
+
console.log('');
|
|
530
|
+
console.log(` ${exports.theme.brand('›')} ${exports.theme.white('1. Got it, let\'s go')}`);
|
|
531
|
+
console.log(` ${exports.theme.dim('2. Exit')}`);
|
|
532
|
+
console.log('');
|
|
533
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
534
|
+
const answer = await new Promise((resolve) => {
|
|
535
|
+
rl.question(exports.theme.dim(' Enter to confirm · Esc to cancel › '), (a) => {
|
|
536
|
+
resolve(a.trim());
|
|
537
|
+
rl.close();
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
if (answer === '2' || answer.toLowerCase() === 'exit') {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
// Trust this directory
|
|
544
|
+
trustedPaths.push(cwd);
|
|
545
|
+
saveTrustedPaths(trustedPaths);
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
// ============================================================================
|
|
549
|
+
// HELP + COMPACT
|
|
397
550
|
// ============================================================================
|
|
398
551
|
function printHelp() {
|
|
399
552
|
console.log(`
|
|
400
553
|
${exports.theme.brand(' Slash Commands:')}
|
|
401
|
-
${exports.theme.code('/help')}
|
|
402
|
-
${exports.theme.code('/clear')}
|
|
403
|
-
${exports.theme.code('/
|
|
404
|
-
${exports.theme.code('/
|
|
405
|
-
${exports.theme.code('/
|
|
554
|
+
${exports.theme.code('/help')} ${exports.theme.dim('Show this help')}
|
|
555
|
+
${exports.theme.code('/clear')} ${exports.theme.dim('Clear the screen')}
|
|
556
|
+
${exports.theme.code('/review')} ${exports.theme.dim('Code review current branch')}
|
|
557
|
+
${exports.theme.code('/commit')} ${exports.theme.dim('Generate commit message from diff')}
|
|
558
|
+
${exports.theme.code('/status')} ${exports.theme.dim('Show auth & session status')}
|
|
559
|
+
${exports.theme.code('/compact')} ${exports.theme.dim('Show context window usage')}
|
|
560
|
+
${exports.theme.code('/exit')} ${exports.theme.dim('Exit CoWorker')}
|
|
406
561
|
`);
|
|
407
562
|
}
|
|
408
563
|
function printCompact(msgCount, tokenEst, sessionId) {
|
|
@@ -412,11 +567,13 @@ function printCompact(msgCount, tokenEst, sessionId) {
|
|
|
412
567
|
const bar = '█'.repeat(filled) + '░'.repeat(barWidth - filled);
|
|
413
568
|
const color = usage > 80 ? exports.theme.error : usage > 50 ? exports.theme.warning : exports.theme.success;
|
|
414
569
|
console.log('');
|
|
415
|
-
console.log(exports.theme.dim(` Messages: ${msgCount} │ Context: `) +
|
|
570
|
+
console.log(exports.theme.dim(` Messages: ${msgCount} │ Context: `) +
|
|
571
|
+
color(`[${bar}] ${usage}%`) +
|
|
572
|
+
exports.theme.dim(` │ Session: ${sessionId.substring(0, 8)}`));
|
|
416
573
|
console.log('');
|
|
417
574
|
}
|
|
418
575
|
// ============================================================================
|
|
419
|
-
// GENERIC
|
|
576
|
+
// GENERIC BOX + TIMER
|
|
420
577
|
// ============================================================================
|
|
421
578
|
function printBox(label, lines) {
|
|
422
579
|
const w = Math.min(getTermWidth() - 2, 70);
|
|
@@ -428,9 +585,6 @@ function printBox(label, lines) {
|
|
|
428
585
|
}
|
|
429
586
|
console.log(exports.theme.brand(` ╰${'─'.repeat(w - 3)}╯`));
|
|
430
587
|
}
|
|
431
|
-
// ============================================================================
|
|
432
|
-
// ELAPSED TIME UTILITY
|
|
433
|
-
// ============================================================================
|
|
434
588
|
class Timer {
|
|
435
589
|
constructor() {
|
|
436
590
|
this.start = Date.now();
|
|
@@ -444,4 +598,41 @@ class Timer {
|
|
|
444
598
|
}
|
|
445
599
|
}
|
|
446
600
|
exports.Timer = Timer;
|
|
601
|
+
// ============================================================================
|
|
602
|
+
// RENDER MARKDOWN (for buffered final rendering)
|
|
603
|
+
// ============================================================================
|
|
604
|
+
function renderMarkdown(text) {
|
|
605
|
+
const lines = text.split('\n');
|
|
606
|
+
const rendered = [];
|
|
607
|
+
let inCodeBlock = false;
|
|
608
|
+
for (const line of lines) {
|
|
609
|
+
if (line.trim().startsWith('```') && !inCodeBlock) {
|
|
610
|
+
inCodeBlock = true;
|
|
611
|
+
const lang = line.trim().replace('```', '').trim() || 'code';
|
|
612
|
+
rendered.push(` ${exports.theme.dim(`┌─ ${lang} ──`)}`);
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
if (line.trim() === '```' && inCodeBlock) {
|
|
616
|
+
inCodeBlock = false;
|
|
617
|
+
rendered.push(` ${exports.theme.dim('└──')}`);
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
if (inCodeBlock) {
|
|
621
|
+
rendered.push(` ${exports.theme.dim('│')} ${exports.theme.code(line)}`);
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
if (line.match(/^#{1,3}\s+/)) {
|
|
625
|
+
rendered.push(exports.theme.brand(line.replace(/^#{1,3}\s+/, '')));
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
if (line.match(/^\s*[-*]\s+/)) {
|
|
629
|
+
rendered.push(`${exports.theme.dim('·')} ${line.replace(/^\s*[-*]\s+/, '')}`);
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
let result = line.replace(/\*\*(.+?)\*\*/g, (_, c) => exports.theme.white(c));
|
|
633
|
+
result = result.replace(/`(.+?)`/g, (_, c) => exports.theme.code(c));
|
|
634
|
+
rendered.push(result);
|
|
635
|
+
}
|
|
636
|
+
return rendered.join('\n');
|
|
637
|
+
}
|
|
447
638
|
//# sourceMappingURL=output.js.map
|