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.
- package/README.md +37 -184
- package/dist/application/use-cases/check-claimed-tests.js +81 -0
- package/dist/application/use-cases/detect-test-weakening.js +237 -0
- package/dist/application/use-cases/rerun-tests.js +329 -0
- package/dist/index.js +74 -1004
- package/dist/infrastructure/orchestration/artifacts-extractor.js +2 -265
- package/dist/presentation/cli/commands/check-command.js +251 -0
- package/dist/presentation/cli/commands/help-command.js +22 -286
- package/dist/ui.js +19 -438
- package/dist/utils/version.js +0 -12
- package/package.json +18 -27
- package/dist/application/use-cases/domain-trust.js +0 -110
- package/dist/application/use-cases/generate-final-report.js +0 -134
- package/dist/application/use-cases/generate-narration.js +0 -128
- package/dist/application/use-cases/generate-thread-title.js +0 -178
- package/dist/application/use-cases/narrator-prompt-template.js +0 -158
- package/dist/application/use-cases/thread-export.js +0 -155
- package/dist/application/use-cases/verify-claim.js +0 -274
- package/dist/application/use-cases/write-pass.js +0 -277
- package/dist/domain/entities/task.js +0 -61
- package/dist/domain/services/codebase-detector.js +0 -91
- package/dist/error-handler.js +0 -251
- package/dist/infrastructure/completion/bash-completion.js +0 -25
- package/dist/infrastructure/completion/fish-completion.js +0 -22
- package/dist/infrastructure/completion/zsh-completion.js +0 -30
- package/dist/infrastructure/config/config-manager.js +0 -173
- package/dist/infrastructure/config/product-context.js +0 -67
- package/dist/infrastructure/context/adapters/drawio-source.js +0 -157
- package/dist/infrastructure/context/adapters/figma-source.js +0 -163
- package/dist/infrastructure/context/adapters/github-issue-source.js +0 -159
- package/dist/infrastructure/context/adapters/linear-source.js +0 -190
- package/dist/infrastructure/context/context-resolver.js +0 -144
- package/dist/infrastructure/context/context-source.js +0 -114
- package/dist/infrastructure/context/oauth-flow.js +0 -207
- package/dist/infrastructure/context/oauth-store.js +0 -119
- package/dist/infrastructure/context/registry-bootstrap.js +0 -99
- package/dist/infrastructure/context/write-pass-resolver.js +0 -106
- package/dist/infrastructure/cost/budget-config.js +0 -113
- package/dist/infrastructure/cost/cost-router.js +0 -104
- package/dist/infrastructure/cost/spend-aggregator.js +0 -147
- package/dist/infrastructure/hooks/claude-sdk-hook.js +0 -888
- package/dist/infrastructure/hooks/hook-mode.js +0 -71
- package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +0 -43
- package/dist/infrastructure/hooks/pre-prompt-scan.js +0 -122
- package/dist/infrastructure/hooks/session-analyzer.js +0 -177
- package/dist/infrastructure/observability/execution-tracer.js +0 -227
- package/dist/infrastructure/orchestration/agent-adapter.js +0 -13
- package/dist/infrastructure/orchestration/agent-installer.js +0 -101
- package/dist/infrastructure/orchestration/agents-config-seed.js +0 -56
- package/dist/infrastructure/orchestration/aider-adapter.js +0 -447
- package/dist/infrastructure/orchestration/cassette-recorder.js +0 -120
- package/dist/infrastructure/orchestration/claude-code-adapter.js +0 -478
- package/dist/infrastructure/orchestration/codex-adapter.js +0 -538
- package/dist/infrastructure/orchestration/conductor-adapter.js +0 -377
- package/dist/infrastructure/orchestration/context-handoff.js +0 -144
- package/dist/infrastructure/orchestration/control/codex-control-surface.js +0 -99
- package/dist/infrastructure/orchestration/control/control-surface.js +0 -15
- package/dist/infrastructure/orchestration/failover-classifier.js +0 -151
- package/dist/infrastructure/orchestration/failover-config.js +0 -77
- package/dist/infrastructure/orchestration/failover-policy.js +0 -106
- package/dist/infrastructure/orchestration/gemini-adapter.js +0 -583
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +0 -558
- package/dist/infrastructure/orchestration/graphify-context.js +0 -254
- package/dist/infrastructure/orchestration/memory-injector.js +0 -380
- package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +0 -233
- package/dist/infrastructure/orchestration/mocks/mock-codex-app-server.js +0 -73
- package/dist/infrastructure/orchestration/mocks/mock-synthesis.js +0 -83
- package/dist/infrastructure/orchestration/mocks/resolve-agent-spawn.js +0 -37
- package/dist/infrastructure/orchestration/opencode-adapter.js +0 -510
- package/dist/infrastructure/orchestration/progress-aggregator.js +0 -689
- package/dist/infrastructure/orchestration/readiness.js +0 -103
- package/dist/infrastructure/orchestration/session-manager.js +0 -1091
- package/dist/infrastructure/orchestration/session-persistence.js +0 -258
- package/dist/infrastructure/orchestration/thread-key-store.js +0 -127
- package/dist/infrastructure/orchestration/write-pass-store.js +0 -46
- package/dist/infrastructure/protocols/cloud-sync.js +0 -207
- package/dist/infrastructure/protocols/mcp-helpers.js +0 -25
- package/dist/infrastructure/protocols/mcp-server-impl.js +0 -2853
- package/dist/infrastructure/protocols/probe-port.js +0 -36
- package/dist/infrastructure/protocols/thread-phase.js +0 -105
- package/dist/infrastructure/protocols/ui-page-v2.js +0 -4418
- package/dist/infrastructure/protocols/ui-page.js +0 -2377
- package/dist/infrastructure/protocols/verify-page.js +0 -983
- package/dist/infrastructure/security/file-collection.js +0 -118
- package/dist/infrastructure/security/input-validator.js +0 -152
- package/dist/infrastructure/security/permissions-config.js +0 -234
- package/dist/infrastructure/security/trust-scorer.js +0 -657
- package/dist/infrastructure/storage/cross-tool-agents.js +0 -268
- package/dist/infrastructure/storage/embeddings-path.js +0 -37
- package/dist/infrastructure/storage/project-thread-migration.js +0 -237
- package/dist/infrastructure/storage/project-thread-mirror.js +0 -524
- package/dist/infrastructure/storage/project-thread-reader.js +0 -172
- package/dist/infrastructure/storage/project-thread-title-backfill.js +0 -214
- package/dist/infrastructure/storage/task-repository.js +0 -206
- package/dist/monitoring.js +0 -212
- package/dist/presentation/cli/commands/audit-command.js +0 -126
- package/dist/presentation/cli/commands/budget-command.js +0 -79
- package/dist/presentation/cli/commands/config-command.js +0 -125
- package/dist/presentation/cli/commands/context-source-command.js +0 -198
- package/dist/presentation/cli/commands/hook-command.js +0 -265
- package/dist/presentation/cli/commands/init-command.js +0 -578
- package/dist/presentation/cli/commands/memory-command.js +0 -1031
- package/dist/presentation/cli/commands/narrator-command.js +0 -101
- package/dist/presentation/cli/commands/permission-command.js +0 -116
- package/dist/presentation/cli/commands/protocols-builder.js +0 -254
- package/dist/presentation/cli/commands/protocols-command.js +0 -84
- package/dist/presentation/cli/commands/repo-map-builder.js +0 -247
- package/dist/presentation/cli/commands/report-command.js +0 -387
- package/dist/presentation/cli/commands/scan-tool-command.js +0 -94
- package/dist/presentation/cli/commands/setup-command.js +0 -307
- package/dist/presentation/cli/commands/status-command.js +0 -661
- package/dist/presentation/cli/commands/thread-command.js +0 -288
- package/dist/presentation/cli/commands/trust-command.js +0 -306
- package/dist/presentation/cli/commands/verify-command.js +0 -233
- package/dist/presentation/cli/error-display.js +0 -336
- package/dist/presentation/cli/repl.js +0 -797
- package/dist/presentation/cli/task-deliverable.js +0 -127
- package/dist/testing/cassette.js +0 -125
- package/dist/testing/replay-adapter.js +0 -166
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI: `codehere audit`
|
|
3
|
-
*
|
|
4
|
-
* F-05 of the demo-v12 backlog · expose the hash-chained audit log verifier
|
|
5
|
-
* + a "show" subcommand for forensic inspection. The chain is the source of
|
|
6
|
-
* truth, NOT codehere itself · this command lets reviewers and CI verify it
|
|
7
|
-
* without trusting our daemon.
|
|
8
|
-
*
|
|
9
|
-
* Subcommands:
|
|
10
|
-
* codehere audit verify [--json] Walk the chain · report intact/tampered
|
|
11
|
-
* + entry counts + every break point.
|
|
12
|
-
* Exit 0 = valid, 1 = invalid.
|
|
13
|
-
* codehere audit show <seq> [--json]
|
|
14
|
-
* Print one entry by sequence number.
|
|
15
|
-
*
|
|
16
|
-
* Default audit file: ~/.codehere/audit/hook-events.jsonl
|
|
17
|
-
* Override via CODEHERE_AUDIT_FILE env var (mirrors the hook's own resolution).
|
|
18
|
-
*/
|
|
19
|
-
import { existsSync, readFileSync } from 'fs';
|
|
20
|
-
import { colors, symbols } from '../../../ui.js';
|
|
21
|
-
import { AUDIT_FILE, verifyAuditChain } from '../../../infrastructure/hooks/claude-sdk-hook.js';
|
|
22
|
-
export function executeAuditCommand(sub, arg, options = {}) {
|
|
23
|
-
if (!sub || sub === 'verify')
|
|
24
|
-
return verify(options.json ?? false);
|
|
25
|
-
if (sub === 'show')
|
|
26
|
-
return show(arg, options.json ?? false);
|
|
27
|
-
process.stderr.write(colors.error(`${symbols.error} Unknown audit subcommand: ${sub}\n`) +
|
|
28
|
-
colors.dim('Try: codehere audit verify | codehere audit show <seq>\n'));
|
|
29
|
-
return 2;
|
|
30
|
-
}
|
|
31
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
32
|
-
/* verify · the F-05 headline */
|
|
33
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
34
|
-
function verify(json) {
|
|
35
|
-
const result = verifyAuditChain(AUDIT_FILE);
|
|
36
|
-
if (json) {
|
|
37
|
-
process.stdout.write(JSON.stringify({
|
|
38
|
-
path: AUDIT_FILE,
|
|
39
|
-
valid: result.valid,
|
|
40
|
-
totalEntries: result.totalEntries,
|
|
41
|
-
chainedEntries: result.chainedEntries,
|
|
42
|
-
legacyEntries: result.legacyEntries,
|
|
43
|
-
errors: result.errors,
|
|
44
|
-
}, null, 2) + '\n');
|
|
45
|
-
return result.valid ? 0 : 1;
|
|
46
|
-
}
|
|
47
|
-
// Human output · header, verdict line, counts, then errors if any.
|
|
48
|
-
process.stdout.write('\n' + colors.dim('audit log: ') + colors.gray(AUDIT_FILE) + '\n\n');
|
|
49
|
-
if (result.totalEntries === 0) {
|
|
50
|
-
process.stdout.write(colors.gray(`${symbols.dot} No audit entries yet.`) +
|
|
51
|
-
colors.dim(' Install the hook first: ') +
|
|
52
|
-
colors.bold('codehere hook install') +
|
|
53
|
-
'\n\n');
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
56
|
-
if (result.valid) {
|
|
57
|
-
process.stdout.write(colors.green(`${symbols.success} Chain intact`) +
|
|
58
|
-
colors.dim(' every entry verified against its predecessor hash.') +
|
|
59
|
-
'\n\n');
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
process.stdout.write(colors.error(`${symbols.error} Chain BROKEN`) +
|
|
63
|
-
colors.dim(` ${result.errors.length} break point${result.errors.length === 1 ? '' : 's'} detected.`) +
|
|
64
|
-
'\n\n');
|
|
65
|
-
}
|
|
66
|
-
process.stdout.write(colors.bold('Counts:\n'));
|
|
67
|
-
process.stdout.write(` ${result.totalEntries.toString().padStart(6)} total entries\n`);
|
|
68
|
-
process.stdout.write(` ${result.chainedEntries.toString().padStart(6)} hash-chained (verifiable)\n`);
|
|
69
|
-
process.stdout.write(` ${result.legacyEntries.toString().padStart(6)} legacy pre-chain (un-verifiable)\n\n`);
|
|
70
|
-
if (result.errors.length > 0) {
|
|
71
|
-
process.stdout.write(colors.bold('Break points:\n'));
|
|
72
|
-
for (const err of result.errors) {
|
|
73
|
-
process.stdout.write(' ' +
|
|
74
|
-
colors.error(`line ${err.lineNumber}`) +
|
|
75
|
-
colors.dim(' ') +
|
|
76
|
-
colors.gray(err.reason) +
|
|
77
|
-
colors.dim(' ') +
|
|
78
|
-
err.detail +
|
|
79
|
-
'\n');
|
|
80
|
-
}
|
|
81
|
-
process.stdout.write('\n');
|
|
82
|
-
}
|
|
83
|
-
return result.valid ? 0 : 1;
|
|
84
|
-
}
|
|
85
|
-
function show(seqStr, json) {
|
|
86
|
-
if (!seqStr || !/^\d+$/.test(seqStr)) {
|
|
87
|
-
process.stderr.write(colors.error(`${symbols.error} Need a numeric sequence: codehere audit show <seq>\n`));
|
|
88
|
-
return 2;
|
|
89
|
-
}
|
|
90
|
-
const target = parseInt(seqStr, 10);
|
|
91
|
-
if (!existsSync(AUDIT_FILE)) {
|
|
92
|
-
process.stderr.write(colors.gray(`${symbols.dot} No audit log yet.\n`));
|
|
93
|
-
return 2;
|
|
94
|
-
}
|
|
95
|
-
const lines = readFileSync(AUDIT_FILE, 'utf-8').split('\n').filter(Boolean);
|
|
96
|
-
for (const line of lines) {
|
|
97
|
-
let entry;
|
|
98
|
-
try {
|
|
99
|
-
entry = JSON.parse(line);
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
if (entry.seq !== target)
|
|
105
|
-
continue;
|
|
106
|
-
if (json) {
|
|
107
|
-
process.stdout.write(JSON.stringify(entry, null, 2) + '\n');
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
process.stdout.write('\n' +
|
|
111
|
-
colors.bold(`Entry #${target}`) +
|
|
112
|
-
(entry.ts ? colors.dim(' ' + new Date(entry.ts).toISOString()) : '') +
|
|
113
|
-
'\n\n');
|
|
114
|
-
for (const [k, v] of Object.entries(entry)) {
|
|
115
|
-
const val = typeof v === 'string' && v.length > 120 ? v.slice(0, 117) + '...' : JSON.stringify(v);
|
|
116
|
-
process.stdout.write(` ${colors.dim(k.padEnd(12))} ${val}\n`);
|
|
117
|
-
}
|
|
118
|
-
process.stdout.write('\n');
|
|
119
|
-
}
|
|
120
|
-
return 0;
|
|
121
|
-
}
|
|
122
|
-
process.stderr.write(colors.error(`${symbols.error} No entry with seq=${target}.\n`) +
|
|
123
|
-
colors.dim(' Tip: run `codehere audit verify` to see the chained-entry count.\n'));
|
|
124
|
-
return 2;
|
|
125
|
-
}
|
|
126
|
-
//# sourceMappingURL=audit-command.js.map
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `codehere budget` — read or set the daily-spend budget.
|
|
3
|
-
*
|
|
4
|
-
* Subcommands:
|
|
5
|
-
* show — print current ceiling, today's spend, % used
|
|
6
|
-
* set <usd> — set daily ceiling in USD (e.g. `codehere budget set 5`)
|
|
7
|
-
* off — disable the budget (omits daily_usd from yaml)
|
|
8
|
-
*
|
|
9
|
-
* Reads + writes ~/.codehere/budget.yaml via budget-config.ts. Per
|
|
10
|
-
* claim_user_persona HIGH the YAML is hand-editable; the CLI is the
|
|
11
|
-
* fast path for users who want one number, one command.
|
|
12
|
-
*/
|
|
13
|
-
import { loadBudget, saveBudget, budgetUsedPct, isOverBudget } from '../../../infrastructure/cost/budget-config.js';
|
|
14
|
-
import { computeSpendToday } from '../../../infrastructure/cost/spend-aggregator.js';
|
|
15
|
-
import { success, error, info, newline } from '../../../ui.js';
|
|
16
|
-
export async function executeBudgetCommand(subcommand, value) {
|
|
17
|
-
const sub = subcommand ?? 'show';
|
|
18
|
-
switch (sub) {
|
|
19
|
-
case 'show':
|
|
20
|
-
return showBudget();
|
|
21
|
-
case 'set':
|
|
22
|
-
if (!value) {
|
|
23
|
-
console.error(error('Usage:'), 'codehere budget set <amount-in-usd> e.g. codehere budget set 5');
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
return setBudget(value);
|
|
27
|
-
case 'off':
|
|
28
|
-
return disableBudget();
|
|
29
|
-
default:
|
|
30
|
-
console.error(error('Unknown subcommand:'), sub);
|
|
31
|
-
console.error(info('Try:'), 'codehere budget [show | set <usd> | off]');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function fmtUsd(n) {
|
|
36
|
-
return n >= 0.01 ? `$${n.toFixed(2)}` : `$${n.toFixed(3)}`;
|
|
37
|
-
}
|
|
38
|
-
function showBudget() {
|
|
39
|
-
const cfg = loadBudget();
|
|
40
|
-
const spend = computeSpendToday();
|
|
41
|
-
newline();
|
|
42
|
-
console.log(info("Today's estimated spend:"), fmtUsd(spend.totalUsd), `(${spend.sessionCount} session${spend.sessionCount === 1 ? '' : 's'})`);
|
|
43
|
-
if (cfg.dailyUsd === null) {
|
|
44
|
-
console.log(info('Daily budget:'), 'none — no enforcement');
|
|
45
|
-
console.log(info('Set one with:'), 'codehere budget set 5');
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
const pct = budgetUsedPct(spend.totalUsd, cfg) ?? 0;
|
|
49
|
-
const over = isOverBudget(spend.totalUsd, cfg);
|
|
50
|
-
console.log(info('Daily budget:'), fmtUsd(cfg.dailyUsd), `(${pct}% used)`);
|
|
51
|
-
if (over) {
|
|
52
|
-
console.log(error('Over budget.'), 'New spawns are blocked until midnight or the budget is raised.');
|
|
53
|
-
}
|
|
54
|
-
else if (pct >= cfg.warnAtPct) {
|
|
55
|
-
console.log(info('Approaching limit.'), `Warn threshold is ${cfg.warnAtPct}%.`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
newline();
|
|
59
|
-
}
|
|
60
|
-
function setBudget(value) {
|
|
61
|
-
const n = Number(value.replace(/[$,]/g, ''));
|
|
62
|
-
if (!Number.isFinite(n) || n <= 0) {
|
|
63
|
-
console.error(error('Invalid amount:'), value, '— expected a positive USD number.');
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
const cfg = loadBudget();
|
|
67
|
-
cfg.dailyUsd = n;
|
|
68
|
-
saveBudget(cfg);
|
|
69
|
-
console.log(success('Daily budget set to'), fmtUsd(n));
|
|
70
|
-
console.log(info("Spawns will be blocked once today's estimated spend reaches this amount."));
|
|
71
|
-
console.log(info('Disable with:'), 'codehere budget off');
|
|
72
|
-
}
|
|
73
|
-
function disableBudget() {
|
|
74
|
-
const cfg = loadBudget();
|
|
75
|
-
cfg.dailyUsd = null;
|
|
76
|
-
saveBudget(cfg);
|
|
77
|
-
console.log(success('Daily budget disabled.'), 'No enforcement on spawns.');
|
|
78
|
-
}
|
|
79
|
-
//# sourceMappingURL=budget-command.js.map
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Config Command
|
|
3
|
-
* Manage Codehere configuration and preferences
|
|
4
|
-
*/
|
|
5
|
-
import { colors, separator, newline, sectionHeader, success, error, createTable, isMinimalStyle } from '../../../ui.js';
|
|
6
|
-
import { getConfigManager } from '../../../infrastructure/config/config-manager.js';
|
|
7
|
-
import { executionTracer } from '../../../infrastructure/observability/execution-tracer.js';
|
|
8
|
-
import { findCodebaseRoot } from '../../../domain/services/codebase-detector.js';
|
|
9
|
-
/**
|
|
10
|
-
* Display current configuration
|
|
11
|
-
*/
|
|
12
|
-
function displayConfig(config) {
|
|
13
|
-
sectionHeader('Current Configuration');
|
|
14
|
-
const configRows = [
|
|
15
|
-
['Preference', 'Value'],
|
|
16
|
-
['Auto Commit', config.preferences.autoCommit ? 'Yes' : 'No'],
|
|
17
|
-
['Ask Before Destructive', config.preferences.askBeforeDestructive ? 'Yes' : 'No'],
|
|
18
|
-
['Cross-Team Learning', config.preferences.enableCrossTeamLearning ? 'Enabled' : 'Disabled'],
|
|
19
|
-
['Default Model', config.preferences.defaultModel || 'auto (detects from API key)'],
|
|
20
|
-
['Max Tokens', String(config.preferences.maxTokens || 4096)],
|
|
21
|
-
['Temperature', String(config.preferences.temperature || 0.3)],
|
|
22
|
-
['Streaming', config.preferences.enableStreaming ? 'Enabled' : 'Disabled'],
|
|
23
|
-
['Output Format', config.ui.outputFormat || 'full'],
|
|
24
|
-
['Show Progress', config.ui.showProgress ? 'Yes' : 'No'],
|
|
25
|
-
['Show Summary', config.ui.showSummary ? 'Yes' : 'No'],
|
|
26
|
-
];
|
|
27
|
-
if (config.codebase.root) {
|
|
28
|
-
configRows.push(['Codebase Root', config.codebase.root]);
|
|
29
|
-
if (config.codebase.lastIndexed) {
|
|
30
|
-
const date = new Date(config.codebase.lastIndexed);
|
|
31
|
-
configRows.push(['Last Indexed', date.toLocaleString()]);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
const table = createTable(['Preference', 'Value'], configRows.slice(1));
|
|
35
|
-
console.log(table.toString());
|
|
36
|
-
newline();
|
|
37
|
-
console.log(colors.dim(`Config file: ${getConfigManager().getConfigPath()}`));
|
|
38
|
-
newline();
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Execute config command
|
|
42
|
-
*/
|
|
43
|
-
export async function executeConfigCommand(action, key, value) {
|
|
44
|
-
// Start execution tracing
|
|
45
|
-
const codebaseInfo = findCodebaseRoot(process.cwd());
|
|
46
|
-
executionTracer.startRun('config', {
|
|
47
|
-
codebaseId: codebaseInfo?.rootPath || process.cwd(),
|
|
48
|
-
});
|
|
49
|
-
try {
|
|
50
|
-
if (!isMinimalStyle()) {
|
|
51
|
-
newline();
|
|
52
|
-
console.log(separator('═', 80));
|
|
53
|
-
console.log(colors.bold('Codehere - Configuration Manager'));
|
|
54
|
-
console.log(separator('═', 80));
|
|
55
|
-
newline();
|
|
56
|
-
}
|
|
57
|
-
const configManager = getConfigManager();
|
|
58
|
-
const config = configManager.getAll();
|
|
59
|
-
// No action - show current config
|
|
60
|
-
if (!action || action === 'show' || action === 'list') {
|
|
61
|
-
displayConfig(config);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
// Get value
|
|
65
|
-
if (action === 'get' && key) {
|
|
66
|
-
const preference = configManager.getPreference(key);
|
|
67
|
-
if (preference !== undefined) {
|
|
68
|
-
console.log(preference);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
console.error(error(`Preference '${key}' not found.`));
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
// Set value
|
|
77
|
-
if (action === 'set' && key && value !== undefined) {
|
|
78
|
-
try {
|
|
79
|
-
// Parse value (boolean, number, or string)
|
|
80
|
-
let parsedValue = value;
|
|
81
|
-
if (value.toLowerCase() === 'true')
|
|
82
|
-
parsedValue = true;
|
|
83
|
-
else if (value.toLowerCase() === 'false')
|
|
84
|
-
parsedValue = false;
|
|
85
|
-
else if (!isNaN(Number(value)))
|
|
86
|
-
parsedValue = Number(value);
|
|
87
|
-
configManager.setPreference(key, parsedValue);
|
|
88
|
-
configManager.saveConfig();
|
|
89
|
-
console.log(success(`Set ${key} = ${parsedValue}`));
|
|
90
|
-
}
|
|
91
|
-
catch (err) {
|
|
92
|
-
console.error(error(`Failed to set preference: ${err instanceof Error ? err.message : String(err)}`));
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
// Reset to defaults
|
|
98
|
-
if (action === 'reset') {
|
|
99
|
-
configManager.reset();
|
|
100
|
-
console.log(success('Configuration reset to defaults'));
|
|
101
|
-
newline();
|
|
102
|
-
displayConfig(configManager.getAll());
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
// Invalid action
|
|
106
|
-
console.error(error(`Unknown action: ${action}`));
|
|
107
|
-
newline();
|
|
108
|
-
console.log(colors.bold('Usage:'));
|
|
109
|
-
console.log(colors.cyan(' codehere config Show current configuration'));
|
|
110
|
-
console.log(colors.cyan(' codehere config get <key> Get a preference value'));
|
|
111
|
-
console.log(colors.cyan(' codehere config set <key> <value> Set a preference value'));
|
|
112
|
-
console.log(colors.cyan(' codehere config reset Reset to defaults'));
|
|
113
|
-
newline();
|
|
114
|
-
console.log(colors.bold('Examples:'));
|
|
115
|
-
console.log(colors.dim(' codehere config set autoCommit true'));
|
|
116
|
-
console.log(colors.dim(' codehere config set temperature 0.5'));
|
|
117
|
-
console.log(colors.dim(' codehere config get defaultModel'));
|
|
118
|
-
newline();
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
finally {
|
|
122
|
-
executionTracer.endRun();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=config-command.js.map
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI: `codehere context-source` · v0.8 S2.5
|
|
3
|
-
*
|
|
4
|
-
* Subcommands:
|
|
5
|
-
* list · show every registered provider + connection status
|
|
6
|
-
* connect <provider> · open the browser to begin OAuth · prints URL
|
|
7
|
-
* disconnect <provider> · clear the stored OAuth token
|
|
8
|
-
*
|
|
9
|
-
* Talks to the running daemon at 127.0.0.1:3773. If the daemon isn't running,
|
|
10
|
-
* we print a clear message rather than starting one silently.
|
|
11
|
-
*/
|
|
12
|
-
import { colors, symbols } from '../../../ui.js';
|
|
13
|
-
import { spawn } from 'child_process';
|
|
14
|
-
const DAEMON_BASE = process.env.CODEHERE_DAEMON_URL || 'http://127.0.0.1:3773';
|
|
15
|
-
export async function executeContextSourceCommand(sub, arg, options = {}) {
|
|
16
|
-
switch (sub) {
|
|
17
|
-
case undefined:
|
|
18
|
-
case 'list':
|
|
19
|
-
return list(options.json ?? false);
|
|
20
|
-
case 'connect':
|
|
21
|
-
return connect(arg, options.json ?? false, options.open !== false);
|
|
22
|
-
case 'disconnect':
|
|
23
|
-
return disconnect(arg, options.json ?? false);
|
|
24
|
-
default:
|
|
25
|
-
process.stderr.write(colors.error(`${symbols.error} Unknown subcommand: ${sub}\n`) +
|
|
26
|
-
colors.dim('Try: codehere context-source list | connect <provider> | disconnect <provider>\n'));
|
|
27
|
-
return 2;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async function fetchJson(path, init = {}) {
|
|
31
|
-
try {
|
|
32
|
-
const r = await fetch(DAEMON_BASE + path, init);
|
|
33
|
-
if (!r.ok) {
|
|
34
|
-
const text = await r.text();
|
|
35
|
-
return { ok: false, status: r.status, error: text };
|
|
36
|
-
}
|
|
37
|
-
return { ok: true, status: r.status, data: (await r.json()) };
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
return { ok: false, status: 0, error: err instanceof Error ? err.message : String(err) };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
function daemonUnreachableNote(err) {
|
|
44
|
-
return (colors.error(`${symbols.error} Daemon not reachable at ${DAEMON_BASE}.\n`) +
|
|
45
|
-
colors.dim(` Start it with: `) +
|
|
46
|
-
colors.bold('codehere start') +
|
|
47
|
-
'\n' +
|
|
48
|
-
colors.dim(` Detail: ${err}\n`));
|
|
49
|
-
}
|
|
50
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
51
|
-
/* list */
|
|
52
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
53
|
-
async function list(json) {
|
|
54
|
-
const r = await fetchJson('/api/context-sources');
|
|
55
|
-
if (!r.ok) {
|
|
56
|
-
if (json) {
|
|
57
|
-
process.stdout.write(JSON.stringify({ error: 'daemon_unreachable', detail: r.error }, null, 2) + '\n');
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
process.stderr.write(daemonUnreachableNote(r.error ?? ''));
|
|
61
|
-
}
|
|
62
|
-
return 2;
|
|
63
|
-
}
|
|
64
|
-
const items = r.data?.providers ?? [];
|
|
65
|
-
if (json) {
|
|
66
|
-
process.stdout.write(JSON.stringify({ providers: items }, null, 2) + '\n');
|
|
67
|
-
return 0;
|
|
68
|
-
}
|
|
69
|
-
process.stdout.write('\n' + colors.bold('Context sources') + '\n\n');
|
|
70
|
-
if (!items.length) {
|
|
71
|
-
process.stdout.write(colors.dim(' (no providers registered)\n\n'));
|
|
72
|
-
return 0;
|
|
73
|
-
}
|
|
74
|
-
for (const p of items) {
|
|
75
|
-
const tag = statusTag(p.status);
|
|
76
|
-
const who = p.userLabel ? colors.gray('· ' + p.userLabel) : '';
|
|
77
|
-
process.stdout.write(` ${tag} ${colors.bold(p.label.padEnd(10))} ${colors.dim(p.scheme + '://')} ${who}\n`);
|
|
78
|
-
if (!p.clientIdConfigured) {
|
|
79
|
-
process.stdout.write(' ' + colors.warning(`set CODEHERE_${p.id.toUpperCase()}_CLIENT_ID before connect()`) + '\n');
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
process.stdout.write('\n' + colors.dim('Connect: ') + colors.bold('codehere context-source connect <provider>') + '\n\n');
|
|
83
|
-
return 0;
|
|
84
|
-
}
|
|
85
|
-
function statusTag(s) {
|
|
86
|
-
switch (s) {
|
|
87
|
-
case 'connected':
|
|
88
|
-
return colors.green('● connected ');
|
|
89
|
-
case 'expired':
|
|
90
|
-
return colors.warning('● expired ');
|
|
91
|
-
case 'manual':
|
|
92
|
-
return colors.gray('● manual ');
|
|
93
|
-
case 'disconnected':
|
|
94
|
-
return colors.gray('○ disconnected');
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
98
|
-
/* connect */
|
|
99
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
100
|
-
async function connect(providerArg, json, openBrowser) {
|
|
101
|
-
if (!providerArg) {
|
|
102
|
-
process.stderr.write(colors.error(`${symbols.error} Need a provider id: codehere context-source connect <id>\n`));
|
|
103
|
-
return 2;
|
|
104
|
-
}
|
|
105
|
-
const r = await fetchJson(`/api/context-sources/${encodeURIComponent(providerArg)}/connect`, { method: 'POST' });
|
|
106
|
-
if (!r.ok) {
|
|
107
|
-
let detail = null;
|
|
108
|
-
try {
|
|
109
|
-
detail = JSON.parse(r.error ?? '{}');
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
/* ignore */
|
|
113
|
-
}
|
|
114
|
-
if (detail?.error === 'provider_not_registered') {
|
|
115
|
-
const envVar = detail.envVar ?? `CODEHERE_${providerArg.toUpperCase()}_CLIENT_ID`;
|
|
116
|
-
if (json) {
|
|
117
|
-
process.stdout.write(JSON.stringify({ error: 'provider_not_registered', envVar, message: detail.message }, null, 2) + '\n');
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
process.stderr.write(colors.error(`${symbols.error} ${providerArg} OAuth app not registered.\n`) +
|
|
121
|
-
colors.dim(` ${detail.message ?? ''}\n`) +
|
|
122
|
-
colors.dim(` Set the env var: `) +
|
|
123
|
-
colors.bold(envVar) +
|
|
124
|
-
'\n');
|
|
125
|
-
}
|
|
126
|
-
return 2;
|
|
127
|
-
}
|
|
128
|
-
if (json) {
|
|
129
|
-
process.stdout.write(JSON.stringify({ error: 'connect_failed', detail: r.error }, null, 2) + '\n');
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
process.stderr.write(daemonUnreachableNote(r.error ?? ''));
|
|
133
|
-
}
|
|
134
|
-
return 2;
|
|
135
|
-
}
|
|
136
|
-
const url = r.data?.authorizeUrl;
|
|
137
|
-
if (!url) {
|
|
138
|
-
process.stderr.write(colors.error(`${symbols.error} Daemon did not return an authorize URL.\n`));
|
|
139
|
-
return 1;
|
|
140
|
-
}
|
|
141
|
-
if (json) {
|
|
142
|
-
process.stdout.write(JSON.stringify({ authorizeUrl: url }, null, 2) + '\n');
|
|
143
|
-
return 0;
|
|
144
|
-
}
|
|
145
|
-
process.stdout.write('\n' +
|
|
146
|
-
colors.bold(`Opening ${providerArg} OAuth flow`) +
|
|
147
|
-
'\n\n' +
|
|
148
|
-
colors.dim(' URL: ') +
|
|
149
|
-
url +
|
|
150
|
-
'\n\n' +
|
|
151
|
-
colors.dim(' Codehere will store the token at ~/.codehere/context-sources.json.\n') +
|
|
152
|
-
colors.dim(' You can close the browser tab when it says "connected".\n\n'));
|
|
153
|
-
if (openBrowser) {
|
|
154
|
-
openInBrowser(url);
|
|
155
|
-
}
|
|
156
|
-
return 0;
|
|
157
|
-
}
|
|
158
|
-
function openInBrowser(url) {
|
|
159
|
-
const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
160
|
-
try {
|
|
161
|
-
const child = spawn(cmd, [url], { detached: true, stdio: 'ignore' });
|
|
162
|
-
child.unref();
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
// best-effort · the URL is already printed
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
169
|
-
/* disconnect */
|
|
170
|
-
/* ──────────────────────────────────────────────────────────────────────── */
|
|
171
|
-
async function disconnect(providerArg, json) {
|
|
172
|
-
if (!providerArg) {
|
|
173
|
-
process.stderr.write(colors.error(`${symbols.error} Need a provider id: codehere context-source disconnect <id>\n`));
|
|
174
|
-
return 2;
|
|
175
|
-
}
|
|
176
|
-
const r = await fetchJson(`/api/context-sources/${encodeURIComponent(providerArg)}/disconnect`, { method: 'POST' });
|
|
177
|
-
if (!r.ok) {
|
|
178
|
-
if (json) {
|
|
179
|
-
process.stdout.write(JSON.stringify({ error: 'disconnect_failed', detail: r.error }, null, 2) + '\n');
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
process.stderr.write(daemonUnreachableNote(r.error ?? ''));
|
|
183
|
-
}
|
|
184
|
-
return 2;
|
|
185
|
-
}
|
|
186
|
-
if (json) {
|
|
187
|
-
process.stdout.write(JSON.stringify(r.data) + '\n');
|
|
188
|
-
return 0;
|
|
189
|
-
}
|
|
190
|
-
if (r.data?.ok) {
|
|
191
|
-
process.stdout.write(colors.green(`${symbols.success} disconnected ${providerArg}\n`));
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
process.stdout.write(colors.gray(`${symbols.dot} ${providerArg} was not connected\n`));
|
|
195
|
-
}
|
|
196
|
-
return 0;
|
|
197
|
-
}
|
|
198
|
-
//# sourceMappingURL=context-source-command.js.map
|