codehere 0.2.2 → 0.3.0-rc.2
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 +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +253 -1219
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +272 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +9 -38
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +321 -30
- package/dist/presentation/cli/commands/trust-command.js +84 -72
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/ui.js +11 -11
- package/package.json +24 -62
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -534
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -704
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
package/dist/session.js
DELETED
|
@@ -1,704 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interactive Session — the main codehere experience
|
|
3
|
-
*
|
|
4
|
-
* Uses raw stdin for live command palette.
|
|
5
|
-
* Pattern copied from test-real.mjs which is verified working.
|
|
6
|
-
*/
|
|
7
|
-
import { existsSync, readdirSync, readFileSync } from 'fs';
|
|
8
|
-
import { join, basename } from 'path';
|
|
9
|
-
import ora from 'ora';
|
|
10
|
-
import chalk from 'chalk';
|
|
11
|
-
// Brand colors
|
|
12
|
-
const brandBlue = chalk.rgb(74, 144, 226); // #4a90e2
|
|
13
|
-
const brandCoral = chalk.rgb(255, 154, 118); // #ff9a76
|
|
14
|
-
import { chatWithContextStream } from './chat.js';
|
|
15
|
-
import { createMarkdownStream } from './infrastructure/ux/stream-markdown.js';
|
|
16
|
-
import { reviewFile } from './review.js';
|
|
17
|
-
import { planTask, formatPlan } from './planner.js';
|
|
18
|
-
import { IntelligentRouter } from './application/services/intelligent-router.js';
|
|
19
|
-
import { colors, error, warning, createCodehereLogo, SLASH_COMMANDS, } from './ui.js';
|
|
20
|
-
import { getVersion } from './utils/version.js';
|
|
21
|
-
const stdin = process.stdin;
|
|
22
|
-
const stdout = process.stdout;
|
|
23
|
-
// Build palette command list from SLASH_COMMANDS
|
|
24
|
-
const PALETTE_CMDS = SLASH_COMMANDS.map(c => ({
|
|
25
|
-
sig: `/${c.name}${c.args ? ' ' + c.args : ''}`,
|
|
26
|
-
name: c.name,
|
|
27
|
-
desc: c.description,
|
|
28
|
-
noKey: c.noKey,
|
|
29
|
-
}));
|
|
30
|
-
// Dynamic: leave room for prompt + header lines
|
|
31
|
-
function maxPalette() {
|
|
32
|
-
const rows = process.stdout.rows || 24;
|
|
33
|
-
return Math.min(rows - 8, 20); // 8 lines reserved for header/prompt/footer
|
|
34
|
-
}
|
|
35
|
-
// ── State detection ─────────────────────────────────────────────────────────
|
|
36
|
-
function detectState() {
|
|
37
|
-
const cwd = process.cwd();
|
|
38
|
-
const name = basename(cwd);
|
|
39
|
-
const settingsPath = join(process.env.HOME || '', '.claude', 'settings.json');
|
|
40
|
-
let hasHooks = false;
|
|
41
|
-
try {
|
|
42
|
-
hasHooks = existsSync(settingsPath) && readFileSync(settingsPath, 'utf-8').includes('codehere');
|
|
43
|
-
}
|
|
44
|
-
catch { }
|
|
45
|
-
const hasApiKey = !!(process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.COHERE_API_KEY);
|
|
46
|
-
const hasEmbeddings = existsSync(join(cwd, '.codehere-cache', 'embeddings.sqlite'));
|
|
47
|
-
const isGitRepo = existsSync(join(cwd, '.git'));
|
|
48
|
-
let fileCount = 0;
|
|
49
|
-
try {
|
|
50
|
-
const count = (dir, d) => {
|
|
51
|
-
if (d > 3)
|
|
52
|
-
return 0;
|
|
53
|
-
let n = 0;
|
|
54
|
-
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
55
|
-
if (e.name.startsWith('.') || e.name === 'node_modules' || e.name === 'dist')
|
|
56
|
-
continue;
|
|
57
|
-
if (e.isDirectory())
|
|
58
|
-
n += count(join(dir, e.name), d + 1);
|
|
59
|
-
else
|
|
60
|
-
n++;
|
|
61
|
-
}
|
|
62
|
-
return n;
|
|
63
|
-
};
|
|
64
|
-
fileCount = count(cwd, 0);
|
|
65
|
-
}
|
|
66
|
-
catch { }
|
|
67
|
-
return { name, hasHooks, hasApiKey, hasEmbeddings, isGitRepo, fileCount };
|
|
68
|
-
}
|
|
69
|
-
function printWelcome() {
|
|
70
|
-
const state = detectState();
|
|
71
|
-
const logo = createCodehereLogo();
|
|
72
|
-
const ver = colors.dim(`v${getVersion()}`);
|
|
73
|
-
console.log();
|
|
74
|
-
console.log(` ${logo} ${ver}`);
|
|
75
|
-
console.log();
|
|
76
|
-
const badges = [
|
|
77
|
-
state.hasHooks ? colors.green('● hooks') : colors.dim('○ hooks'),
|
|
78
|
-
state.hasApiKey ? colors.green('● api') : colors.dim('○ api'),
|
|
79
|
-
state.hasEmbeddings ? colors.green('● indexed') : colors.dim('○ indexed'),
|
|
80
|
-
];
|
|
81
|
-
console.log(' ' + badges.join(' '));
|
|
82
|
-
console.log();
|
|
83
|
-
console.log(colors.dim(` ${state.name}`) + colors.dim(` · ${state.isGitRepo ? 'git' : 'dir'} · ${state.fileCount} files`));
|
|
84
|
-
console.log();
|
|
85
|
-
if (!state.hasHooks)
|
|
86
|
-
console.log(' ' + colors.yellow('→') + ' ' + colors.cyan('/hook install') + colors.dim(' to activate safety scanning'));
|
|
87
|
-
else if (!state.hasApiKey)
|
|
88
|
-
console.log(' ' + colors.yellow('→') + ' ' + colors.cyan('codehere setup') + colors.dim(' to add an API key'));
|
|
89
|
-
else if (!state.hasEmbeddings)
|
|
90
|
-
console.log(' ' + colors.yellow('→') + ' Type ' + colors.cyan('/index') + colors.dim(' to enable semantic search'));
|
|
91
|
-
console.log(colors.dim(' Type / for commands, or ask anything'));
|
|
92
|
-
console.log();
|
|
93
|
-
}
|
|
94
|
-
// ── Main session ────────────────────────────────────────────────────────────
|
|
95
|
-
export async function startSession() {
|
|
96
|
-
printWelcome();
|
|
97
|
-
// Raw mode
|
|
98
|
-
if (stdin.isTTY)
|
|
99
|
-
stdin.setRawMode(true);
|
|
100
|
-
stdin.resume();
|
|
101
|
-
stdin.setEncoding('utf8');
|
|
102
|
-
const state = { history: [] };
|
|
103
|
-
const historyBuf = [];
|
|
104
|
-
let historyIdx = -1;
|
|
105
|
-
let line = '';
|
|
106
|
-
let selected = 0;
|
|
107
|
-
let pLines = 0;
|
|
108
|
-
let processing = false;
|
|
109
|
-
let escBuf = '';
|
|
110
|
-
let escTimer = null;
|
|
111
|
-
// ── Render: clear from prompt to end of screen, redraw everything ──
|
|
112
|
-
// Key insight: truncate all output lines to terminal width to prevent wrapping,
|
|
113
|
-
// which breaks cursor-up counting.
|
|
114
|
-
const cols = () => stdout.columns || 80;
|
|
115
|
-
function truncate(s, maxWidth) {
|
|
116
|
-
// Strip ANSI to measure visible length, truncate if needed
|
|
117
|
-
const visible = s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
118
|
-
if (visible.length <= maxWidth)
|
|
119
|
-
return s;
|
|
120
|
-
// Truncate by removing chars from the end (keep ANSI structure intact)
|
|
121
|
-
let vis = 0;
|
|
122
|
-
let cut = 0;
|
|
123
|
-
for (let i = 0; i < s.length; i++) {
|
|
124
|
-
if (s[i] === '\x1b') {
|
|
125
|
-
// Skip ANSI sequence
|
|
126
|
-
const end = s.indexOf('m', i);
|
|
127
|
-
if (end !== -1) {
|
|
128
|
-
i = end;
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
vis++;
|
|
133
|
-
if (vis >= maxWidth - 1) {
|
|
134
|
-
cut = i + 1;
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return cut > 0 ? s.slice(0, cut) + '\x1b[0m' : s;
|
|
139
|
-
}
|
|
140
|
-
function render() {
|
|
141
|
-
stdout.write('\r\x1b[J');
|
|
142
|
-
stdout.write(brandBlue('> ') + line);
|
|
143
|
-
if (line.startsWith('/') && !line.includes(' ')) {
|
|
144
|
-
const filter = line.slice(1).toLowerCase();
|
|
145
|
-
const allMatching = PALETTE_CMDS.filter(c => c.name.startsWith(filter));
|
|
146
|
-
const limit = maxPalette();
|
|
147
|
-
const filtered = allMatching.slice(0, limit);
|
|
148
|
-
const overflow = allMatching.length - filtered.length;
|
|
149
|
-
if (filtered.length > 0) {
|
|
150
|
-
const maxLen = Math.max(...filtered.map(c => c.sig.length));
|
|
151
|
-
const w = cols();
|
|
152
|
-
let drawnLines = 0;
|
|
153
|
-
for (let i = 0; i < filtered.length; i++) {
|
|
154
|
-
const c = filtered[i];
|
|
155
|
-
const pad = ' '.repeat(Math.max(1, maxLen - c.sig.length + 2));
|
|
156
|
-
const badge = c.noKey ? colors.dim(' (free)') : '';
|
|
157
|
-
const prefix = i === selected ? brandBlue('▸') : ' ';
|
|
158
|
-
const text = i === selected ? brandBlue(c.sig) : c.sig;
|
|
159
|
-
const row = ` ${prefix} ${text}${pad}${colors.dim(c.desc)}${badge}`;
|
|
160
|
-
stdout.write('\n' + truncate(row, w));
|
|
161
|
-
drawnLines++;
|
|
162
|
-
}
|
|
163
|
-
if (overflow > 0) {
|
|
164
|
-
stdout.write('\n' + colors.dim(` ... +${overflow} more (type to filter)`));
|
|
165
|
-
drawnLines++;
|
|
166
|
-
}
|
|
167
|
-
stdout.write(`\x1b[${drawnLines}A`);
|
|
168
|
-
stdout.write(`\x1b[${line.length + 3}G`);
|
|
169
|
-
pLines = drawnLines;
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
stdout.write('\n' + colors.dim(' No matching commands'));
|
|
173
|
-
stdout.write('\x1b[1A');
|
|
174
|
-
stdout.write(`\x1b[${line.length + 3}G`);
|
|
175
|
-
pLines = 1;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
pLines = 0;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
// ── Key handler (synchronous for palette, async exec wrapped separately) ──
|
|
183
|
-
function handle(key) {
|
|
184
|
-
if (processing)
|
|
185
|
-
return;
|
|
186
|
-
// Ctrl+C
|
|
187
|
-
if (key === '\x03') {
|
|
188
|
-
if (line.length > 0) {
|
|
189
|
-
line = '';
|
|
190
|
-
selected = 0;
|
|
191
|
-
stdout.write('\r\x1b[J\n');
|
|
192
|
-
render();
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
stdout.write('\r\x1b[J\n');
|
|
196
|
-
process.exit(0);
|
|
197
|
-
}
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
// Ctrl+D
|
|
201
|
-
if (key === '\x04') {
|
|
202
|
-
stdout.write('\r\x1b[J\n' + colors.dim(' See you.') + '\n');
|
|
203
|
-
process.exit(0);
|
|
204
|
-
}
|
|
205
|
-
// Ctrl+L
|
|
206
|
-
if (key === '\x0c') {
|
|
207
|
-
line = '';
|
|
208
|
-
selected = 0;
|
|
209
|
-
stdout.write('\x1b[2J\x1b[H');
|
|
210
|
-
printWelcome();
|
|
211
|
-
render();
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
// Arrow up
|
|
215
|
-
if (key === '\x1b[A') {
|
|
216
|
-
if (pLines > 0) {
|
|
217
|
-
selected = Math.max(0, selected - 1);
|
|
218
|
-
}
|
|
219
|
-
else if (historyBuf.length > 0 && historyIdx < historyBuf.length - 1) {
|
|
220
|
-
historyIdx++;
|
|
221
|
-
line = historyBuf[historyIdx];
|
|
222
|
-
}
|
|
223
|
-
render();
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
// Arrow down
|
|
227
|
-
if (key === '\x1b[B') {
|
|
228
|
-
if (pLines > 0) {
|
|
229
|
-
selected = Math.min(pLines - 1, selected + 1);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
if (historyIdx > 0) {
|
|
233
|
-
historyIdx--;
|
|
234
|
-
line = historyBuf[historyIdx];
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
historyIdx = -1;
|
|
238
|
-
line = '';
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
render();
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
// Tab
|
|
245
|
-
if (key === '\t' && pLines > 0) {
|
|
246
|
-
const filter = line.slice(1).toLowerCase();
|
|
247
|
-
const filtered = PALETTE_CMDS.filter(c => c.name.startsWith(filter)).slice(0, maxPalette());
|
|
248
|
-
if (filtered[selected]) {
|
|
249
|
-
line = `/${filtered[selected].name} `;
|
|
250
|
-
selected = 0;
|
|
251
|
-
}
|
|
252
|
-
render();
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
// Enter
|
|
256
|
-
if (key === '\r' || key === '\n') {
|
|
257
|
-
// If palette is visible, complete the selected command first
|
|
258
|
-
if (pLines > 0 && line.startsWith('/') && !line.includes(' ')) {
|
|
259
|
-
const filter = line.slice(1).toLowerCase();
|
|
260
|
-
const filtered = PALETTE_CMDS.filter(c => c.name.startsWith(filter)).slice(0, maxPalette());
|
|
261
|
-
if (filtered[selected]) {
|
|
262
|
-
line = `/${filtered[selected].name}`;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
stdout.write('\r\x1b[J\n');
|
|
266
|
-
const trimmed = line.trim();
|
|
267
|
-
if (trimmed) {
|
|
268
|
-
historyBuf.unshift(trimmed);
|
|
269
|
-
historyIdx = -1;
|
|
270
|
-
}
|
|
271
|
-
line = '';
|
|
272
|
-
selected = 0;
|
|
273
|
-
pLines = 0;
|
|
274
|
-
if (!trimmed) {
|
|
275
|
-
render();
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
// Async execution
|
|
279
|
-
processing = true;
|
|
280
|
-
executeInput(trimmed, state).catch(err => {
|
|
281
|
-
console.log(error(' ' + (err instanceof Error ? err.message : String(err))));
|
|
282
|
-
}).finally(() => {
|
|
283
|
-
processing = false;
|
|
284
|
-
stdin.resume();
|
|
285
|
-
stdin.ref();
|
|
286
|
-
if (stdin.isTTY && !stdin.isRaw)
|
|
287
|
-
stdin.setRawMode(true);
|
|
288
|
-
console.log();
|
|
289
|
-
render();
|
|
290
|
-
});
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
// Backspace
|
|
294
|
-
if (key === '\x7f' || key === '\b') {
|
|
295
|
-
if (line.length > 0) {
|
|
296
|
-
line = line.slice(0, -1);
|
|
297
|
-
selected = 0;
|
|
298
|
-
render();
|
|
299
|
-
}
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
// Ignore escape sequences
|
|
303
|
-
if (key.startsWith('\x1b'))
|
|
304
|
-
return;
|
|
305
|
-
// Regular character
|
|
306
|
-
line += key;
|
|
307
|
-
selected = 0;
|
|
308
|
-
render();
|
|
309
|
-
}
|
|
310
|
-
// ── Initial render ──
|
|
311
|
-
render();
|
|
312
|
-
// ── Stdin with escape buffering ──
|
|
313
|
-
// CRITICAL: raw mode can deliver multiple chars in one data event (fast typing, paste).
|
|
314
|
-
// We must process each character individually, except escape sequences which are multi-byte.
|
|
315
|
-
stdin.on('data', (raw) => {
|
|
316
|
-
if (processing)
|
|
317
|
-
return;
|
|
318
|
-
// If the whole chunk is a known escape sequence, handle it directly
|
|
319
|
-
if (raw.startsWith('\x1b') && raw.length >= 2) {
|
|
320
|
-
handle(raw);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
// Otherwise iterate character by character
|
|
324
|
-
for (let i = 0; i < raw.length; i++) {
|
|
325
|
-
if (processing)
|
|
326
|
-
return; // stop if a command started executing mid-chunk
|
|
327
|
-
const ch = raw[i];
|
|
328
|
-
if (escBuf.length > 0) {
|
|
329
|
-
escBuf += ch;
|
|
330
|
-
if (escTimer)
|
|
331
|
-
clearTimeout(escTimer);
|
|
332
|
-
if (escBuf.length >= 3) {
|
|
333
|
-
const seq = escBuf;
|
|
334
|
-
escBuf = '';
|
|
335
|
-
handle(seq);
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
escTimer = setTimeout(() => { const seq = escBuf; escBuf = ''; handle(seq); }, 50);
|
|
339
|
-
}
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
if (ch === '\x1b') {
|
|
343
|
-
escBuf = ch;
|
|
344
|
-
escTimer = setTimeout(() => { const seq = escBuf; escBuf = ''; handle(seq); }, 50);
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
347
|
-
handle(ch);
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
// ── Command list (for bare / or help) ──────────────────────────────────────
|
|
352
|
-
function printCommandList() {
|
|
353
|
-
console.log();
|
|
354
|
-
const maxLen = Math.max(...PALETTE_CMDS.map(c => c.sig.length));
|
|
355
|
-
for (const cmd of PALETTE_CMDS) {
|
|
356
|
-
const pad = ' '.repeat(Math.max(1, maxLen - cmd.sig.length + 2));
|
|
357
|
-
const badge = cmd.noKey ? colors.dim(' (free)') : '';
|
|
358
|
-
console.log(` ${colors.cyan(cmd.sig)}${pad}${colors.dim(cmd.desc)}${badge}`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
// ── Input dispatcher ────────────────────────────────────────────────────────
|
|
362
|
-
async function executeInput(input, state) {
|
|
363
|
-
if (input === '/') {
|
|
364
|
-
printCommandList();
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
if (input.startsWith('/')) {
|
|
368
|
-
const spaceIdx = input.indexOf(' ');
|
|
369
|
-
const cmd = (spaceIdx === -1 ? input.slice(1) : input.slice(1, spaceIdx)).toLowerCase();
|
|
370
|
-
const args = spaceIdx === -1 ? '' : input.slice(spaceIdx + 1).trim();
|
|
371
|
-
await handleSlash(cmd, args, state);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
// Exact keywords for REPL control
|
|
375
|
-
if (/^(exit|quit)$/i.test(input)) {
|
|
376
|
-
console.log(colors.dim(' See you.'));
|
|
377
|
-
process.exit(0);
|
|
378
|
-
}
|
|
379
|
-
if (/^(help|\?)$/i.test(input)) {
|
|
380
|
-
printCommandList();
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
if (input.toLowerCase() === 'clear') {
|
|
384
|
-
stdout.write('\x1b[2J\x1b[H');
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
// Bare command names: "trust ." or "status" → same as "/trust ." or "/status"
|
|
388
|
-
// Only match unambiguous commands — skip words that are common English ("help", "fix", "run", "plan", "report", "test")
|
|
389
|
-
const BARE_SAFE = ['trust', 'hook', 'status', 'health', 'setup', 'serve', 'models', 'config', 'index', 'explain', 'review', 'cost', 'undo'];
|
|
390
|
-
const lower = input.toLowerCase();
|
|
391
|
-
const firstWord = lower.split(/\s+/)[0];
|
|
392
|
-
const restArgs = input.slice(firstWord.length).trim();
|
|
393
|
-
if (BARE_SAFE.includes(firstWord)) {
|
|
394
|
-
await handleSlash(firstWord, restArgs, state);
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
// Everything else → AI query (the router decides what to do)
|
|
398
|
-
await handleQuery(input, state);
|
|
399
|
-
}
|
|
400
|
-
// ── Slash commands ──────────────────────────────────────────────────────────
|
|
401
|
-
async function handleSlash(cmd, args, state) {
|
|
402
|
-
switch (cmd) {
|
|
403
|
-
case 'ask':
|
|
404
|
-
case 'q':
|
|
405
|
-
if (!args) {
|
|
406
|
-
console.log(colors.dim(' Usage: /ask <question>'));
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
await handleQuery(args, state);
|
|
410
|
-
break;
|
|
411
|
-
case 'explain':
|
|
412
|
-
case 'e':
|
|
413
|
-
if (!args) {
|
|
414
|
-
console.log(colors.dim(' Usage: /explain <file>'));
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
await handleExplain(args);
|
|
418
|
-
break;
|
|
419
|
-
case 'fix':
|
|
420
|
-
case 'edit': {
|
|
421
|
-
const p = args.split(' ');
|
|
422
|
-
if (!p[0]) {
|
|
423
|
-
console.log(colors.dim(' Usage: /fix <file> <instruction>'));
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
await handleFix(p[0], p.slice(1).join(' '));
|
|
427
|
-
break;
|
|
428
|
-
}
|
|
429
|
-
case 'review':
|
|
430
|
-
if (!args) {
|
|
431
|
-
console.log(colors.dim(' Usage: /review <file>'));
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
await handleReview(args);
|
|
435
|
-
break;
|
|
436
|
-
case 'plan':
|
|
437
|
-
if (!args) {
|
|
438
|
-
console.log(colors.dim(' Usage: /plan <goal>'));
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
await handlePlan(args);
|
|
442
|
-
break;
|
|
443
|
-
case 'trust': {
|
|
444
|
-
const { executeTrustCommand } = await import('./presentation/cli/commands/trust-command.js');
|
|
445
|
-
await executeTrustCommand(args || undefined);
|
|
446
|
-
break;
|
|
447
|
-
}
|
|
448
|
-
case 'report': {
|
|
449
|
-
const { executeReportCommand } = await import('./presentation/cli/commands/report-command.js');
|
|
450
|
-
await executeReportCommand(args || undefined);
|
|
451
|
-
break;
|
|
452
|
-
}
|
|
453
|
-
case 'hook': {
|
|
454
|
-
const { executeHookCommand } = await import('./presentation/cli/commands/hook-command.js');
|
|
455
|
-
await executeHookCommand(args.split(' ')[0] || 'status');
|
|
456
|
-
break;
|
|
457
|
-
}
|
|
458
|
-
case 'status': {
|
|
459
|
-
const { executeStatusCommand } = await import('./presentation/cli/commands/status-command.js');
|
|
460
|
-
await executeStatusCommand({});
|
|
461
|
-
break;
|
|
462
|
-
}
|
|
463
|
-
case 'suggest': {
|
|
464
|
-
const { executeSuggestCommand } = await import('./presentation/cli/commands/suggest-command.js');
|
|
465
|
-
if (!args) {
|
|
466
|
-
console.log(colors.dim(' Usage: /suggest <query>'));
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
await executeSuggestCommand(args);
|
|
470
|
-
break;
|
|
471
|
-
}
|
|
472
|
-
case 'test': {
|
|
473
|
-
if (!args) {
|
|
474
|
-
console.log(colors.dim(' Usage: /test <file>'));
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
if (!(await requireKey()))
|
|
478
|
-
return;
|
|
479
|
-
await handleQuery(`Generate tests for ${args}`, state);
|
|
480
|
-
break;
|
|
481
|
-
}
|
|
482
|
-
case 'docs': {
|
|
483
|
-
const { executeDocsCommand } = await import('./presentation/cli/commands/docs-command.js');
|
|
484
|
-
await executeDocsCommand((args || 'readme'));
|
|
485
|
-
break;
|
|
486
|
-
}
|
|
487
|
-
case 'refactor': {
|
|
488
|
-
if (!args) {
|
|
489
|
-
console.log(colors.dim(' Usage: /refactor <goal>'));
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
if (!(await requireKey()))
|
|
493
|
-
return;
|
|
494
|
-
await handleQuery('Refactor: ' + args, state);
|
|
495
|
-
break;
|
|
496
|
-
}
|
|
497
|
-
case 'orchestrate': {
|
|
498
|
-
const { executeOrchestrateCommand } = await import('./presentation/cli/commands/orchestrate-command.js');
|
|
499
|
-
if (!args) {
|
|
500
|
-
console.log(colors.dim(' Usage: /orchestrate <goal>'));
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
await executeOrchestrateCommand(args, {});
|
|
504
|
-
break;
|
|
505
|
-
}
|
|
506
|
-
case 'run': {
|
|
507
|
-
const { executeRunCommand } = await import('./presentation/cli/commands/run-command.js');
|
|
508
|
-
if (!args) {
|
|
509
|
-
console.log(colors.dim(' Usage: /run <goal>'));
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
await executeRunCommand(args, {});
|
|
513
|
-
break;
|
|
514
|
-
}
|
|
515
|
-
case 'git-review': {
|
|
516
|
-
if (!(await requireKey()))
|
|
517
|
-
return;
|
|
518
|
-
await handleQuery('Review the recent git changes in this project', state);
|
|
519
|
-
break;
|
|
520
|
-
}
|
|
521
|
-
case 'index': {
|
|
522
|
-
if (!(await requireKey()))
|
|
523
|
-
return;
|
|
524
|
-
const { indexRepositoryParallel } = await import('./embed.js');
|
|
525
|
-
const spinner = startSpinner('Indexing codebase...');
|
|
526
|
-
try {
|
|
527
|
-
await indexRepositoryParallel(process.cwd(), { useCache: true, maxConcurrency: 5 });
|
|
528
|
-
spinner.succeed(colors.green('Index built'));
|
|
529
|
-
}
|
|
530
|
-
catch (err) {
|
|
531
|
-
spinner.fail(error('Index failed: ' + (err instanceof Error ? err.message : String(err))));
|
|
532
|
-
}
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
case 'health': {
|
|
536
|
-
const { performHealthCheck, formatHealthStatus } = await import('./monitoring.js');
|
|
537
|
-
console.log(formatHealthStatus(performHealthCheck()));
|
|
538
|
-
break;
|
|
539
|
-
}
|
|
540
|
-
case 'setup': {
|
|
541
|
-
const { executeSetupCommand } = await import('./presentation/cli/commands/setup-command.js');
|
|
542
|
-
await executeSetupCommand(false);
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
|
-
case 'serve': {
|
|
546
|
-
console.log(colors.dim(' MCP server must run in its own process:'));
|
|
547
|
-
console.log(colors.cyan(' codehere serve'));
|
|
548
|
-
break;
|
|
549
|
-
}
|
|
550
|
-
case 'config': {
|
|
551
|
-
const { executeConfigCommand } = await import('./presentation/cli/commands/config-command.js');
|
|
552
|
-
const parts = args.split(' ');
|
|
553
|
-
await executeConfigCommand(parts[0], parts[1], parts[2]);
|
|
554
|
-
break;
|
|
555
|
-
}
|
|
556
|
-
case 'cost': {
|
|
557
|
-
const { executeCostCommand } = await import('./presentation/cli/commands/cost-command.js');
|
|
558
|
-
await executeCostCommand((args || 'status'));
|
|
559
|
-
break;
|
|
560
|
-
}
|
|
561
|
-
case 'models': {
|
|
562
|
-
const { executeModelsCommand } = await import('./presentation/cli/commands/models-command.js');
|
|
563
|
-
await executeModelsCommand({ list: true });
|
|
564
|
-
break;
|
|
565
|
-
}
|
|
566
|
-
case 'undo': {
|
|
567
|
-
const { executeUndoCommand } = await import('./presentation/cli/commands/undo-command.js');
|
|
568
|
-
await executeUndoCommand(args ? 'undo' : 'list', args || undefined);
|
|
569
|
-
break;
|
|
570
|
-
}
|
|
571
|
-
case 'clear':
|
|
572
|
-
stdout.write('\x1b[2J\x1b[H');
|
|
573
|
-
break;
|
|
574
|
-
case 'help':
|
|
575
|
-
case '?':
|
|
576
|
-
printCommandList();
|
|
577
|
-
break;
|
|
578
|
-
case 'exit':
|
|
579
|
-
case 'quit':
|
|
580
|
-
console.log(colors.dim(' See you.'));
|
|
581
|
-
process.exit(0);
|
|
582
|
-
default: {
|
|
583
|
-
// Fuzzy match: find closest command
|
|
584
|
-
const ALL_CMD_NAMES = PALETTE_CMDS.map(c => c.name);
|
|
585
|
-
const KNOWN = [...ALL_CMD_NAMES, 'q', 'e', 'edit', 'quit'];
|
|
586
|
-
const match = KNOWN.find(k => k.startsWith(cmd));
|
|
587
|
-
if (match) {
|
|
588
|
-
console.log(colors.dim(` Did you mean /${match}?`));
|
|
589
|
-
}
|
|
590
|
-
else {
|
|
591
|
-
console.log(warning(` Unknown: /${cmd}`));
|
|
592
|
-
console.log(colors.dim(' Type / to see commands'));
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
// ── Handlers ────────────────────────────────────────────────────────────────
|
|
598
|
-
function startSpinner(text) {
|
|
599
|
-
return ora({ text: colors.dim(text), spinner: 'dots', color: 'cyan' }).start();
|
|
600
|
-
}
|
|
601
|
-
async function requireKey() {
|
|
602
|
-
if (!process.env.ANTHROPIC_API_KEY && !process.env.OPENAI_API_KEY && !process.env.COHERE_API_KEY && process.env.CODEHERE_FAKE_AI !== '1') {
|
|
603
|
-
console.log(warning(' No API key set. Run: codehere setup'));
|
|
604
|
-
return false;
|
|
605
|
-
}
|
|
606
|
-
return true;
|
|
607
|
-
}
|
|
608
|
-
async function handleQuery(query, state) {
|
|
609
|
-
if (!(await requireKey()))
|
|
610
|
-
return;
|
|
611
|
-
const spinner = startSpinner('Thinking...');
|
|
612
|
-
try {
|
|
613
|
-
const { container } = await import('./application/services/dependency-container.js');
|
|
614
|
-
const router = new IntelligentRouter(undefined, container.aiService, container.memoryStreamService);
|
|
615
|
-
const { conversationContextManager } = await import('./infrastructure/context/conversation-context.js');
|
|
616
|
-
const { sessionManager } = await import('./infrastructure/context/session-manager.js');
|
|
617
|
-
const sessionId = sessionManager.getSessionId(process.cwd());
|
|
618
|
-
const history = conversationContextManager.getHistory(sessionId, 5);
|
|
619
|
-
const result = await router.route({
|
|
620
|
-
query,
|
|
621
|
-
context: {
|
|
622
|
-
currentDirectory: process.cwd(),
|
|
623
|
-
conversationHistory: history.map(t => ({ query: t.query, response: t.response, timestamp: typeof t.timestamp === 'string' ? Date.parse(t.timestamp) : t.timestamp })),
|
|
624
|
-
sessionId,
|
|
625
|
-
},
|
|
626
|
-
});
|
|
627
|
-
spinner.stop();
|
|
628
|
-
if (result.success && result.message) {
|
|
629
|
-
const { formatMarkdownForTerminal } = await import('./infrastructure/ux/stream-markdown.js');
|
|
630
|
-
console.log();
|
|
631
|
-
console.log(formatMarkdownForTerminal(result.message));
|
|
632
|
-
}
|
|
633
|
-
else if (result.error) {
|
|
634
|
-
console.log(error(' ' + result.error));
|
|
635
|
-
}
|
|
636
|
-
else {
|
|
637
|
-
console.log(colors.dim(' No response. Try rephrasing, or run "codehere index" first.'));
|
|
638
|
-
}
|
|
639
|
-
state.history.push({ command: query, response: result.message || result.error || '', timestamp: new Date().toISOString() });
|
|
640
|
-
const entities = conversationContextManager.extractEntities(query);
|
|
641
|
-
conversationContextManager.addTurn(sessionId, query, result.message || '', entities, result.intent);
|
|
642
|
-
}
|
|
643
|
-
catch (err) {
|
|
644
|
-
spinner.stop();
|
|
645
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
646
|
-
if (msg.includes('No embeddings') || msg.includes('not found') || msg.includes('Not found')) {
|
|
647
|
-
console.log(colors.dim(` Couldn't answer that. Try "codehere index" first, or rephrase your question.`));
|
|
648
|
-
}
|
|
649
|
-
else {
|
|
650
|
-
console.log(error(' ' + msg));
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
async function handleExplain(file) {
|
|
655
|
-
if (!(await requireKey()))
|
|
656
|
-
return;
|
|
657
|
-
const fullPath = join(process.cwd(), file);
|
|
658
|
-
if (!existsSync(fullPath)) {
|
|
659
|
-
console.log(error(` Not found: ${file}`));
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
const spinner = startSpinner('Reading...');
|
|
663
|
-
const content = readFileSync(fullPath, 'utf-8');
|
|
664
|
-
const context = [{ filepath: file, content, score: 1.0 }];
|
|
665
|
-
spinner.stop();
|
|
666
|
-
console.log();
|
|
667
|
-
const md = createMarkdownStream();
|
|
668
|
-
await chatWithContextStream(`Explain this file: ${file}`, context, (token) => md.write(token));
|
|
669
|
-
md.flush();
|
|
670
|
-
console.log();
|
|
671
|
-
}
|
|
672
|
-
async function handleFix(file, hint) {
|
|
673
|
-
if (!(await requireKey()))
|
|
674
|
-
return;
|
|
675
|
-
if (!hint) {
|
|
676
|
-
console.log(colors.dim(' Usage: /fix <file> <what to fix>'));
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
|
-
const { executeFixCommand } = await import('./presentation/cli/commands/fix-command.js');
|
|
680
|
-
await executeFixCommand(file, hint);
|
|
681
|
-
}
|
|
682
|
-
async function handleReview(file) {
|
|
683
|
-
if (!(await requireKey()))
|
|
684
|
-
return;
|
|
685
|
-
const spinner = startSpinner('Reviewing...');
|
|
686
|
-
const review = await reviewFile(file);
|
|
687
|
-
spinner.stop();
|
|
688
|
-
console.log();
|
|
689
|
-
console.log(colors.bold(` ${file}`) + colors.dim(` · ${review.score}/100 · ${review.issues.length} issues`));
|
|
690
|
-
for (const issue of review.issues.slice(0, 5)) {
|
|
691
|
-
const icon = issue.severity === 'error' ? colors.red('✗') : issue.severity === 'warning' ? colors.yellow('!') : colors.dim('·');
|
|
692
|
-
console.log(` ${icon} ${issue.message}`);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
async function handlePlan(goal) {
|
|
696
|
-
if (!(await requireKey()))
|
|
697
|
-
return;
|
|
698
|
-
const spinner = startSpinner('Planning...');
|
|
699
|
-
const plan = await planTask(goal);
|
|
700
|
-
spinner.stop();
|
|
701
|
-
console.log();
|
|
702
|
-
console.log(formatPlan(plan));
|
|
703
|
-
}
|
|
704
|
-
//# sourceMappingURL=session.js.map
|