codehere 0.8.0 → 1.0.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.
Files changed (119) hide show
  1. package/README.md +37 -184
  2. package/dist/application/use-cases/check-claimed-tests.js +81 -0
  3. package/dist/application/use-cases/detect-test-weakening.js +237 -0
  4. package/dist/application/use-cases/rerun-tests.js +329 -0
  5. package/dist/index.js +74 -1004
  6. package/dist/infrastructure/orchestration/artifacts-extractor.js +2 -265
  7. package/dist/presentation/cli/commands/check-command.js +251 -0
  8. package/dist/presentation/cli/commands/help-command.js +22 -286
  9. package/dist/ui.js +19 -438
  10. package/dist/utils/version.js +0 -12
  11. package/package.json +18 -27
  12. package/dist/application/use-cases/domain-trust.js +0 -110
  13. package/dist/application/use-cases/generate-final-report.js +0 -134
  14. package/dist/application/use-cases/generate-narration.js +0 -128
  15. package/dist/application/use-cases/generate-thread-title.js +0 -178
  16. package/dist/application/use-cases/narrator-prompt-template.js +0 -158
  17. package/dist/application/use-cases/thread-export.js +0 -155
  18. package/dist/application/use-cases/verify-claim.js +0 -274
  19. package/dist/application/use-cases/write-pass.js +0 -277
  20. package/dist/domain/entities/task.js +0 -61
  21. package/dist/domain/services/codebase-detector.js +0 -91
  22. package/dist/error-handler.js +0 -251
  23. package/dist/infrastructure/completion/bash-completion.js +0 -25
  24. package/dist/infrastructure/completion/fish-completion.js +0 -22
  25. package/dist/infrastructure/completion/zsh-completion.js +0 -30
  26. package/dist/infrastructure/config/config-manager.js +0 -173
  27. package/dist/infrastructure/config/product-context.js +0 -67
  28. package/dist/infrastructure/context/adapters/drawio-source.js +0 -157
  29. package/dist/infrastructure/context/adapters/figma-source.js +0 -163
  30. package/dist/infrastructure/context/adapters/github-issue-source.js +0 -159
  31. package/dist/infrastructure/context/adapters/linear-source.js +0 -190
  32. package/dist/infrastructure/context/context-resolver.js +0 -144
  33. package/dist/infrastructure/context/context-source.js +0 -114
  34. package/dist/infrastructure/context/oauth-flow.js +0 -207
  35. package/dist/infrastructure/context/oauth-store.js +0 -119
  36. package/dist/infrastructure/context/registry-bootstrap.js +0 -99
  37. package/dist/infrastructure/context/write-pass-resolver.js +0 -106
  38. package/dist/infrastructure/cost/budget-config.js +0 -113
  39. package/dist/infrastructure/cost/cost-router.js +0 -104
  40. package/dist/infrastructure/cost/spend-aggregator.js +0 -147
  41. package/dist/infrastructure/hooks/claude-sdk-hook.js +0 -888
  42. package/dist/infrastructure/hooks/hook-mode.js +0 -71
  43. package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +0 -43
  44. package/dist/infrastructure/hooks/pre-prompt-scan.js +0 -122
  45. package/dist/infrastructure/hooks/session-analyzer.js +0 -177
  46. package/dist/infrastructure/observability/execution-tracer.js +0 -227
  47. package/dist/infrastructure/orchestration/agent-adapter.js +0 -13
  48. package/dist/infrastructure/orchestration/agent-installer.js +0 -101
  49. package/dist/infrastructure/orchestration/agents-config-seed.js +0 -56
  50. package/dist/infrastructure/orchestration/aider-adapter.js +0 -447
  51. package/dist/infrastructure/orchestration/cassette-recorder.js +0 -120
  52. package/dist/infrastructure/orchestration/claude-code-adapter.js +0 -478
  53. package/dist/infrastructure/orchestration/codex-adapter.js +0 -538
  54. package/dist/infrastructure/orchestration/conductor-adapter.js +0 -377
  55. package/dist/infrastructure/orchestration/context-handoff.js +0 -144
  56. package/dist/infrastructure/orchestration/control/codex-control-surface.js +0 -99
  57. package/dist/infrastructure/orchestration/control/control-surface.js +0 -15
  58. package/dist/infrastructure/orchestration/failover-classifier.js +0 -151
  59. package/dist/infrastructure/orchestration/failover-config.js +0 -77
  60. package/dist/infrastructure/orchestration/failover-policy.js +0 -106
  61. package/dist/infrastructure/orchestration/gemini-adapter.js +0 -583
  62. package/dist/infrastructure/orchestration/generic-cli-adapter.js +0 -558
  63. package/dist/infrastructure/orchestration/graphify-context.js +0 -254
  64. package/dist/infrastructure/orchestration/memory-injector.js +0 -380
  65. package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +0 -233
  66. package/dist/infrastructure/orchestration/mocks/mock-codex-app-server.js +0 -73
  67. package/dist/infrastructure/orchestration/mocks/mock-synthesis.js +0 -83
  68. package/dist/infrastructure/orchestration/mocks/resolve-agent-spawn.js +0 -37
  69. package/dist/infrastructure/orchestration/opencode-adapter.js +0 -510
  70. package/dist/infrastructure/orchestration/progress-aggregator.js +0 -689
  71. package/dist/infrastructure/orchestration/readiness.js +0 -103
  72. package/dist/infrastructure/orchestration/session-manager.js +0 -1091
  73. package/dist/infrastructure/orchestration/session-persistence.js +0 -258
  74. package/dist/infrastructure/orchestration/thread-key-store.js +0 -127
  75. package/dist/infrastructure/orchestration/write-pass-store.js +0 -46
  76. package/dist/infrastructure/protocols/cloud-sync.js +0 -207
  77. package/dist/infrastructure/protocols/mcp-helpers.js +0 -25
  78. package/dist/infrastructure/protocols/mcp-server-impl.js +0 -2853
  79. package/dist/infrastructure/protocols/probe-port.js +0 -36
  80. package/dist/infrastructure/protocols/thread-phase.js +0 -105
  81. package/dist/infrastructure/protocols/ui-page-v2.js +0 -4418
  82. package/dist/infrastructure/protocols/ui-page.js +0 -2377
  83. package/dist/infrastructure/protocols/verify-page.js +0 -983
  84. package/dist/infrastructure/security/file-collection.js +0 -118
  85. package/dist/infrastructure/security/input-validator.js +0 -152
  86. package/dist/infrastructure/security/permissions-config.js +0 -234
  87. package/dist/infrastructure/security/trust-scorer.js +0 -657
  88. package/dist/infrastructure/storage/cross-tool-agents.js +0 -268
  89. package/dist/infrastructure/storage/embeddings-path.js +0 -37
  90. package/dist/infrastructure/storage/project-thread-migration.js +0 -237
  91. package/dist/infrastructure/storage/project-thread-mirror.js +0 -524
  92. package/dist/infrastructure/storage/project-thread-reader.js +0 -172
  93. package/dist/infrastructure/storage/project-thread-title-backfill.js +0 -214
  94. package/dist/infrastructure/storage/task-repository.js +0 -206
  95. package/dist/monitoring.js +0 -212
  96. package/dist/presentation/cli/commands/audit-command.js +0 -126
  97. package/dist/presentation/cli/commands/budget-command.js +0 -79
  98. package/dist/presentation/cli/commands/config-command.js +0 -125
  99. package/dist/presentation/cli/commands/context-source-command.js +0 -198
  100. package/dist/presentation/cli/commands/hook-command.js +0 -265
  101. package/dist/presentation/cli/commands/init-command.js +0 -578
  102. package/dist/presentation/cli/commands/memory-command.js +0 -1031
  103. package/dist/presentation/cli/commands/narrator-command.js +0 -101
  104. package/dist/presentation/cli/commands/permission-command.js +0 -116
  105. package/dist/presentation/cli/commands/protocols-builder.js +0 -254
  106. package/dist/presentation/cli/commands/protocols-command.js +0 -84
  107. package/dist/presentation/cli/commands/repo-map-builder.js +0 -247
  108. package/dist/presentation/cli/commands/report-command.js +0 -387
  109. package/dist/presentation/cli/commands/scan-tool-command.js +0 -94
  110. package/dist/presentation/cli/commands/setup-command.js +0 -307
  111. package/dist/presentation/cli/commands/status-command.js +0 -661
  112. package/dist/presentation/cli/commands/thread-command.js +0 -288
  113. package/dist/presentation/cli/commands/trust-command.js +0 -306
  114. package/dist/presentation/cli/commands/verify-command.js +0 -233
  115. package/dist/presentation/cli/error-display.js +0 -336
  116. package/dist/presentation/cli/repl.js +0 -797
  117. package/dist/presentation/cli/task-deliverable.js +0 -127
  118. package/dist/testing/cassette.js +0 -125
  119. package/dist/testing/replay-adapter.js +0 -166
