codetyper-cli 0.4.1 → 0.4.3
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/README.md +77 -51
- package/dist/index.js +347 -192
- package/package.json +5 -7
- package/src/version.json +1 -1
package/README.md
CHANGED
|
@@ -90,9 +90,11 @@ Full-screen terminal interface with real-time streaming responses.
|
|
|
90
90
|

|
|
91
91
|
|
|
92
92
|
**Key bindings:**
|
|
93
|
+
|
|
93
94
|
- `Enter` - Send message
|
|
94
95
|
- `Shift+Enter` - New line
|
|
95
|
-
-
|
|
96
|
+
- `@` - Open file picker (works anywhere in input)
|
|
97
|
+
- `/` - Open command menu (works anywhere in input)
|
|
96
98
|
- `Ctrl+M` - Toggle interaction mode
|
|
97
99
|
- `Ctrl+T` - Toggle todo panel
|
|
98
100
|
- `Shift+Up/Down` - Scroll log panel
|
|
@@ -103,6 +105,7 @@ Full-screen terminal interface with real-time streaming responses.
|
|
|
103
105
|
Optional vim-style keyboard navigation for power users. Enable in settings.
|
|
104
106
|
|
|
105
107
|
**Normal Mode:**
|
|
108
|
+
|
|
106
109
|
- `j/k` - Scroll down/up
|
|
107
110
|
- `gg/G` - Jump to top/bottom
|
|
108
111
|
- `Ctrl+d/u` - Half page scroll
|
|
@@ -111,6 +114,7 @@ Optional vim-style keyboard navigation for power users. Enable in settings.
|
|
|
111
114
|
- `:` - Command mode (`:q` quit, `:w` save)
|
|
112
115
|
|
|
113
116
|
**Configuration:**
|
|
117
|
+
|
|
114
118
|
```json
|
|
115
119
|
{
|
|
116
120
|
"vim": {
|
|
@@ -128,26 +132,26 @@ Press `/` to access all commands organized by category.
|
|
|
128
132
|
|
|
129
133
|
**Available Commands:**
|
|
130
134
|
|
|
131
|
-
| Category | Command
|
|
132
|
-
|
|
133
|
-
| General
|
|
134
|
-
| General
|
|
135
|
-
| General
|
|
136
|
-
| Session
|
|
137
|
-
| Session
|
|
138
|
-
| Session
|
|
139
|
-
| Session
|
|
140
|
-
| Session
|
|
141
|
-
| Settings | `/model`
|
|
142
|
-
| Settings | `/agent`
|
|
143
|
-
| Settings | `/mode`
|
|
144
|
-
| Settings | `/provider`
|
|
145
|
-
| Settings | `/status`
|
|
146
|
-
| Settings | `/theme`
|
|
147
|
-
| Settings | `/mcp`
|
|
148
|
-
| Account
|
|
149
|
-
| Account
|
|
150
|
-
| Account
|
|
135
|
+
| Category | Command | Description |
|
|
136
|
+
| -------- | ------------ | --------------------------------- |
|
|
137
|
+
| General | `/help` | Show available commands |
|
|
138
|
+
| General | `/clear` | Clear conversation history |
|
|
139
|
+
| General | `/exit` | Exit the chat |
|
|
140
|
+
| Session | `/save` | Save current session |
|
|
141
|
+
| Session | `/context` | Show context information |
|
|
142
|
+
| Session | `/usage` | Show token usage statistics |
|
|
143
|
+
| Session | `/remember` | Save a learning about the project |
|
|
144
|
+
| Session | `/learnings` | Show saved learnings |
|
|
145
|
+
| Settings | `/model` | Select AI model |
|
|
146
|
+
| Settings | `/agent` | Select agent |
|
|
147
|
+
| Settings | `/mode` | Switch interaction mode |
|
|
148
|
+
| Settings | `/provider` | Switch LLM provider |
|
|
149
|
+
| Settings | `/status` | Show provider status |
|
|
150
|
+
| Settings | `/theme` | Change color theme |
|
|
151
|
+
| Settings | `/mcp` | Manage MCP servers |
|
|
152
|
+
| Account | `/whoami` | Show logged in account |
|
|
153
|
+
| Account | `/login` | Authenticate with provider |
|
|
154
|
+
| Account | `/logout` | Sign out from provider |
|
|
151
155
|
|
|
152
156
|
### Agent Mode with Diff View
|
|
153
157
|
|
|
@@ -156,6 +160,7 @@ When CodeTyper modifies files, you see a clear diff view of changes.
|
|
|
156
160
|

|
|
157
161
|
|
|
158
162
|
**Interaction Modes:**
|
|
163
|
+
|
|
159
164
|
- **Agent** - Full access, can modify files
|
|
160
165
|
- **Ask** - Read-only, answers questions
|
|
161
166
|
- **Code Review** - Review PRs and diffs
|
|
@@ -167,6 +172,7 @@ Granular control over what CodeTyper can do. Every file operation requires appro
|
|
|
167
172
|

|
|
168
173
|
|
|
169
174
|
**Permission Scopes:**
|
|
175
|
+
|
|
170
176
|
- `[y]` Yes, this once
|
|
171
177
|
- `[s]` Yes, for this session
|
|
172
178
|
- `[a]` Always allow for this project
|
|
@@ -180,6 +186,7 @@ Access to multiple AI models through GitHub Copilot.
|
|
|
180
186
|

|
|
181
187
|
|
|
182
188
|
**Available Models:**
|
|
189
|
+
|
|
183
190
|
- GPT-5, GPT-5-mini (Unlimited)
|
|
184
191
|
- GPT-5.2-codex, GPT-5.1-codex
|
|
185
192
|
- Grok-code-fast-1
|
|
@@ -187,19 +194,19 @@ Access to multiple AI models through GitHub Copilot.
|
|
|
187
194
|
|
|
188
195
|
### Theme System
|
|
189
196
|
|
|
190
|
-
|
|
197
|
+
15+ built-in themes to customize your experience.
|
|
191
198
|
|
|
192
199
|

|
|
193
200
|
|
|
194
201
|
**Available Themes:**
|
|
195
|
-
default, dracula, nord, tokyo-night, gruvbox, monokai, catppuccin, one-dark, solarized-dark, github-dark, rose-pine, kanagawa, ayu-dark, cargdev-cyberpunk
|
|
202
|
+
default, dracula, nord, tokyo-night, gruvbox, monokai, catppuccin, one-dark, solarized-dark, github-dark, rose-pine, kanagawa, ayu-dark, cargdev-cyberpunk, pink-purple
|
|
196
203
|
|
|
197
204
|
## Providers
|
|
198
205
|
|
|
199
|
-
| Provider
|
|
200
|
-
|
|
201
|
-
| **GitHub Copilot** | GPT-5, Claude, Gemini
|
|
202
|
-
| **Ollama**
|
|
206
|
+
| Provider | Models | Auth Method | Use Case |
|
|
207
|
+
| ------------------ | --------------------------- | ------------------- | --------------------------- |
|
|
208
|
+
| **GitHub Copilot** | GPT-5, Claude, Gemini | OAuth (device flow) | Cloud-based, high quality |
|
|
209
|
+
| **Ollama** | Llama, DeepSeek, Qwen, etc. | Local server | Private, offline, zero-cost |
|
|
203
210
|
|
|
204
211
|
### Cascade Mode
|
|
205
212
|
|
|
@@ -244,6 +251,7 @@ Settings are stored in `~/.config/codetyper/config.json`:
|
|
|
244
251
|
### Project Context
|
|
245
252
|
|
|
246
253
|
CodeTyper reads project-specific context from:
|
|
254
|
+
|
|
247
255
|
- `.github/` - GitHub workflows and templates
|
|
248
256
|
- `.codetyper/` - Project-specific rules and learnings
|
|
249
257
|
- `rules.md` - Custom instructions for the AI
|
|
@@ -274,18 +282,18 @@ codetyper --print "Explain this codebase"
|
|
|
274
282
|
|
|
275
283
|
CodeTyper has access to these built-in tools:
|
|
276
284
|
|
|
277
|
-
| Tool
|
|
278
|
-
|
|
279
|
-
| `bash`
|
|
280
|
-
| `read`
|
|
281
|
-
| `write`
|
|
282
|
-
| `edit`
|
|
283
|
-
| `glob`
|
|
284
|
-
| `grep`
|
|
285
|
-
| `lsp`
|
|
286
|
-
| `web_search` | Search the web
|
|
287
|
-
| `todo-read`
|
|
288
|
-
| `todo-write` | Update todo list
|
|
285
|
+
| Tool | Description |
|
|
286
|
+
| ------------ | ----------------------------------- |
|
|
287
|
+
| `bash` | Execute shell commands |
|
|
288
|
+
| `read` | Read file contents |
|
|
289
|
+
| `write` | Create or overwrite files |
|
|
290
|
+
| `edit` | Find and replace in files |
|
|
291
|
+
| `glob` | Find files by pattern |
|
|
292
|
+
| `grep` | Search file contents |
|
|
293
|
+
| `lsp` | Language Server Protocol operations |
|
|
294
|
+
| `web_search` | Search the web |
|
|
295
|
+
| `todo-read` | Read current todo list |
|
|
296
|
+
| `todo-write` | Update todo list |
|
|
289
297
|
|
|
290
298
|
### MCP Integration
|
|
291
299
|
|
|
@@ -311,6 +319,7 @@ Connect external MCP (Model Context Protocol) servers for extended capabilities:
|
|
|
311
319
|
```
|
|
312
320
|
|
|
313
321
|
**MCP Browser Features:**
|
|
322
|
+
|
|
314
323
|
- Search by name, description, or tags
|
|
315
324
|
- Filter by category (database, web, AI, etc.)
|
|
316
325
|
- View server details and required environment variables
|
|
@@ -324,6 +333,7 @@ Connect external MCP (Model Context Protocol) servers for extended capabilities:
|
|
|
324
333
|
Lifecycle hooks for intercepting tool execution and session events.
|
|
325
334
|
|
|
326
335
|
**Hook Events:**
|
|
336
|
+
|
|
327
337
|
- `PreToolUse` - Validate/modify before tool execution
|
|
328
338
|
- `PostToolUse` - Side effects after tool execution
|
|
329
339
|
- `SessionStart` - At session initialization
|
|
@@ -332,16 +342,22 @@ Lifecycle hooks for intercepting tool execution and session events.
|
|
|
332
342
|
- `Stop` - When execution stops
|
|
333
343
|
|
|
334
344
|
**Configuration** (`.codetyper/hooks.json`):
|
|
345
|
+
|
|
335
346
|
```json
|
|
336
347
|
{
|
|
337
348
|
"hooks": [
|
|
338
|
-
{
|
|
349
|
+
{
|
|
350
|
+
"event": "PreToolUse",
|
|
351
|
+
"script": ".codetyper/hooks/validate.sh",
|
|
352
|
+
"timeout": 5000
|
|
353
|
+
},
|
|
339
354
|
{ "event": "PostToolUse", "script": ".codetyper/hooks/notify.sh" }
|
|
340
355
|
]
|
|
341
356
|
}
|
|
342
357
|
```
|
|
343
358
|
|
|
344
359
|
**Exit Codes:**
|
|
360
|
+
|
|
345
361
|
- `0` - Allow (optionally output `{"updatedInput": {...}}` to modify args)
|
|
346
362
|
- `1` - Warn but continue
|
|
347
363
|
- `2` - Block execution
|
|
@@ -351,6 +367,7 @@ Lifecycle hooks for intercepting tool execution and session events.
|
|
|
351
367
|
Extend CodeTyper with custom tools, commands, and hooks.
|
|
352
368
|
|
|
353
369
|
**Plugin Structure:**
|
|
370
|
+
|
|
354
371
|
```
|
|
355
372
|
.codetyper/plugins/{name}/
|
|
356
373
|
├── plugin.json # Manifest
|
|
@@ -363,6 +380,7 @@ Extend CodeTyper with custom tools, commands, and hooks.
|
|
|
363
380
|
```
|
|
364
381
|
|
|
365
382
|
**Manifest** (`plugin.json`):
|
|
383
|
+
|
|
366
384
|
```json
|
|
367
385
|
{
|
|
368
386
|
"name": "my-plugin",
|
|
@@ -373,13 +391,18 @@ Extend CodeTyper with custom tools, commands, and hooks.
|
|
|
373
391
|
```
|
|
374
392
|
|
|
375
393
|
**Custom Tool Definition:**
|
|
394
|
+
|
|
376
395
|
```typescript
|
|
377
396
|
import { z } from "zod";
|
|
378
397
|
export default {
|
|
379
398
|
name: "custom_tool",
|
|
380
399
|
description: "Does something",
|
|
381
400
|
parameters: z.object({ input: z.string() }),
|
|
382
|
-
execute: async (args, ctx) => ({
|
|
401
|
+
execute: async (args, ctx) => ({
|
|
402
|
+
success: true,
|
|
403
|
+
title: "Done",
|
|
404
|
+
output: "...",
|
|
405
|
+
}),
|
|
383
406
|
};
|
|
384
407
|
```
|
|
385
408
|
|
|
@@ -404,12 +427,12 @@ Sessions are stored in `.codetyper/sessions/` with automatic commit message sugg
|
|
|
404
427
|
|
|
405
428
|
The next major release focuses on production-ready autonomous agent execution:
|
|
406
429
|
|
|
407
|
-
| Feature
|
|
408
|
-
|
|
409
|
-
| Plan Approval Gate
|
|
410
|
-
| Diff Preview Before Write
|
|
411
|
-
| Execution Control (Pause/Resume/Abort)
|
|
412
|
-
| Consistent Model Behavior
|
|
430
|
+
| Feature | Issue | Status |
|
|
431
|
+
| --------------------------------------- | ----------------------------------------------------------- | ------- |
|
|
432
|
+
| Plan Approval Gate | [#111](https://github.com/CarGDev/codetyper.cli/issues/111) | Planned |
|
|
433
|
+
| Diff Preview Before Write | [#112](https://github.com/CarGDev/codetyper.cli/issues/112) | Planned |
|
|
434
|
+
| Execution Control (Pause/Resume/Abort) | [#113](https://github.com/CarGDev/codetyper.cli/issues/113) | Planned |
|
|
435
|
+
| Consistent Model Behavior | [#114](https://github.com/CarGDev/codetyper.cli/issues/114) | Planned |
|
|
413
436
|
| Quality Gates (TypeScript, Lint, Tests) | [#115](https://github.com/CarGDev/codetyper.cli/issues/115) | Planned |
|
|
414
437
|
|
|
415
438
|
### Known Issues
|
|
@@ -439,11 +462,14 @@ bun test
|
|
|
439
462
|
bun run lint
|
|
440
463
|
```
|
|
441
464
|
|
|
442
|
-
## Recent Changes (v0.
|
|
465
|
+
## Recent Changes (v0.4.2)
|
|
443
466
|
|
|
444
|
-
- **
|
|
445
|
-
- **
|
|
446
|
-
-
|
|
467
|
+
- **Pink Purple Theme**: New built-in color theme
|
|
468
|
+
- **Image Paste Fix**: Fixed race condition where pasted images were silently dropped
|
|
469
|
+
- **@ and / Anywhere**: File picker and command menu now work at any cursor position
|
|
470
|
+
- **Plan Approval Gate**: User confirmation before agent executes plans
|
|
471
|
+
- **Execution Control**: Pause, resume, and abort agent execution
|
|
472
|
+
- **Text Clipboard Copy/Read**: Cross-platform clipboard operations with mouse selection
|
|
447
473
|
|
|
448
474
|
See [CHANGELOG](docs/CHANGELOG.md) for complete version history.
|
|
449
475
|
|
package/dist/index.js
CHANGED
|
@@ -36986,9 +36986,18 @@ var init_source4 = __esm(() => {
|
|
|
36986
36986
|
});
|
|
36987
36987
|
|
|
36988
36988
|
// src/constants/copilot.ts
|
|
36989
|
-
var COPILOT_PROVIDER_NAME = "copilot", COPILOT_DISPLAY_NAME = "GitHub Copilot", COPILOT_AUTH_URL = "https://api.github.com/copilot_internal/v2/token", COPILOT_MODELS_URL = "https://api.githubcopilot.com/models", GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98", GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code", GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token", COPILOT_MODELS_CACHE_TTL, COPILOT_MAX_RETRIES = 3, COPILOT_INITIAL_RETRY_DELAY = 1000, COPILOT_DEFAULT_MODEL = "gpt-5-mini", COPILOT_UNLIMITED_MODEL = "gpt-4o", MODEL_COST_MULTIPLIERS, UNLIMITED_MODELS, MODEL_CONTEXT_SIZES, DEFAULT_CONTEXT_SIZE, getModelContextSize = (modelId) => MODEL_CONTEXT_SIZES[modelId] ?? DEFAULT_CONTEXT_SIZE, COPILOT_FALLBACK_MODELS;
|
|
36989
|
+
var COPILOT_PROVIDER_NAME = "copilot", COPILOT_DISPLAY_NAME = "GitHub Copilot", COPILOT_AUTH_URL = "https://api.github.com/copilot_internal/v2/token", COPILOT_MODELS_URL = "https://api.githubcopilot.com/models", GITHUB_CLIENT_ID = "Iv1.b507a08c87ecfe98", GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code", GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token", COPILOT_MODELS_CACHE_TTL, COPILOT_MAX_RETRIES = 3, COPILOT_INITIAL_RETRY_DELAY = 1000, COPILOT_STREAM_TIMEOUT = 120000, COPILOT_CONNECTION_RETRY_DELAY = 2000, CONNECTION_ERROR_PATTERNS, COPILOT_DEFAULT_MODEL = "gpt-5-mini", COPILOT_UNLIMITED_MODEL = "gpt-4o", MODEL_COST_MULTIPLIERS, UNLIMITED_MODELS, MODEL_CONTEXT_SIZES, DEFAULT_CONTEXT_SIZE, getModelContextSize = (modelId) => MODEL_CONTEXT_SIZES[modelId] ?? DEFAULT_CONTEXT_SIZE, COPILOT_FALLBACK_MODELS;
|
|
36990
36990
|
var init_copilot = __esm(() => {
|
|
36991
36991
|
COPILOT_MODELS_CACHE_TTL = 5 * 60 * 1000;
|
|
36992
|
+
CONNECTION_ERROR_PATTERNS = [
|
|
36993
|
+
/socket.*closed/i,
|
|
36994
|
+
/ECONNRESET/i,
|
|
36995
|
+
/ECONNREFUSED/i,
|
|
36996
|
+
/ETIMEDOUT/i,
|
|
36997
|
+
/network.*error/i,
|
|
36998
|
+
/fetch.*failed/i,
|
|
36999
|
+
/aborted/i
|
|
37000
|
+
];
|
|
36992
37001
|
MODEL_COST_MULTIPLIERS = {
|
|
36993
37002
|
"gpt-4o": 0,
|
|
36994
37003
|
"gpt-4o-mini": 0,
|
|
@@ -37321,7 +37330,10 @@ var init_models = __esm(() => {
|
|
|
37321
37330
|
});
|
|
37322
37331
|
|
|
37323
37332
|
// src/providers/copilot/utils.ts
|
|
37324
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
37333
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), isConnectionError = (error2) => {
|
|
37334
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
37335
|
+
return CONNECTION_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
37336
|
+
}, isRateLimitError = (error2) => {
|
|
37325
37337
|
if (error2 && typeof error2 === "object" && "response" in error2) {
|
|
37326
37338
|
const response2 = error2.response;
|
|
37327
37339
|
return response2?.statusCode === 429;
|
|
@@ -66811,40 +66823,53 @@ var formatMessages = (messages) => messages.map((msg) => {
|
|
|
66811
66823
|
}
|
|
66812
66824
|
} catch {}
|
|
66813
66825
|
return false;
|
|
66814
|
-
}, executeStream = (endpoint, token, body, onChunk) =>
|
|
66815
|
-
const
|
|
66816
|
-
|
|
66817
|
-
|
|
66826
|
+
}, executeStream = async (endpoint, token, body, onChunk) => {
|
|
66827
|
+
const response2 = await fetch(endpoint, {
|
|
66828
|
+
method: "POST",
|
|
66829
|
+
headers: {
|
|
66830
|
+
...buildHeaders(token),
|
|
66831
|
+
Accept: "text/event-stream"
|
|
66832
|
+
},
|
|
66833
|
+
body: JSON.stringify(body),
|
|
66834
|
+
signal: AbortSignal.timeout(COPILOT_STREAM_TIMEOUT)
|
|
66818
66835
|
});
|
|
66836
|
+
if (!response2.ok) {
|
|
66837
|
+
throw new Error(`Copilot API error: ${response2.status} ${response2.statusText}`);
|
|
66838
|
+
}
|
|
66839
|
+
if (!response2.body) {
|
|
66840
|
+
throw new Error("No response body from Copilot stream");
|
|
66841
|
+
}
|
|
66842
|
+
const reader = response2.body.getReader();
|
|
66843
|
+
const decoder3 = new TextDecoder;
|
|
66819
66844
|
let buffer = "";
|
|
66820
66845
|
let doneReceived = false;
|
|
66821
|
-
|
|
66822
|
-
|
|
66823
|
-
|
|
66846
|
+
try {
|
|
66847
|
+
while (true) {
|
|
66848
|
+
const { done, value } = await reader.read();
|
|
66849
|
+
if (done)
|
|
66850
|
+
break;
|
|
66851
|
+
buffer += decoder3.decode(value, { stream: true });
|
|
66852
|
+
const lines = buffer.split(`
|
|
66824
66853
|
`);
|
|
66825
|
-
|
|
66826
|
-
|
|
66827
|
-
|
|
66828
|
-
|
|
66829
|
-
|
|
66854
|
+
buffer = lines.pop() ?? "";
|
|
66855
|
+
for (const line of lines) {
|
|
66856
|
+
if (processStreamLine(line, onChunk)) {
|
|
66857
|
+
doneReceived = true;
|
|
66858
|
+
return;
|
|
66859
|
+
}
|
|
66830
66860
|
}
|
|
66831
66861
|
}
|
|
66832
|
-
}
|
|
66833
|
-
|
|
66834
|
-
|
|
66835
|
-
|
|
66836
|
-
|
|
66837
|
-
|
|
66838
|
-
|
|
66839
|
-
|
|
66840
|
-
}
|
|
66841
|
-
|
|
66842
|
-
|
|
66843
|
-
onChunk({ type: "done" });
|
|
66844
|
-
}
|
|
66845
|
-
resolve3();
|
|
66846
|
-
});
|
|
66847
|
-
}), chatStream = async (messages, options2, onChunk) => {
|
|
66862
|
+
} finally {
|
|
66863
|
+
reader.releaseLock();
|
|
66864
|
+
}
|
|
66865
|
+
if (buffer.trim()) {
|
|
66866
|
+
processStreamLine(buffer, onChunk);
|
|
66867
|
+
}
|
|
66868
|
+
if (!doneReceived) {
|
|
66869
|
+
addDebugLog("api", "Stream ended without [DONE] message, sending done chunk");
|
|
66870
|
+
onChunk({ type: "done" });
|
|
66871
|
+
}
|
|
66872
|
+
}, chatStream = async (messages, options2, onChunk) => {
|
|
66848
66873
|
addDebugLog("api", `Copilot stream request: ${messages.length} messages`);
|
|
66849
66874
|
const token = await refreshToken();
|
|
66850
66875
|
const endpoint = getEndpoint(token);
|
|
@@ -66874,6 +66899,12 @@ var formatMessages = (messages) => messages.map((msg) => {
|
|
|
66874
66899
|
switchedToUnlimited = true;
|
|
66875
66900
|
continue;
|
|
66876
66901
|
}
|
|
66902
|
+
if (isConnectionError(error2) && attempt < COPILOT_MAX_RETRIES - 1) {
|
|
66903
|
+
const delay2 = COPILOT_CONNECTION_RETRY_DELAY * Math.pow(2, attempt);
|
|
66904
|
+
addDebugLog("api", `Connection error, retrying in ${delay2}ms (attempt ${attempt + 1})`);
|
|
66905
|
+
await sleep(delay2);
|
|
66906
|
+
continue;
|
|
66907
|
+
}
|
|
66877
66908
|
if (isRateLimitError(error2) && attempt < COPILOT_MAX_RETRIES - 1) {
|
|
66878
66909
|
const delay2 = getRetryDelay(error2, attempt);
|
|
66879
66910
|
await sleep(delay2);
|
|
@@ -67247,57 +67278,61 @@ var parseStreamLine = (line, onChunk) => {
|
|
|
67247
67278
|
onChunk({ type: "done" });
|
|
67248
67279
|
}
|
|
67249
67280
|
} catch {}
|
|
67250
|
-
}, processStreamData = (data, buffer, onChunk) => {
|
|
67251
|
-
const combined = buffer + data.toString();
|
|
67252
|
-
const lines = combined.split(`
|
|
67253
|
-
`);
|
|
67254
|
-
const remaining = lines.pop() || "";
|
|
67255
|
-
for (const line of lines) {
|
|
67256
|
-
parseStreamLine(line, onChunk);
|
|
67257
|
-
}
|
|
67258
|
-
return remaining;
|
|
67259
67281
|
}, ollamaChatStream = async (messages, options2, onChunk) => {
|
|
67260
67282
|
const baseUrl = getOllamaBaseUrl();
|
|
67261
67283
|
const body = buildChatRequest(messages, options2, true);
|
|
67262
67284
|
addDebugLog("api", `Ollama stream request: ${messages.length} msgs, model=${body.model}`);
|
|
67263
|
-
const
|
|
67264
|
-
|
|
67265
|
-
|
|
67285
|
+
const response2 = await fetch(`${baseUrl}${OLLAMA_ENDPOINTS.CHAT}`, {
|
|
67286
|
+
method: "POST",
|
|
67287
|
+
headers: { "Content-Type": "application/json" },
|
|
67288
|
+
body: JSON.stringify(body),
|
|
67289
|
+
signal: AbortSignal.timeout(OLLAMA_TIMEOUTS.CHAT)
|
|
67266
67290
|
});
|
|
67291
|
+
if (!response2.ok) {
|
|
67292
|
+
throw new Error(`Ollama API error: ${response2.status} ${response2.statusText}`);
|
|
67293
|
+
}
|
|
67294
|
+
if (!response2.body) {
|
|
67295
|
+
throw new Error("No response body from Ollama stream");
|
|
67296
|
+
}
|
|
67297
|
+
const reader = response2.body.getReader();
|
|
67298
|
+
const decoder3 = new TextDecoder;
|
|
67267
67299
|
let buffer = "";
|
|
67268
67300
|
let doneReceived = false;
|
|
67269
|
-
|
|
67270
|
-
|
|
67271
|
-
|
|
67272
|
-
|
|
67273
|
-
|
|
67274
|
-
|
|
67275
|
-
|
|
67276
|
-
|
|
67277
|
-
|
|
67278
|
-
|
|
67279
|
-
|
|
67280
|
-
return new Promise((resolve3, reject) => {
|
|
67281
|
-
stream2.on("end", () => {
|
|
67282
|
-
if (buffer.trim()) {
|
|
67283
|
-
parseStreamLine(buffer, (chunk2) => {
|
|
67301
|
+
try {
|
|
67302
|
+
while (true) {
|
|
67303
|
+
const { done, value } = await reader.read();
|
|
67304
|
+
if (done)
|
|
67305
|
+
break;
|
|
67306
|
+
buffer += decoder3.decode(value, { stream: true });
|
|
67307
|
+
const lines = buffer.split(`
|
|
67308
|
+
`);
|
|
67309
|
+
buffer = lines.pop() ?? "";
|
|
67310
|
+
for (const line of lines) {
|
|
67311
|
+
parseStreamLine(line, (chunk2) => {
|
|
67284
67312
|
if (chunk2.type === "done") {
|
|
67285
67313
|
doneReceived = true;
|
|
67286
67314
|
}
|
|
67287
67315
|
onChunk(chunk2);
|
|
67288
67316
|
});
|
|
67289
67317
|
}
|
|
67290
|
-
|
|
67291
|
-
|
|
67292
|
-
|
|
67318
|
+
}
|
|
67319
|
+
} finally {
|
|
67320
|
+
reader.releaseLock();
|
|
67321
|
+
}
|
|
67322
|
+
if (buffer.trim()) {
|
|
67323
|
+
parseStreamLine(buffer, (chunk2) => {
|
|
67324
|
+
if (chunk2.type === "done") {
|
|
67325
|
+
doneReceived = true;
|
|
67293
67326
|
}
|
|
67294
|
-
|
|
67327
|
+
onChunk(chunk2);
|
|
67295
67328
|
});
|
|
67296
|
-
|
|
67297
|
-
|
|
67329
|
+
}
|
|
67330
|
+
if (!doneReceived) {
|
|
67331
|
+
addDebugLog("api", "Ollama stream ended without done, sending done chunk");
|
|
67332
|
+
onChunk({ type: "done" });
|
|
67333
|
+
}
|
|
67298
67334
|
};
|
|
67299
67335
|
var init_stream2 = __esm(async () => {
|
|
67300
|
-
init_source4();
|
|
67301
67336
|
init_ollama();
|
|
67302
67337
|
init_state2();
|
|
67303
67338
|
init_chat2();
|
|
@@ -92500,56 +92535,58 @@ var activePlans, planListeners, COMPLEXITY_KEYWORDS, analyzeTask = (taskDescript
|
|
|
92500
92535
|
return activePlans.get(planId);
|
|
92501
92536
|
}, getActivePlans = () => {
|
|
92502
92537
|
return Array.from(activePlans.values()).filter((p) => p.status !== "completed" && p.status !== "failed" && p.status !== "rejected");
|
|
92503
|
-
}, formatPlanForDisplay = (plan) => {
|
|
92538
|
+
}, RISK_ICONS, formatPlanForDisplay = (plan) => {
|
|
92504
92539
|
const lines = [];
|
|
92505
|
-
lines.push(
|
|
92540
|
+
lines.push(`Plan to implement`);
|
|
92541
|
+
lines.push("");
|
|
92542
|
+
lines.push(plan.title);
|
|
92506
92543
|
lines.push("");
|
|
92507
|
-
lines.push(`## Summary`);
|
|
92508
92544
|
lines.push(plan.summary);
|
|
92509
92545
|
lines.push("");
|
|
92510
92546
|
if (plan.context.filesAnalyzed.length > 0) {
|
|
92511
|
-
lines.push(
|
|
92512
|
-
plan.context.filesAnalyzed.forEach((f) => lines.push(
|
|
92547
|
+
lines.push("Files Analyzed");
|
|
92548
|
+
plan.context.filesAnalyzed.forEach((f) => lines.push(` ${f}`));
|
|
92513
92549
|
lines.push("");
|
|
92514
92550
|
}
|
|
92515
92551
|
if (plan.context.currentArchitecture) {
|
|
92516
|
-
lines.push(
|
|
92517
|
-
lines.push(plan.context.currentArchitecture);
|
|
92552
|
+
lines.push("Current Architecture");
|
|
92553
|
+
lines.push(` ${plan.context.currentArchitecture}`);
|
|
92554
|
+
lines.push("");
|
|
92555
|
+
}
|
|
92556
|
+
if (plan.steps.length > 0) {
|
|
92557
|
+
lines.push("Implementation Steps");
|
|
92558
|
+
plan.steps.forEach((step, i2) => {
|
|
92559
|
+
const icon = RISK_ICONS[step.riskLevel] ?? " ";
|
|
92560
|
+
lines.push(` ${i2 + 1}. [${icon}] ${step.title}`);
|
|
92561
|
+
lines.push(` ${step.description}`);
|
|
92562
|
+
if (step.filesAffected.length > 0) {
|
|
92563
|
+
lines.push(` Files: ${step.filesAffected.join(", ")}`);
|
|
92564
|
+
}
|
|
92565
|
+
});
|
|
92518
92566
|
lines.push("");
|
|
92519
92567
|
}
|
|
92520
|
-
lines.push(`## Implementation Steps`);
|
|
92521
|
-
plan.steps.forEach((step, i2) => {
|
|
92522
|
-
const riskIcon = step.riskLevel === "high" ? "⚠️" : step.riskLevel === "medium" ? "⚡" : "✓";
|
|
92523
|
-
lines.push(`${i2 + 1}. ${riskIcon} **${step.title}**`);
|
|
92524
|
-
lines.push(` ${step.description}`);
|
|
92525
|
-
if (step.filesAffected.length > 0) {
|
|
92526
|
-
lines.push(` Files: ${step.filesAffected.join(", ")}`);
|
|
92527
|
-
}
|
|
92528
|
-
});
|
|
92529
|
-
lines.push("");
|
|
92530
92568
|
if (plan.risks.length > 0) {
|
|
92531
|
-
lines.push(
|
|
92569
|
+
lines.push("Risks");
|
|
92532
92570
|
plan.risks.forEach((risk) => {
|
|
92533
|
-
lines.push(
|
|
92534
|
-
lines.push(`
|
|
92571
|
+
lines.push(` [${risk.impact.toUpperCase()}] ${risk.description}`);
|
|
92572
|
+
lines.push(` Mitigation: ${risk.mitigation}`);
|
|
92535
92573
|
});
|
|
92536
92574
|
lines.push("");
|
|
92537
92575
|
}
|
|
92538
|
-
|
|
92539
|
-
|
|
92540
|
-
|
|
92541
|
-
|
|
92542
|
-
|
|
92543
|
-
|
|
92544
|
-
|
|
92545
|
-
|
|
92546
|
-
|
|
92547
|
-
|
|
92548
|
-
lines.push("");
|
|
92549
|
-
lines.push(
|
|
92550
|
-
lines.push(
|
|
92551
|
-
lines.push(
|
|
92552
|
-
lines.push("Reply with 'stop', 'cancel', or provide feedback to modify the plan.");
|
|
92576
|
+
if (plan.testingStrategy) {
|
|
92577
|
+
lines.push("Testing Strategy");
|
|
92578
|
+
lines.push(` ${plan.testingStrategy}`);
|
|
92579
|
+
lines.push("");
|
|
92580
|
+
}
|
|
92581
|
+
if (plan.rollbackPlan) {
|
|
92582
|
+
lines.push("Rollback Plan");
|
|
92583
|
+
lines.push(` ${plan.rollbackPlan}`);
|
|
92584
|
+
lines.push("");
|
|
92585
|
+
}
|
|
92586
|
+
lines.push("Estimated Changes");
|
|
92587
|
+
lines.push(` Files to create: ${plan.estimatedChanges.filesCreated}`);
|
|
92588
|
+
lines.push(` Files to modify: ${plan.estimatedChanges.filesModified}`);
|
|
92589
|
+
lines.push(` Files to delete: ${plan.estimatedChanges.filesDeleted}`);
|
|
92553
92590
|
return lines.join(`
|
|
92554
92591
|
`);
|
|
92555
92592
|
}, isApprovalMessage = (message) => {
|
|
@@ -92607,6 +92644,11 @@ var init_plan_service = __esm(() => {
|
|
|
92607
92644
|
"module"
|
|
92608
92645
|
]
|
|
92609
92646
|
};
|
|
92647
|
+
RISK_ICONS = {
|
|
92648
|
+
high: "!",
|
|
92649
|
+
medium: "~",
|
|
92650
|
+
low: " "
|
|
92651
|
+
};
|
|
92610
92652
|
});
|
|
92611
92653
|
|
|
92612
92654
|
// src/tools/plan-approval/execute.ts
|
|
@@ -93906,14 +93948,14 @@ var serviceState, callOllamaEmbed = async (texts, model) => {
|
|
|
93906
93948
|
}
|
|
93907
93949
|
} catch (error49) {
|
|
93908
93950
|
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
93909
|
-
const
|
|
93951
|
+
const isConnectionError2 = message.includes("ECONNREFUSED") || message.includes("connect");
|
|
93910
93952
|
serviceState = {
|
|
93911
93953
|
initialized: true,
|
|
93912
93954
|
model: null,
|
|
93913
93955
|
available: false,
|
|
93914
93956
|
error: {
|
|
93915
|
-
code:
|
|
93916
|
-
message:
|
|
93957
|
+
code: isConnectionError2 ? "OLLAMA_NOT_RUNNING" : "EMBEDDING_FAILED",
|
|
93958
|
+
message: isConnectionError2 ? "Ollama is not running. Start it with: ollama serve" : `Embedding service error: ${message}`
|
|
93917
93959
|
}
|
|
93918
93960
|
};
|
|
93919
93961
|
}
|
|
@@ -94067,7 +94109,7 @@ var init_semantic_search = __esm(() => {
|
|
|
94067
94109
|
var version_default;
|
|
94068
94110
|
var init_version = __esm(() => {
|
|
94069
94111
|
version_default = {
|
|
94070
|
-
version: "0.4.
|
|
94112
|
+
version: "0.4.2"
|
|
94071
94113
|
};
|
|
94072
94114
|
});
|
|
94073
94115
|
|
|
@@ -104147,6 +104189,9 @@ var initializeChatService = async (options2) => {
|
|
|
104147
104189
|
initializeBrain().catch(() => {});
|
|
104148
104190
|
return { state: state4, session };
|
|
104149
104191
|
};
|
|
104192
|
+
// src/services/chat-tui/message-handler.ts
|
|
104193
|
+
init_dist_node();
|
|
104194
|
+
|
|
104150
104195
|
// src/services/agent-stream.ts
|
|
104151
104196
|
init_dist_node();
|
|
104152
104197
|
init_tools3();
|
|
@@ -107321,6 +107366,46 @@ ${commentsContext}` : ""}`;
|
|
|
107321
107366
|
callbacks.onLog("system", formatted);
|
|
107322
107367
|
}
|
|
107323
107368
|
}
|
|
107369
|
+
const newPendingPlans = getActivePlans().filter((p) => p.status === "pending");
|
|
107370
|
+
if (newPendingPlans.length > 0) {
|
|
107371
|
+
const plan = newPendingPlans[0];
|
|
107372
|
+
const planContent = formatPlanForDisplay(plan);
|
|
107373
|
+
addDebugLog("state", `Showing plan approval modal: ${plan.id}`);
|
|
107374
|
+
await new Promise((resolve4) => {
|
|
107375
|
+
appStore.setMode("plan_approval");
|
|
107376
|
+
appStore.setPlanApprovalPrompt({
|
|
107377
|
+
id: v4_default(),
|
|
107378
|
+
planTitle: plan.title,
|
|
107379
|
+
planSummary: plan.summary,
|
|
107380
|
+
planContent,
|
|
107381
|
+
resolve: (response2) => {
|
|
107382
|
+
appStore.setPlanApprovalPrompt(null);
|
|
107383
|
+
if (response2.approved) {
|
|
107384
|
+
approvePlan(plan.id, response2.editMode);
|
|
107385
|
+
startPlanExecution(plan.id);
|
|
107386
|
+
addDebugLog("state", `Plan ${plan.id} approved via modal`);
|
|
107387
|
+
appStore.addLog({
|
|
107388
|
+
type: "system",
|
|
107389
|
+
content: `Plan "${plan.title}" approved. Proceeding with implementation.`
|
|
107390
|
+
});
|
|
107391
|
+
state4.messages.push({
|
|
107392
|
+
role: "user",
|
|
107393
|
+
content: `The user approved the plan. Proceed with the implementation of plan "${plan.title}".`
|
|
107394
|
+
});
|
|
107395
|
+
} else {
|
|
107396
|
+
rejectPlan(plan.id, response2.feedback ?? "User cancelled");
|
|
107397
|
+
addDebugLog("state", `Plan ${plan.id} rejected via modal`);
|
|
107398
|
+
appStore.addLog({
|
|
107399
|
+
type: "system",
|
|
107400
|
+
content: `Plan "${plan.title}" cancelled.`
|
|
107401
|
+
});
|
|
107402
|
+
}
|
|
107403
|
+
appStore.setMode("idle");
|
|
107404
|
+
resolve4();
|
|
107405
|
+
}
|
|
107406
|
+
});
|
|
107407
|
+
});
|
|
107408
|
+
}
|
|
107324
107409
|
} catch (error49) {
|
|
107325
107410
|
appStore.cancelStreaming();
|
|
107326
107411
|
appStore.stopThinking();
|
|
@@ -108095,6 +108180,51 @@ var getFiles = (dir, cwd, maxDepth = FILE_PICKER_DEFAULTS.MAX_DEPTH, currentDept
|
|
|
108095
108180
|
// src/tui-solid/app.tsx
|
|
108096
108181
|
init_terminal();
|
|
108097
108182
|
|
|
108183
|
+
// src/services/exit-message.ts
|
|
108184
|
+
import { EOL } from "os";
|
|
108185
|
+
|
|
108186
|
+
// src/constants/exit-message.ts
|
|
108187
|
+
var EXIT_LOGO = [
|
|
108188
|
+
"█▀▀█",
|
|
108189
|
+
"█ █",
|
|
108190
|
+
"▀▀▀▀"
|
|
108191
|
+
];
|
|
108192
|
+
var EXIT_STYLES = {
|
|
108193
|
+
RESET: "\x1B[0m",
|
|
108194
|
+
DIM: "\x1B[90m",
|
|
108195
|
+
HIGHLIGHT: "\x1B[96m",
|
|
108196
|
+
BOLD: "\x1B[1m",
|
|
108197
|
+
LOGO_COLOR: "\x1B[36m"
|
|
108198
|
+
};
|
|
108199
|
+
var EXIT_DESCRIPTION_MAX_WIDTH = 50;
|
|
108200
|
+
var EXIT_LINE_PADDING = " ";
|
|
108201
|
+
var EXIT_LOGO_GAP = " ";
|
|
108202
|
+
var EXIT_TRUNCATION_MARKER = "…";
|
|
108203
|
+
|
|
108204
|
+
// src/services/exit-message.ts
|
|
108205
|
+
var truncateText = (text, maxWidth) => {
|
|
108206
|
+
if (text.length <= maxWidth)
|
|
108207
|
+
return text;
|
|
108208
|
+
return text.slice(0, maxWidth - 1) + EXIT_TRUNCATION_MARKER;
|
|
108209
|
+
};
|
|
108210
|
+
var formatExitMessage = (sessionId, sessionTitle) => {
|
|
108211
|
+
if (!sessionId)
|
|
108212
|
+
return "";
|
|
108213
|
+
const { RESET, DIM, HIGHLIGHT, LOGO_COLOR } = EXIT_STYLES;
|
|
108214
|
+
const pad = EXIT_LINE_PADDING;
|
|
108215
|
+
const gap = EXIT_LOGO_GAP;
|
|
108216
|
+
const description = sessionTitle ? truncateText(sessionTitle, EXIT_DESCRIPTION_MAX_WIDTH) : "";
|
|
108217
|
+
const resumeCommand = `codetyper --resume ${sessionId}`;
|
|
108218
|
+
const lines = [
|
|
108219
|
+
"",
|
|
108220
|
+
`${pad}${LOGO_COLOR}${EXIT_LOGO[0]}${RESET}${gap}${HIGHLIGHT}${description}${RESET}`,
|
|
108221
|
+
`${pad}${LOGO_COLOR}${EXIT_LOGO[1]}${RESET}${gap}${DIM}${resumeCommand}${RESET}`,
|
|
108222
|
+
`${pad}${LOGO_COLOR}${EXIT_LOGO[2]}${RESET}`,
|
|
108223
|
+
""
|
|
108224
|
+
];
|
|
108225
|
+
return lines.join(EOL);
|
|
108226
|
+
};
|
|
108227
|
+
|
|
108098
108228
|
// src/constants/clipboard.ts
|
|
108099
108229
|
var OSC52_SEQUENCE_PREFIX = "\x1B]52;c;";
|
|
108100
108230
|
var OSC52_SEQUENCE_SUFFIX = "\x07";
|
|
@@ -113252,92 +113382,106 @@ function PlanApprovalModal(props) {
|
|
|
113252
113382
|
}
|
|
113253
113383
|
});
|
|
113254
113384
|
return (() => {
|
|
113255
|
-
var _el$ = createElement("box"), _el$
|
|
113256
|
-
insertNode(_el$, _el$
|
|
113385
|
+
var _el$ = createElement("box"), _el$8 = createElement("box"), _el$9 = createElement("text");
|
|
113386
|
+
insertNode(_el$, _el$8);
|
|
113257
113387
|
setProp(_el$, "flexDirection", "column");
|
|
113258
113388
|
setProp(_el$, "border", ["top", "bottom", "left", "right"]);
|
|
113259
113389
|
setProp(_el$, "paddingLeft", 2);
|
|
113260
113390
|
setProp(_el$, "paddingRight", 2);
|
|
113261
113391
|
setProp(_el$, "paddingTop", 1);
|
|
113262
113392
|
setProp(_el$, "paddingBottom", 1);
|
|
113263
|
-
insertNode(_el$2, _el$3);
|
|
113264
|
-
setProp(_el$2, "marginBottom", 1);
|
|
113265
|
-
insertNode(_el$3, createTextNode(`CodeTyper has written up a plan and is ready to execute. Would you like to proceed?`));
|
|
113266
113393
|
insert(_el$, createComponent2(Show, {
|
|
113267
113394
|
get when() {
|
|
113268
|
-
return props.prompt.
|
|
113395
|
+
return props.prompt.planContent;
|
|
113396
|
+
},
|
|
113397
|
+
get children() {
|
|
113398
|
+
var _el$2 = createElement("box"), _el$3 = createElement("text");
|
|
113399
|
+
insertNode(_el$2, _el$3);
|
|
113400
|
+
setProp(_el$2, "marginBottom", 1);
|
|
113401
|
+
setProp(_el$2, "flexDirection", "column");
|
|
113402
|
+
insert(_el$3, () => props.prompt.planContent);
|
|
113403
|
+
effect((_$p) => setProp(_el$3, "fg", theme.colors.text, _$p));
|
|
113404
|
+
return _el$2;
|
|
113405
|
+
}
|
|
113406
|
+
}), _el$8);
|
|
113407
|
+
insert(_el$, createComponent2(Show, {
|
|
113408
|
+
get when() {
|
|
113409
|
+
return memo2(() => !!!props.prompt.planContent)() && props.prompt.planTitle;
|
|
113269
113410
|
},
|
|
113270
113411
|
get children() {
|
|
113271
|
-
var _el$
|
|
113272
|
-
insertNode(_el$
|
|
113273
|
-
setProp(_el$
|
|
113274
|
-
insert(_el$
|
|
113412
|
+
var _el$4 = createElement("box"), _el$5 = createElement("text");
|
|
113413
|
+
insertNode(_el$4, _el$5);
|
|
113414
|
+
setProp(_el$4, "marginBottom", 1);
|
|
113415
|
+
insert(_el$5, () => props.prompt.planTitle);
|
|
113275
113416
|
effect((_p$) => {
|
|
113276
113417
|
var _v$ = theme.colors.text, _v$2 = TextAttributes.BOLD;
|
|
113277
|
-
_v$ !== _p$.e && (_p$.e = setProp(_el$
|
|
113278
|
-
_v$2 !== _p$.t && (_p$.t = setProp(_el$
|
|
113418
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$5, "fg", _v$, _p$.e));
|
|
113419
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$5, "attributes", _v$2, _p$.t));
|
|
113279
113420
|
return _p$;
|
|
113280
113421
|
}, {
|
|
113281
113422
|
e: undefined,
|
|
113282
113423
|
t: undefined
|
|
113283
113424
|
});
|
|
113284
|
-
return _el$
|
|
113425
|
+
return _el$4;
|
|
113285
113426
|
}
|
|
113286
|
-
}),
|
|
113427
|
+
}), _el$8);
|
|
113287
113428
|
insert(_el$, createComponent2(Show, {
|
|
113288
113429
|
get when() {
|
|
113289
|
-
return props.prompt.planSummary;
|
|
113430
|
+
return memo2(() => !!!props.prompt.planContent)() && props.prompt.planSummary;
|
|
113290
113431
|
},
|
|
113291
113432
|
get children() {
|
|
113292
|
-
var _el$
|
|
113293
|
-
insertNode(_el$
|
|
113294
|
-
setProp(_el$
|
|
113295
|
-
insert(_el$
|
|
113296
|
-
effect((_$p) => setProp(_el$
|
|
113297
|
-
return _el$
|
|
113433
|
+
var _el$6 = createElement("box"), _el$7 = createElement("text");
|
|
113434
|
+
insertNode(_el$6, _el$7);
|
|
113435
|
+
setProp(_el$6, "marginBottom", 1);
|
|
113436
|
+
insert(_el$7, () => props.prompt.planSummary);
|
|
113437
|
+
effect((_$p) => setProp(_el$7, "fg", theme.colors.textDim, _$p));
|
|
113438
|
+
return _el$6;
|
|
113298
113439
|
}
|
|
113299
|
-
}),
|
|
113440
|
+
}), _el$8);
|
|
113441
|
+
insertNode(_el$8, _el$9);
|
|
113442
|
+
setProp(_el$8, "marginBottom", 1);
|
|
113443
|
+
insertNode(_el$9, createTextNode(`Would you like to proceed with this plan?`));
|
|
113300
113444
|
insert(_el$, createComponent2(Show, {
|
|
113301
113445
|
get when() {
|
|
113302
113446
|
return !feedbackMode();
|
|
113303
113447
|
},
|
|
113304
113448
|
get children() {
|
|
113305
|
-
var _el$
|
|
113306
|
-
setProp(_el$
|
|
113307
|
-
setProp(_el$
|
|
113308
|
-
insert(_el$
|
|
113449
|
+
var _el$1 = createElement("box");
|
|
113450
|
+
setProp(_el$1, "flexDirection", "column");
|
|
113451
|
+
setProp(_el$1, "marginTop", 1);
|
|
113452
|
+
insert(_el$1, createComponent2(For, {
|
|
113309
113453
|
each: PLAN_APPROVAL_OPTIONS,
|
|
113310
113454
|
children: (option, index) => {
|
|
113311
113455
|
const isSelected = () => index() === selectedIndex();
|
|
113312
113456
|
return (() => {
|
|
113313
|
-
var _el$
|
|
113314
|
-
insertNode(_el$23, _el$24);
|
|
113315
|
-
insertNode(_el$23, _el$25);
|
|
113316
|
-
insertNode(_el$23, _el$27);
|
|
113317
|
-
setProp(_el$23, "flexDirection", "row");
|
|
113318
|
-
insert(_el$24, () => isSelected() ? "> " : " ");
|
|
113457
|
+
var _el$25 = createElement("box"), _el$26 = createElement("text"), _el$27 = createElement("text"), _el$28 = createTextNode(`. `), _el$29 = createElement("text");
|
|
113319
113458
|
insertNode(_el$25, _el$26);
|
|
113320
|
-
|
|
113321
|
-
|
|
113322
|
-
|
|
113459
|
+
insertNode(_el$25, _el$27);
|
|
113460
|
+
insertNode(_el$25, _el$29);
|
|
113461
|
+
setProp(_el$25, "flexDirection", "row");
|
|
113462
|
+
insert(_el$26, () => isSelected() ? "> " : " ");
|
|
113463
|
+
insertNode(_el$27, _el$28);
|
|
113464
|
+
insert(_el$27, () => option.key, _el$28);
|
|
113465
|
+
insert(_el$29, () => option.label);
|
|
113466
|
+
insert(_el$25, createComponent2(Show, {
|
|
113323
113467
|
get when() {
|
|
113324
113468
|
return option.shortcut;
|
|
113325
113469
|
},
|
|
113326
113470
|
get children() {
|
|
113327
|
-
var _el$
|
|
113328
|
-
insertNode(_el$
|
|
113329
|
-
insertNode(_el$
|
|
113330
|
-
insert(_el$
|
|
113331
|
-
effect((_$p) => setProp(_el$
|
|
113332
|
-
return _el$
|
|
113471
|
+
var _el$30 = createElement("text"), _el$31 = createTextNode(` (`), _el$33 = createTextNode(`)`);
|
|
113472
|
+
insertNode(_el$30, _el$31);
|
|
113473
|
+
insertNode(_el$30, _el$33);
|
|
113474
|
+
insert(_el$30, () => option.shortcut, _el$33);
|
|
113475
|
+
effect((_$p) => setProp(_el$30, "fg", theme.colors.textMuted, _$p));
|
|
113476
|
+
return _el$30;
|
|
113333
113477
|
}
|
|
113334
113478
|
}), null);
|
|
113335
113479
|
effect((_p$) => {
|
|
113336
113480
|
var _v$10 = isSelected() ? theme.colors.primary : theme.colors.textDim, _v$11 = isSelected() ? TextAttributes.BOLD : TextAttributes.NONE, _v$12 = theme.colors.textDim, _v$13 = isSelected() ? theme.colors.text : theme.colors.textDim;
|
|
113337
|
-
_v$10 !== _p$.e && (_p$.e = setProp(_el$
|
|
113338
|
-
_v$11 !== _p$.t && (_p$.t = setProp(_el$
|
|
113339
|
-
_v$12 !== _p$.a && (_p$.a = setProp(_el$
|
|
113340
|
-
_v$13 !== _p$.o && (_p$.o = setProp(_el$
|
|
113481
|
+
_v$10 !== _p$.e && (_p$.e = setProp(_el$26, "fg", _v$10, _p$.e));
|
|
113482
|
+
_v$11 !== _p$.t && (_p$.t = setProp(_el$26, "attributes", _v$11, _p$.t));
|
|
113483
|
+
_v$12 !== _p$.a && (_p$.a = setProp(_el$27, "fg", _v$12, _p$.a));
|
|
113484
|
+
_v$13 !== _p$.o && (_p$.o = setProp(_el$29, "fg", _v$13, _p$.o));
|
|
113341
113485
|
return _p$;
|
|
113342
113486
|
}, {
|
|
113343
113487
|
e: undefined,
|
|
@@ -113345,11 +113489,11 @@ function PlanApprovalModal(props) {
|
|
|
113345
113489
|
a: undefined,
|
|
113346
113490
|
o: undefined
|
|
113347
113491
|
});
|
|
113348
|
-
return _el$
|
|
113492
|
+
return _el$25;
|
|
113349
113493
|
})();
|
|
113350
113494
|
}
|
|
113351
113495
|
}));
|
|
113352
|
-
return _el$
|
|
113496
|
+
return _el$1;
|
|
113353
113497
|
}
|
|
113354
113498
|
}), null);
|
|
113355
113499
|
insert(_el$, createComponent2(Show, {
|
|
@@ -113357,28 +113501,28 @@ function PlanApprovalModal(props) {
|
|
|
113357
113501
|
return feedbackMode();
|
|
113358
113502
|
},
|
|
113359
113503
|
get children() {
|
|
113360
|
-
var _el$
|
|
113361
|
-
insertNode(_el$
|
|
113362
|
-
insertNode(_el$
|
|
113363
|
-
insertNode(_el$
|
|
113364
|
-
setProp(_el$
|
|
113365
|
-
setProp(_el$
|
|
113366
|
-
insertNode(_el$
|
|
113367
|
-
insertNode(_el$
|
|
113368
|
-
setProp(_el$
|
|
113369
|
-
setProp(_el$
|
|
113370
|
-
setProp(_el$
|
|
113371
|
-
insertNode(_el$
|
|
113372
|
-
insert(_el$
|
|
113373
|
-
insertNode(_el$
|
|
113374
|
-
insertNode(_el$
|
|
113504
|
+
var _el$10 = createElement("box"), _el$11 = createElement("text"), _el$13 = createElement("box"), _el$14 = createElement("text"), _el$15 = createElement("text"), _el$17 = createElement("text");
|
|
113505
|
+
insertNode(_el$10, _el$11);
|
|
113506
|
+
insertNode(_el$10, _el$13);
|
|
113507
|
+
insertNode(_el$10, _el$17);
|
|
113508
|
+
setProp(_el$10, "flexDirection", "column");
|
|
113509
|
+
setProp(_el$10, "marginTop", 1);
|
|
113510
|
+
insertNode(_el$11, createTextNode(`Tell CodeTyper what to change:`));
|
|
113511
|
+
insertNode(_el$13, _el$14);
|
|
113512
|
+
setProp(_el$13, "border", ["left"]);
|
|
113513
|
+
setProp(_el$13, "paddingLeft", 1);
|
|
113514
|
+
setProp(_el$13, "marginTop", 1);
|
|
113515
|
+
insertNode(_el$14, _el$15);
|
|
113516
|
+
insert(_el$14, () => feedbackText() || " ", _el$15);
|
|
113517
|
+
insertNode(_el$15, createTextNode(`_`));
|
|
113518
|
+
insertNode(_el$17, createTextNode(`Enter to submit | Esc to cancel`));
|
|
113375
113519
|
effect((_p$) => {
|
|
113376
113520
|
var _v$3 = theme.colors.text, _v$4 = theme.colors.borderFocus, _v$5 = theme.colors.text, _v$6 = theme.colors.bgCursor, _v$7 = theme.colors.textDim;
|
|
113377
|
-
_v$3 !== _p$.e && (_p$.e = setProp(_el$
|
|
113378
|
-
_v$4 !== _p$.t && (_p$.t = setProp(_el$
|
|
113379
|
-
_v$5 !== _p$.a && (_p$.a = setProp(_el$
|
|
113380
|
-
_v$6 !== _p$.o && (_p$.o = setProp(_el$
|
|
113381
|
-
_v$7 !== _p$.i && (_p$.i = setProp(_el$
|
|
113521
|
+
_v$3 !== _p$.e && (_p$.e = setProp(_el$11, "fg", _v$3, _p$.e));
|
|
113522
|
+
_v$4 !== _p$.t && (_p$.t = setProp(_el$13, "borderColor", _v$4, _p$.t));
|
|
113523
|
+
_v$5 !== _p$.a && (_p$.a = setProp(_el$14, "fg", _v$5, _p$.a));
|
|
113524
|
+
_v$6 !== _p$.o && (_p$.o = setProp(_el$15, "fg", _v$6, _p$.o));
|
|
113525
|
+
_v$7 !== _p$.i && (_p$.i = setProp(_el$17, "fg", _v$7, _p$.i));
|
|
113382
113526
|
return _p$;
|
|
113383
113527
|
}, {
|
|
113384
113528
|
e: undefined,
|
|
@@ -113387,7 +113531,7 @@ function PlanApprovalModal(props) {
|
|
|
113387
113531
|
o: undefined,
|
|
113388
113532
|
i: undefined
|
|
113389
113533
|
});
|
|
113390
|
-
return _el$
|
|
113534
|
+
return _el$10;
|
|
113391
113535
|
}
|
|
113392
113536
|
}), null);
|
|
113393
113537
|
insert(_el$, createComponent2(Show, {
|
|
@@ -113395,42 +113539,42 @@ function PlanApprovalModal(props) {
|
|
|
113395
113539
|
return !feedbackMode();
|
|
113396
113540
|
},
|
|
113397
113541
|
get children() {
|
|
113398
|
-
var _el$
|
|
113399
|
-
setProp(_el$
|
|
113400
|
-
setProp(_el$
|
|
113401
|
-
insert(_el$
|
|
113542
|
+
var _el$19 = createElement("box");
|
|
113543
|
+
setProp(_el$19, "marginTop", 1);
|
|
113544
|
+
setProp(_el$19, "flexDirection", "row");
|
|
113545
|
+
insert(_el$19, createComponent2(Show, {
|
|
113402
113546
|
get when() {
|
|
113403
113547
|
return props.prompt.planFilePath;
|
|
113404
113548
|
},
|
|
113405
113549
|
get children() {
|
|
113406
|
-
var _el$
|
|
113407
|
-
insertNode(_el$
|
|
113408
|
-
insert(_el$
|
|
113409
|
-
insert(_el$
|
|
113410
|
-
effect((_$p) => setProp(_el$
|
|
113411
|
-
return _el$
|
|
113550
|
+
var _el$20 = createElement("text"), _el$21 = createTextNode(` - `);
|
|
113551
|
+
insertNode(_el$20, _el$21);
|
|
113552
|
+
insert(_el$20, PLAN_APPROVAL_FOOTER_TEXT, _el$21);
|
|
113553
|
+
insert(_el$20, () => props.prompt.planFilePath, null);
|
|
113554
|
+
effect((_$p) => setProp(_el$20, "fg", theme.colors.textDim, _$p));
|
|
113555
|
+
return _el$20;
|
|
113412
113556
|
}
|
|
113413
113557
|
}), null);
|
|
113414
|
-
insert(_el$
|
|
113558
|
+
insert(_el$19, createComponent2(Show, {
|
|
113415
113559
|
get when() {
|
|
113416
113560
|
return !props.prompt.planFilePath;
|
|
113417
113561
|
},
|
|
113418
113562
|
get children() {
|
|
113419
|
-
var _el$
|
|
113420
|
-
insertNode(_el$
|
|
113421
|
-
effect((_$p) => setProp(_el$
|
|
113422
|
-
return _el$
|
|
113563
|
+
var _el$22 = createElement("text"), _el$23 = createTextNode(`↑↓ options | Enter select | 1-4 shortcut | Esc cancel`);
|
|
113564
|
+
insertNode(_el$22, _el$23);
|
|
113565
|
+
effect((_$p) => setProp(_el$22, "fg", theme.colors.textDim, _$p));
|
|
113566
|
+
return _el$22;
|
|
113423
113567
|
}
|
|
113424
113568
|
}), null);
|
|
113425
|
-
return _el$
|
|
113569
|
+
return _el$19;
|
|
113426
113570
|
}
|
|
113427
113571
|
}), null);
|
|
113428
113572
|
effect((_p$) => {
|
|
113429
113573
|
var _v$8 = theme.colors.borderModal, _v$9 = theme.colors.background, _v$0 = theme.colors.primary, _v$1 = TextAttributes.BOLD;
|
|
113430
113574
|
_v$8 !== _p$.e && (_p$.e = setProp(_el$, "borderColor", _v$8, _p$.e));
|
|
113431
113575
|
_v$9 !== _p$.t && (_p$.t = setProp(_el$, "backgroundColor", _v$9, _p$.t));
|
|
113432
|
-
_v$0 !== _p$.a && (_p$.a = setProp(_el$
|
|
113433
|
-
_v$1 !== _p$.o && (_p$.o = setProp(_el$
|
|
113576
|
+
_v$0 !== _p$.a && (_p$.a = setProp(_el$9, "fg", _v$0, _p$.a));
|
|
113577
|
+
_v$1 !== _p$.o && (_p$.o = setProp(_el$9, "attributes", _v$1, _p$.o));
|
|
113434
113578
|
return _p$;
|
|
113435
113579
|
}, {
|
|
113436
113580
|
e: undefined,
|
|
@@ -115436,6 +115580,7 @@ function AppContent(props) {
|
|
|
115436
115580
|
const toast = useToast();
|
|
115437
115581
|
const theme = useTheme();
|
|
115438
115582
|
const renderer = useRenderer();
|
|
115583
|
+
renderer.disableStdoutInterception();
|
|
115439
115584
|
const [fileList, setFileList] = createSignal([]);
|
|
115440
115585
|
setAppStoreRef(app);
|
|
115441
115586
|
const copySelectionToClipboard = async () => {
|
|
@@ -115634,6 +115779,10 @@ function AppContent(props) {
|
|
|
115634
115779
|
props.onPermissionResponse(allowed, scope);
|
|
115635
115780
|
};
|
|
115636
115781
|
const handlePlanApprovalResponse = (response2) => {
|
|
115782
|
+
const prompt2 = app.planApprovalPrompt();
|
|
115783
|
+
if (prompt2?.resolve) {
|
|
115784
|
+
prompt2.resolve(response2);
|
|
115785
|
+
}
|
|
115637
115786
|
props.onPlanApprovalResponse(response2);
|
|
115638
115787
|
};
|
|
115639
115788
|
const handleLearningResponse = (save, scope, editedContent) => {
|
|
@@ -115818,6 +115967,13 @@ function tui(options2) {
|
|
|
115818
115967
|
const handleExit = (output) => {
|
|
115819
115968
|
try {
|
|
115820
115969
|
writeSync2(1, TERMINAL_RESET);
|
|
115970
|
+
const state4 = appStore.getState();
|
|
115971
|
+
const firstUserLog = state4?.logs?.find((log2) => log2.type === "user");
|
|
115972
|
+
const sessionTitle = firstUserLog?.content;
|
|
115973
|
+
const exitMsg = formatExitMessage(output.sessionId, sessionTitle);
|
|
115974
|
+
if (exitMsg) {
|
|
115975
|
+
writeSync2(1, exitMsg);
|
|
115976
|
+
}
|
|
115821
115977
|
} catch {}
|
|
115822
115978
|
resolve4(output);
|
|
115823
115979
|
};
|
|
@@ -115826,8 +115982,7 @@ function tui(options2) {
|
|
|
115826
115982
|
})), {
|
|
115827
115983
|
targetFps: 60,
|
|
115828
115984
|
exitOnCtrlC: false,
|
|
115829
|
-
useKittyKeyboard: {}
|
|
115830
|
-
useMouse: true
|
|
115985
|
+
useKittyKeyboard: {}
|
|
115831
115986
|
});
|
|
115832
115987
|
});
|
|
115833
115988
|
}
|
|
@@ -117071,4 +117226,4 @@ ${plan.steps.map((s) => `${s.id}. ${s.description}`).join(`
|
|
|
117071
117226
|
});
|
|
117072
117227
|
program2.parse(process.argv);
|
|
117073
117228
|
|
|
117074
|
-
//# debugId=
|
|
117229
|
+
//# debugId=07E4A86E6DD680D764756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codetyper-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "CodeTyper AI Agent - Standalone CLI for autonomous code generation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,9 +10,6 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"dev": "bun src/index.ts",
|
|
12
12
|
"dev:nobump": "bun scripts/build.ts && npm link",
|
|
13
|
-
"dev:watch": "bun scripts/dev-watch.ts",
|
|
14
|
-
"dev:debug": "bun --inspect=localhost:6499/debug src/index.ts",
|
|
15
|
-
"dev:debug-brk": "bun --inspect-brk=localhost:6499/debug src/index.ts",
|
|
16
13
|
"build": "bun scripts/build.ts",
|
|
17
14
|
"sync-version": "bun scripts/sync-version.ts",
|
|
18
15
|
"start": "bun src/index.ts",
|
|
@@ -20,7 +17,8 @@
|
|
|
20
17
|
"lint": "bun eslint src/**/*.ts",
|
|
21
18
|
"format": "npx prettier --write \"src/**/*.ts\"",
|
|
22
19
|
"prettier": "npx prettier --write \"src/**/*.ts\" \"src/**/*.tsx\" \"scripts/**/*.ts\"",
|
|
23
|
-
"typecheck": "bun tsc --noEmit"
|
|
20
|
+
"typecheck": "bun tsc --noEmit",
|
|
21
|
+
"version": "bun scripts/sync-version.ts && git add src/version.json"
|
|
24
22
|
},
|
|
25
23
|
"keywords": [
|
|
26
24
|
"ai",
|
|
@@ -78,13 +76,13 @@
|
|
|
78
76
|
},
|
|
79
77
|
"devDependencies": {
|
|
80
78
|
"@eslint/eslintrc": "^3.3.3",
|
|
81
|
-
"@eslint/js": "^
|
|
79
|
+
"@eslint/js": "^10.0.1",
|
|
82
80
|
"@types/inquirer": "^9.0.7",
|
|
83
81
|
"@types/node": "^25.0.10",
|
|
84
82
|
"@types/uuid": "^10.0.0",
|
|
85
83
|
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
|
86
84
|
"@typescript-eslint/parser": "^8.53.1",
|
|
87
|
-
"eslint": "^
|
|
85
|
+
"eslint": "^10.0.0",
|
|
88
86
|
"eslint-config-standard": "^17.1.0",
|
|
89
87
|
"eslint-config-standard-with-typescript": "^43.0.1",
|
|
90
88
|
"eslint-plugin-import": "^2.32.0",
|
package/src/version.json
CHANGED