@@ -1,233 +0,0 @@
1
- /**
2
- * CLI command: verify
3
- *
4
- * v0.7 verifier-agent · Slice 2 (CLI surface for the pure verify-claim use case).
5
- *
6
- * Compares what the agent's Final Report TEXT claims against the structured
7
- * reality (artifacts + steps) captured during the session. Catches the
8
- * easy lies before they reach a PR description.
9
- *
10
- * Usage:
11
- * codehere verify <session-id> # run verifier on a completed session
12
- * codehere verify <session-id> --json # machine-readable output for CI
13
- * codehere verify # list recent sessions to pick from
14
- *
15
- * Exit codes:
16
- * 0 = verified OR partial (warnings only · unverifiable claims)
17
- * 0 = no-report (nothing to verify; not a failure)
18
- * 1 = broken (at least one claim contradicts recorded reality)
19
- * 2 = session not found / invalid input
20
- *
21
- * The verifier is intentionally conservative: only claims that map to
22
- * structured data are checked. Prose claims pass through silently.
23
- */
24
- import { colors, symbols } from '../../../ui.js';
25
- import { loadSessionById, loadRecent, } from '../../../infrastructure/orchestration/session-persistence.js';
26
- import { verifyClaim } from '../../../application/use-cases/verify-claim.js';
27
- export async function executeVerifyCommand(sessionId, options = {}) {
28
- // No session id: show a picker list and exit gracefully.
29
- if (!sessionId) {
30
- return showSessionPicker(options.json ?? false);
31
- }
32
- const session = loadSessionById(sessionId);
33
- if (!session) {
34
- if (options.json) {
35
- process.stdout.write(JSON.stringify({
36
- error: 'session-not-found',
37
- sessionId,
38
- hint: 'Run `codehere verify` (no args) to list recent sessions.',
39
- }, null, 2) + '\n');
40
- }
41
- else {
42
- process.stderr.write(colors.error(`${symbols.error} No completed session found matching "${sessionId}".\n`) +
43
- colors.dim(' Tip: run `codehere verify` (no args) to see recent sessions.\n'));
44
- }
45
- return 2;
46
- }
47
- const result = verifyClaim({
48
- summary: session.finalReport?.summary,
49
- artifacts: session.artifacts,
50
- steps: session.steps,
51
- });
52
- if (options.json) {
53
- process.stdout.write(JSON.stringify(serializeResult(session, result), null, 2) + '\n');
54
- }
55
- else {
56
- printHumanReadable(session, result);
57
- }
58
- // Exit code: only `broken` is a hard failure (CI-friendly).
59
- return result.status === 'broken' ? 1 : 0;
60
- }
61
- /* ──────────────────────────────────────────────────────────────────────── */
62
- /* Picker mode · no session id given */
63
- /* ──────────────────────────────────────────────────────────────────────── */
64
- function showSessionPicker(json) {
65
- const recent = loadRecent(15);
66
- if (recent.length === 0) {
67
- if (json) {
68
- process.stdout.write(JSON.stringify({ sessions: [], note: 'No completed sessions found.' }, null, 2) + '\n');
69
- }
70
- else {
71
- process.stdout.write(colors.dim('No completed sessions found. Run a task first, then verify it:\n') +
72
- colors.dim(' codehere task "describe what you want done"\n'));
73
- }
74
- return 0;
75
- }
76
- if (json) {
77
- const items = recent.map((s) => ({
78
- sessionId: s.sessionId,
79
- agent: s.agent,
80
- prompt: s.prompt,
81
- completedAt: s.completedAt,
82
- hasFinalReport: Boolean(s.finalReport),
83
- }));
84
- process.stdout.write(JSON.stringify({ sessions: items }, null, 2) + '\n');
85
- return 0;
86
- }
87
- process.stdout.write('\n' + colors.bold('Recent sessions') + colors.dim(' (pass --json for machine output)\n\n'));
88
- for (const s of recent) {
89
- const shortId = s.sessionId.slice(0, 8);
90
- const when = formatRelativeTime(s.completedAt);
91
- const reportTag = s.finalReport ? colors.gray('· report ✓') : colors.gray('· no report');
92
- const promptLine = truncate(s.prompt.replace(/\s+/g, ' ').trim(), 70);
93
- process.stdout.write(` ${colors.cyan(shortId)} ${colors.gray(s.agent.padEnd(11))}${colors.dim(when.padEnd(14))} ${reportTag}\n` +
94
- ` ${colors.dim(promptLine)}\n\n`);
95
- }
96
- process.stdout.write(colors.dim('To verify one of these: ') + colors.bold('codehere verify <id>') + '\n\n');
97
- return 0;
98
- }
99
- /* ──────────────────────────────────────────────────────────────────────── */
100
- /* Human-readable output */
101
- /* ──────────────────────────────────────────────────────────────────────── */
102
- function printHumanReadable(session, result) {
103
- const shortId = session.sessionId.slice(0, 8);
104
- const when = formatRelativeTime(session.completedAt);
105
- // Header
106
- process.stdout.write('\n' +
107
- colors.dim('session ') +
108
- colors.cyan(shortId) +
109
- colors.dim(' · ') +
110
- colors.gray(session.agent) +
111
- colors.dim(' · ') +
112
- colors.gray(when) +
113
- '\n' +
114
- colors.dim('task: ') +
115
- truncate(session.prompt.replace(/\s+/g, ' ').trim(), 80) +
116
- '\n\n');
117
- // What the agent did — lead with the deliverable, not the audit. A
118
- // non-technical user opening this wants "what happened" first, then "does
119
- // it check out". Both come straight from recorded state (no screen lies).
120
- if (session.finalReport?.summary) {
121
- process.stdout.write(session.finalReport.summary.trim() + '\n\n');
122
- }
123
- // Files changed + trust, or the honest can't-track note.
124
- const files = session.artifacts?.files ?? [];
125
- if (session.artifacts?.noGitTracking) {
126
- process.stdout.write(colors.dim("Files: codehere couldn't track changes here (this folder isn't a git repository).\n\n"));
127
- }
128
- else if (files.length > 0) {
129
- process.stdout.write(colors.bold('Files changed:\n'));
130
- for (const f of files) {
131
- const trust = typeof f.trust === 'number' ? colors.dim(` · trust ${f.trust}/100`) : '';
132
- process.stdout.write(` • ${f.path} ${colors.success('+' + f.added)}/${colors.error('-' + f.removed)}${trust}\n`);
133
- }
134
- process.stdout.write('\n');
135
- }
136
- // Verdict line · color-coded by status
137
- const verdict = verdictLine(result);
138
- process.stdout.write(colors.bold('Fact-check: ') + verdict + '\n\n');
139
- // Findings detail
140
- if (result.findings.length > 0 && result.status !== 'no-report') {
141
- process.stdout.write(colors.bold('Findings:\n\n'));
142
- for (let i = 0; i < result.findings.length; i++) {
143
- const f = result.findings[i];
144
- const num = colors.dim(` ${(i + 1).toString().padStart(2)}. `);
145
- const sev = severityTag(f.severity);
146
- const kind = colors.gray(`[${f.kind}]`);
147
- process.stdout.write(`${num}${sev} ${kind} ${f.message}\n`);
148
- process.stdout.write(` ${colors.dim('claim:')} ${colors.gray(f.claim)}\n`);
149
- process.stdout.write(` ${colors.dim('reality:')} ${colors.gray(f.reality)}\n\n`);
150
- }
151
- }
152
- // What was checked (so users know the verifier's scope)
153
- process.stdout.write(colors.dim('What was checked:\n'));
154
- process.stdout.write(colors.dim(' · numeric test claims (X tests passed, X of Y, etc) vs artifacts.tests\n'));
155
- process.stdout.write(colors.dim(' · universal claims (all tests pass, no failures) vs artifacts.tests.failed\n'));
156
- process.stdout.write(colors.dim(' · file claims (X files changed, no files changed) vs artifacts.files\n'));
157
- process.stdout.write(colors.dim('Not checked: prose claims, intent, semantic correctness of changes.\n\n'));
158
- }
159
- function verdictLine(result) {
160
- switch (result.status) {
161
- case 'verified':
162
- return colors.green(`${symbols.success} Verified`) + colors.dim(' ' + result.summary);
163
- case 'partial':
164
- return colors.warning(`${symbols.warning} Partial`) + colors.dim(' ' + result.summary);
165
- case 'broken':
166
- return colors.error(`${symbols.error} Broken`) + colors.dim(' ' + result.summary);
167
- case 'no-report':
168
- return colors.gray(`${symbols.dot} No report`) + colors.dim(' ' + result.summary);
169
- }
170
- }
171
- function severityTag(sev) {
172
- switch (sev) {
173
- case 'fail':
174
- return colors.error('fail');
175
- case 'warn':
176
- return colors.warning('warn');
177
- case 'info':
178
- return colors.info('info');
179
- }
180
- }
181
- /* ──────────────────────────────────────────────────────────────────────── */
182
- /* JSON serialization */
183
- /* ──────────────────────────────────────────────────────────────────────── */
184
- function serializeResult(session, result) {
185
- return {
186
- sessionId: session.sessionId,
187
- agent: session.agent,
188
- prompt: session.prompt,
189
- completedAt: session.completedAt,
190
- durationMs: session.durationMs,
191
- hasFinalReport: Boolean(session.finalReport),
192
- verdict: {
193
- status: result.status,
194
- summary: result.summary,
195
- findings: result.findings.map((f) => ({
196
- severity: f.severity,
197
- kind: f.kind,
198
- claim: f.claim,
199
- reality: f.reality,
200
- message: f.message,
201
- })),
202
- },
203
- };
204
- }
205
- /* ──────────────────────────────────────────────────────────────────────── */
206
- /* Small utilities */
207
- /* ──────────────────────────────────────────────────────────────────────── */
208
- function formatRelativeTime(ts) {
209
- if (!ts || ts <= 0)
210
- return 'unknown';
211
- const deltaMs = Date.now() - ts;
212
- if (deltaMs < 0)
213
- return 'just now';
214
- const seconds = Math.floor(deltaMs / 1000);
215
- if (seconds < 60)
216
- return `${seconds}s ago`;
217
- const minutes = Math.floor(seconds / 60);
218
- if (minutes < 60)
219
- return `${minutes}m ago`;
220
- const hours = Math.floor(minutes / 60);
221
- if (hours < 24)
222
- return `${hours}h ago`;
223
- const days = Math.floor(hours / 24);
224
- if (days < 30)
225
- return `${days}d ago`;
226
- return new Date(ts).toISOString().split('T')[0];
227
- }
228
- function truncate(s, max) {
229
- if (s.length <= max)
230
- return s;
231
- return s.slice(0, max - 1).trimEnd() + '…';
232
- }
233
- //# sourceMappingURL=verify-command.js.map
@@ -1,336 +0,0 @@
1
- /**
2
- * Centralized Error Display Utility
3
- * Provides consistent, helpful error messages with recovery suggestions
4
- *
5
- * Clean Architecture: Presentation Layer
6
- */
7
- import { ErrorType, classifyError, EnterpriseError } from '../../error-handler.js';
8
- import { colors, separator, newline, symbols } from '../../ui.js';
9
- /**
10
- * Determine error severity based on error type
11
- */
12
- function getErrorSeverity(errorType) {
13
- switch (errorType) {
14
- case ErrorType.FATAL:
15
- case ErrorType.POLICY:
16
- return 'critical';
17
- case ErrorType.RATE_LIMIT:
18
- case ErrorType.API_ERROR:
19
- case ErrorType.VALIDATION:
20
- return 'warning';
21
- case ErrorType.NETWORK:
22
- case ErrorType.RETRYABLE:
23
- return 'info';
24
- default:
25
- return 'warning';
26
- }
27
- }
28
- /**
29
- * Get severity label (text-based, enterprise-grade)
30
- */
31
- function getSeverityLabel(severity) {
32
- switch (severity) {
33
- case 'critical':
34
- return colors.red('[CRITICAL] Error:');
35
- case 'warning':
36
- return colors.yellow('[WARNING] Error:');
37
- case 'info':
38
- return colors.cyan('[INFO] Error:');
39
- default:
40
- return colors.red('Error:');
41
- }
42
- }
43
- /**
44
- * Extract file path from error message
45
- */
46
- function extractFilePath(errorMessage) {
47
- // Patterns: "File not found: path/to/file", "in path/to/file", "at path/to/file"
48
- const patterns = [
49
- /(?:File|file)\s+(?:not found|error|issue)[:\s]+([^\s]+)/i,
50
- /(?:in|at)\s+([^\s]+\.(ts|js|py|json|md|yaml|yml))/i,
51
- /([^\s]+\.(ts|js|py|json|md|yaml|yml)(?::\d+)?)/i,
52
- ];
53
- for (const pattern of patterns) {
54
- const match = errorMessage.match(pattern);
55
- if (match && match[1]) {
56
- return match[1].replace(/^["']|["']$/g, ''); // Remove quotes
57
- }
58
- }
59
- return undefined;
60
- }
61
- /**
62
- * Extract line number from error message
63
- */
64
- function extractLineNumber(errorMessage) {
65
- // Patterns: "line 42", ":42", "at line 42"
66
- const patterns = [/(?:line|Line)\s+(\d+)/i, /:(\d+):/, /\((\d+)\)/];
67
- for (const pattern of patterns) {
68
- const match = errorMessage.match(pattern);
69
- if (match && match[1]) {
70
- const line = parseInt(match[1], 10);
71
- if (!isNaN(line) && line > 0) {
72
- return line;
73
- }
74
- }
75
- }
76
- return undefined;
77
- }
78
- /**
79
- * Get recovery commands based on error type and context
80
- */
81
- function getRecoveryCommands(errorType, errorMessage, context) {
82
- const commands = [];
83
- const lowerMessage = errorMessage.toLowerCase();
84
- switch (errorType) {
85
- case ErrorType.VALIDATION:
86
- if (lowerMessage.includes('file') || lowerMessage.includes('not found')) {
87
- if (context.filepath) {
88
- commands.push(`codehere trust ${context.filepath}`);
89
- }
90
- }
91
- break;
92
- case ErrorType.API_ERROR:
93
- if (lowerMessage.includes('api') || lowerMessage.includes('key')) {
94
- commands.push('codehere setup');
95
- commands.push('codehere config --help');
96
- }
97
- break;
98
- case ErrorType.POLICY:
99
- if (context.filepath) {
100
- commands.push(`codehere trust ${context.filepath}`);
101
- commands.push('codehere config policies');
102
- }
103
- break;
104
- case ErrorType.RATE_LIMIT:
105
- commands.push('codehere config --help');
106
- break;
107
- default:
108
- break;
109
- }
110
- return commands;
111
- }
112
- /**
113
- * Get help command for operation (Task 7.3: Contextual Help Integration)
114
- */
115
- function getHelpCommandForOperation(operation) {
116
- const operationLower = operation.toLowerCase();
117
- // Map operations to help commands
118
- if (operationLower.includes('ask') || operationLower.includes('question')) {
119
- return 'ask';
120
- }
121
- if (operationLower.includes('explain')) {
122
- return 'explain';
123
- }
124
- if (operationLower.includes('plan')) {
125
- return 'plan';
126
- }
127
- if (operationLower.includes('orchestrate')) {
128
- return 'orchestrate';
129
- }
130
- if (operationLower.includes('react')) {
131
- return 'react';
132
- }
133
- if (operationLower.includes('index')) {
134
- return 'index';
135
- }
136
- if (operationLower.includes('setup') || operationLower.includes('config')) {
137
- return 'setup';
138
- }
139
- if (operationLower.includes('undo')) {
140
- return 'undo';
141
- }
142
- if (operationLower.includes('trace')) {
143
- return 'trace';
144
- }
145
- return null;
146
- }
147
- /**
148
- * Get documentation link for error type
149
- */
150
- function getDocumentationLink(errorType) {
151
- const baseUrl = 'https://docs.codehere.dev';
152
- switch (errorType) {
153
- case ErrorType.POLICY:
154
- return `${baseUrl}/security-policies`;
155
- case ErrorType.API_ERROR:
156
- case ErrorType.RATE_LIMIT:
157
- return `${baseUrl}/setup/api-keys`;
158
- case ErrorType.VALIDATION:
159
- return `${baseUrl}/troubleshooting`;
160
- case ErrorType.NETWORK:
161
- return `${baseUrl}/troubleshooting/network`;
162
- default:
163
- return undefined;
164
- }
165
- }
166
- /**
167
- * Generate error code for troubleshooting
168
- */
169
- function generateErrorCode(errorType, errorMessage) {
170
- const prefix = errorType.toUpperCase().substring(0, 3);
171
- const hash = errorMessage.split('').reduce((acc, char) => {
172
- return (acc << 5) - acc + char.charCodeAt(0);
173
- }, 0);
174
- const code = Math.abs(hash).toString(16).substring(0, 4).toUpperCase();
175
- return `${prefix}-${code}`;
176
- }
177
- /**
178
- * Display error with helpful context and recovery suggestions
179
- */
180
- export function displayError(error, options = {}) {
181
- const { operation = 'operation', query, showSuggestions = true, showStack = false } = options;
182
- const errorType = classifyError(error);
183
- const errorMessage = error instanceof Error ? error.message : String(error);
184
- const isEnterpriseError = error instanceof EnterpriseError;
185
- // Generate error code for troubleshooting
186
- const errorCode = generateErrorCode(errorType, errorMessage);
187
- // Determine error severity (based on error type)
188
- const severity = getErrorSeverity(errorType);
189
- // Extract file/line context from error message or options
190
- const fileContext = options.filepath || extractFilePath(errorMessage);
191
- const lineContext = options.lineNumber || extractLineNumber(errorMessage);
192
- // Display error header
193
- newline();
194
- console.log(separator('═', 80));
195
- // Show severity indicator (text-based, no emojis for enterprise)
196
- const severityLabel = getSeverityLabel(severity);
197
- if (severityLabel) {
198
- console.log(severityLabel + ` ${errorMessage}`);
199
- }
200
- else {
201
- console.log(colors.red(`Error: ${errorMessage}`));
202
- }
203
- if (errorCode) {
204
- console.log(colors.dim(`Error Code: ${errorCode}`));
205
- }
206
- // Show file/line context if available
207
- if (fileContext) {
208
- console.log(colors.dim(`File: ${fileContext}${lineContext ? `:${lineContext}` : ''}`));
209
- }
210
- console.log(separator('═', 80));
211
- newline();
212
- // Show error type if it's an EnterpriseError
213
- if (isEnterpriseError) {
214
- console.log(colors.dim(`Type: ${errorType}`));
215
- if (error.context?.attempt !== undefined) {
216
- console.log(colors.dim(`Attempt: ${error.context.attempt + 1}/${error.context.maxRetries || '?'}`));
217
- }
218
- newline();
219
- }
220
- // Show suggestions based on error type
221
- if (showSuggestions) {
222
- const suggestions = getErrorSuggestions(errorType, errorMessage, { operation, query, filepath: fileContext });
223
- if (suggestions.length > 0) {
224
- console.log(colors.bold('Suggestions:'));
225
- suggestions.forEach((suggestion) => {
226
- console.log(colors.dim(` ${symbols.bullet} ${suggestion}`));
227
- });
228
- newline();
229
- }
230
- // Show recovery commands for certain error types
231
- const recoveryCommands = getRecoveryCommands(errorType, errorMessage, {
232
- operation,
233
- query,
234
- filepath: fileContext,
235
- lineNumber: lineContext,
236
- });
237
- if (recoveryCommands.length > 0) {
238
- console.log(colors.bold('Recovery Commands:'));
239
- recoveryCommands.forEach((cmd) => {
240
- console.log(colors.cyan(` $ ${cmd}`));
241
- });
242
- newline();
243
- }
244
- // Show documentation link for complex errors
245
- const docLink = getDocumentationLink(errorType);
246
- if (docLink) {
247
- console.log(colors.dim(`Learn More: ${docLink}`));
248
- newline();
249
- }
250
- // Contextual help suggestion (Task 7.3: Contextual Help Integration)
251
- if (operation) {
252
- const helpCommand = getHelpCommandForOperation(operation);
253
- if (helpCommand) {
254
- console.log(colors.dim(`Get help: ${colors.cyan(`codehere help ${helpCommand}`)}`));
255
- newline();
256
- }
257
- }
258
- }
259
- // Show stack trace if requested (for debugging)
260
- if (showStack && error instanceof Error && error.stack) {
261
- console.log(colors.dim('Stack trace:'));
262
- console.log(colors.dim(error.stack));
263
- newline();
264
- }
265
- }
266
- /**
267
- * Get recovery suggestions based on error type
268
- */
269
- function getErrorSuggestions(errorType, errorMessage, _context) {
270
- const suggestions = [];
271
- const lowerMessage = errorMessage.toLowerCase();
272
- switch (errorType) {
273
- case ErrorType.RATE_LIMIT:
274
- suggestions.push("You've reached the API rate limit or monthly quota");
275
- suggestions.push('Wait a moment and try again');
276
- suggestions.push('Check your API key limits at: https://dashboard.cohere.com/api-keys');
277
- suggestions.push('Consider upgrading your API key for higher limits');
278
- break;
279
- case ErrorType.API_ERROR:
280
- case ErrorType.VALIDATION:
281
- if (lowerMessage.includes('api') || lowerMessage.includes('key')) {
282
- suggestions.push('Check your COHERE_API_KEY is set correctly');
283
- suggestions.push('Verify your API key at: https://dashboard.cohere.com/api-keys');
284
- suggestions.push('Make sure .env file exists in your project root');
285
- suggestions.push('Run "codehere setup" to configure your API key');
286
- suggestions.push('For troubleshooting, include the error code when reporting issues');
287
- }
288
- else if (lowerMessage.includes('not found') || lowerMessage.includes('missing')) {
289
- suggestions.push("Make sure you're in the correct directory");
290
- suggestions.push('Run "codehere trust ." to verify the path is scanned');
291
- }
292
- else {
293
- suggestions.push('Check the error message above for specific details');
294
- suggestions.push('Run "codehere setup" to verify your configuration');
295
- }
296
- break;
297
- case ErrorType.NETWORK:
298
- suggestions.push('Check your internet connection');
299
- suggestions.push('Verify the API service is accessible');
300
- suggestions.push('Try again in a few moments');
301
- break;
302
- case ErrorType.POLICY:
303
- suggestions.push('The operation was blocked by safety policies');
304
- suggestions.push('Review the policy reason above');
305
- suggestions.push('Modify your request to comply with safety rules');
306
- break;
307
- case ErrorType.FATAL:
308
- suggestions.push('This is a fatal error that cannot be recovered');
309
- suggestions.push('Check the error message for details');
310
- suggestions.push('If this persists, please report the issue');
311
- break;
312
- default:
313
- // Generic suggestions for retryable errors
314
- if (lowerMessage.includes('file') || lowerMessage.includes('path')) {
315
- suggestions.push('Verify the file path is correct');
316
- suggestions.push('Check file permissions');
317
- }
318
- else if (lowerMessage.includes('memory') || lowerMessage.includes('database')) {
319
- suggestions.push('Run "codehere health" to inspect runtime state');
320
- }
321
- else {
322
- suggestions.push('This error may be temporary - try again');
323
- suggestions.push('Check the error message for specific details');
324
- }
325
- }
326
- return suggestions;
327
- }
328
- /**
329
- * Display error and exit with appropriate code
330
- */
331
- export function displayErrorAndExit(error, options = {}) {
332
- const { exitCode = 1, ...displayOptions } = options;
333
- displayError(error, displayOptions);
334
- process.exit(exitCode);
335
- }
336
- //# sourceMappingURL=error-display.js.map