@orquentra/codebuddy 2.6.0 → 2.7.0
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/CLAUDE_CODEX.md +6 -4
- package/WORKFLOW.md +5 -5
- package/dist/{chunk-U4HAJLIB.js → chunk-3QGW53GD.js} +16 -3
- package/dist/chunk-3QGW53GD.js.map +1 -0
- package/dist/{chunk-L5AYZC3F.js → chunk-5EDGAZQN.js} +438 -68
- package/dist/chunk-5EDGAZQN.js.map +1 -0
- package/dist/chunk-5UH3BEQR.js +32 -0
- package/dist/chunk-5UH3BEQR.js.map +1 -0
- package/dist/{chunk-JFDRBPYF.js → chunk-6JCKMIQY.js} +2 -2
- package/dist/{chunk-UN57FKQX.js → chunk-AK2UAE32.js} +152 -862
- package/dist/chunk-AK2UAE32.js.map +1 -0
- package/dist/{chunk-GDJH7XJC.js → chunk-AL6VBTNA.js} +77 -3
- package/dist/chunk-AL6VBTNA.js.map +1 -0
- package/dist/{chunk-WHZSVY2L.js → chunk-AQHPEJR6.js} +94 -23
- package/dist/chunk-AQHPEJR6.js.map +1 -0
- package/dist/{chunk-PCE4STAY.js → chunk-BQM7FJ7D.js} +6 -6
- package/dist/chunk-BQM7FJ7D.js.map +1 -0
- package/dist/{chunk-XBJQKCLU.js → chunk-CAEPHLHC.js} +13 -9
- package/dist/chunk-CAEPHLHC.js.map +1 -0
- package/dist/chunk-CG5B3LYG.js +66 -0
- package/dist/chunk-CG5B3LYG.js.map +1 -0
- package/dist/chunk-CSRD5OQA.js +79 -0
- package/dist/chunk-CSRD5OQA.js.map +1 -0
- package/dist/{chunk-IHQM2ZDV.js → chunk-DFV2SK6C.js} +1 -1
- package/dist/{chunk-IHQM2ZDV.js.map → chunk-DFV2SK6C.js.map} +1 -1
- package/dist/chunk-EEUFU7KV.js +1634 -0
- package/dist/chunk-EEUFU7KV.js.map +1 -0
- package/dist/{chunk-UFZD3JAA.js → chunk-ESZXCZIN.js} +3 -3
- package/dist/{chunk-PYLH4MH5.js → chunk-FJOTP632.js} +1 -1
- package/dist/{chunk-SYWJG5NA.js → chunk-GKNYMNFM.js} +17 -7
- package/dist/{chunk-SYWJG5NA.js.map → chunk-GKNYMNFM.js.map} +1 -1
- package/dist/{chunk-JPHJBCZB.js → chunk-HPOR6YXA.js} +3 -2
- package/dist/chunk-HPOR6YXA.js.map +1 -0
- package/dist/chunk-JUAFCLRB.js +1014 -0
- package/dist/chunk-JUAFCLRB.js.map +1 -0
- package/dist/{chunk-776EQXDV.js → chunk-KNR2P2UY.js} +110 -83
- package/dist/chunk-KNR2P2UY.js.map +1 -0
- package/dist/{chunk-N34XHWBA.js → chunk-LCSBL5TT.js} +24 -11
- package/dist/chunk-LCSBL5TT.js.map +1 -0
- package/dist/{chunk-QDBDYCM2.js → chunk-MSUAVR3R.js} +76 -11
- package/dist/chunk-MSUAVR3R.js.map +1 -0
- package/dist/{chunk-6MKEIDX5.js → chunk-SFMIMLXR.js} +2 -2
- package/dist/chunk-TGFTKWOR.js +16 -0
- package/dist/chunk-TGFTKWOR.js.map +1 -0
- package/dist/chunk-TUR6YKEE.js +55 -0
- package/dist/chunk-TUR6YKEE.js.map +1 -0
- package/dist/chunk-Y7D7PUBE.js +321 -0
- package/dist/chunk-Y7D7PUBE.js.map +1 -0
- package/dist/{chunk-VAKBJV26.js → chunk-YJIA2MFL.js} +918 -2238
- package/dist/chunk-YJIA2MFL.js.map +1 -0
- package/dist/cli/index.js +14 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/{cloud-7WM3YLI4.js → cloud-LXZUR3U2.js} +3 -3
- package/dist/{codebuddy-DM-i0Fu5.d.ts → codebuddy-DO7ZhoWn.d.ts} +37 -3
- package/dist/config-GEZFLXK6.js +12 -0
- package/dist/docker-autostart-KDME7TVC.js +12 -0
- package/dist/index.d.ts +48 -3
- package/dist/index.js +32 -25
- package/dist/langgraph/index.d.ts +1 -1
- package/dist/lean-command-CWJAVQ5G.js +18 -0
- package/dist/local-ST4WMRCG.js +17 -0
- package/dist/{main-HFHLGID4.js → main-AHNGHC4L.js} +327 -329
- package/dist/main-AHNGHC4L.js.map +1 -0
- package/dist/{memory-4RGVLPKG.js → memory-TGHVTBME.js} +9 -8
- package/dist/memory-TGHVTBME.js.map +1 -0
- package/dist/operations-7BTAAUHF.js +26 -0
- package/dist/postgres-docker-QQZQ2ABK.js +16 -0
- package/dist/pretool-command-3SXQSMAO.js +13 -0
- package/dist/{rerank-3P3C2UHN.js → rerank-IQAEWLQR.js} +6 -5
- package/dist/rerank-IQAEWLQR.js.map +1 -0
- package/dist/runtime-E7JQZ2BZ.js +46 -0
- package/dist/runtime-E7JQZ2BZ.js.map +1 -0
- package/dist/stdio-HOV4P3DQ.js +12 -0
- package/dist/stdio-HOV4P3DQ.js.map +1 -0
- package/dist/summaries-XV3JGGCC.js +20 -0
- package/dist/summaries-XV3JGGCC.js.map +1 -0
- package/dist/{zvec-MAPSJQSR.js → zvec-KP4KNB7Y.js} +10 -3
- package/dist/zvec-KP4KNB7Y.js.map +1 -0
- package/package.json +7 -10
- package/src/db/migrations/0006_fact_idempotency_key.sql +2 -0
- package/src/db/migrations/meta/0006_snapshot.json +1258 -0
- package/src/db/migrations/meta/_journal.json +7 -0
- package/dist/chunk-776EQXDV.js.map +0 -1
- package/dist/chunk-GDJH7XJC.js.map +0 -1
- package/dist/chunk-JPHJBCZB.js.map +0 -1
- package/dist/chunk-L5AYZC3F.js.map +0 -1
- package/dist/chunk-N34XHWBA.js.map +0 -1
- package/dist/chunk-PCE4STAY.js.map +0 -1
- package/dist/chunk-PQK3GKZH.js +0 -98
- package/dist/chunk-PQK3GKZH.js.map +0 -1
- package/dist/chunk-QDBDYCM2.js.map +0 -1
- package/dist/chunk-U4HAJLIB.js.map +0 -1
- package/dist/chunk-UN57FKQX.js.map +0 -1
- package/dist/chunk-VAKBJV26.js.map +0 -1
- package/dist/chunk-WHZSVY2L.js.map +0 -1
- package/dist/chunk-XBJQKCLU.js.map +0 -1
- package/dist/config-KFEHLV6W.js +0 -11
- package/dist/lean-command-C5YPFKHP.js +0 -15
- package/dist/local-OTOY56B4.js +0 -13
- package/dist/main-HFHLGID4.js.map +0 -1
- package/dist/memory-4RGVLPKG.js.map +0 -1
- package/dist/operations-LOBAQRLO.js +0 -24
- package/dist/pretool-command-MQQ2UNQM.js +0 -10
- package/dist/rerank-3P3C2UHN.js.map +0 -1
- package/dist/summaries-ZBV5IN7Y.js +0 -18
- /package/dist/{chunk-JFDRBPYF.js.map → chunk-6JCKMIQY.js.map} +0 -0
- /package/dist/{chunk-UFZD3JAA.js.map → chunk-ESZXCZIN.js.map} +0 -0
- /package/dist/{chunk-PYLH4MH5.js.map → chunk-FJOTP632.js.map} +0 -0
- /package/dist/{chunk-6MKEIDX5.js.map → chunk-SFMIMLXR.js.map} +0 -0
- /package/dist/{cloud-7WM3YLI4.js.map → cloud-LXZUR3U2.js.map} +0 -0
- /package/dist/{config-KFEHLV6W.js.map → config-GEZFLXK6.js.map} +0 -0
- /package/dist/{lean-command-C5YPFKHP.js.map → docker-autostart-KDME7TVC.js.map} +0 -0
- /package/dist/{local-OTOY56B4.js.map → lean-command-CWJAVQ5G.js.map} +0 -0
- /package/dist/{operations-LOBAQRLO.js.map → local-ST4WMRCG.js.map} +0 -0
- /package/dist/{pretool-command-MQQ2UNQM.js.map → operations-7BTAAUHF.js.map} +0 -0
- /package/dist/{summaries-ZBV5IN7Y.js.map → postgres-docker-QQZQ2ABK.js.map} +0 -0
- /package/dist/{zvec-MAPSJQSR.js.map → pretool-command-3SXQSMAO.js.map} +0 -0
|
@@ -1,72 +1,70 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-PCE4STAY.js";
|
|
2
|
+
runPreToolHookCommand
|
|
3
|
+
} from "./chunk-AQHPEJR6.js";
|
|
5
4
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
5
|
+
isDockerDaemonRunning,
|
|
6
|
+
tryStartDockerDesktop,
|
|
7
|
+
waitForDockerDaemon
|
|
8
|
+
} from "./chunk-5UH3BEQR.js";
|
|
9
|
+
import {
|
|
10
|
+
postgresDown,
|
|
11
|
+
postgresStatus,
|
|
12
|
+
postgresUp
|
|
13
|
+
} from "./chunk-CSRD5OQA.js";
|
|
10
14
|
import {
|
|
11
15
|
renderLeanBlock,
|
|
12
16
|
runLeanHookCommand
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import {
|
|
15
|
-
runPreToolHookCommand
|
|
16
|
-
} from "./chunk-WHZSVY2L.js";
|
|
17
|
+
} from "./chunk-LCSBL5TT.js";
|
|
17
18
|
import {
|
|
18
19
|
failSoft,
|
|
19
20
|
readHookInput,
|
|
20
21
|
writeStdout
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-FJOTP632.js";
|
|
23
|
+
import {
|
|
24
|
+
generateSuggestions,
|
|
25
|
+
migrateMemoryToFiles,
|
|
26
|
+
registerCodeBuddyTools,
|
|
27
|
+
startMcpServer,
|
|
28
|
+
watchRepository
|
|
29
|
+
} from "./chunk-EEUFU7KV.js";
|
|
30
|
+
import {
|
|
31
|
+
DEFAULT_ZVEC_MODEL,
|
|
32
|
+
buildZvecIndex,
|
|
33
|
+
zvecStatus
|
|
34
|
+
} from "./chunk-MSUAVR3R.js";
|
|
22
35
|
import {
|
|
23
36
|
PlanFileStore,
|
|
24
37
|
PlanLifecycle,
|
|
25
38
|
ReviewStore,
|
|
26
|
-
VERSION,
|
|
27
39
|
WorklogStore,
|
|
28
40
|
approveReviewItem,
|
|
29
41
|
assessRisk,
|
|
30
42
|
buildBeforeEditContext,
|
|
31
43
|
buildBootstrapContext,
|
|
32
|
-
generateSuggestions,
|
|
33
|
-
migrateMemoryToFiles,
|
|
34
44
|
openHookSemantics,
|
|
35
|
-
parseTraceLines,
|
|
36
|
-
readTraces,
|
|
37
|
-
registerCodeBuddyTools,
|
|
38
45
|
renderContextBlock,
|
|
39
46
|
resolveRiskPaths,
|
|
40
47
|
runCaptureHook,
|
|
41
48
|
runContextHook,
|
|
42
49
|
runResetHook,
|
|
43
50
|
runStageHook,
|
|
44
|
-
runSyncHook
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
runSyncHook
|
|
52
|
+
} from "./chunk-YJIA2MFL.js";
|
|
53
|
+
import {
|
|
54
|
+
parseTraceLines,
|
|
55
|
+
readTraces,
|
|
56
|
+
tracePath
|
|
57
|
+
} from "./chunk-TUR6YKEE.js";
|
|
58
|
+
import "./chunk-DFV2SK6C.js";
|
|
50
59
|
import {
|
|
51
60
|
SessionCapsuleLedger,
|
|
61
|
+
detectTestCommand,
|
|
52
62
|
estimateTokens
|
|
53
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-GKNYMNFM.js";
|
|
54
64
|
import {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
indexRepository,
|
|
58
|
-
loadFreshIndex,
|
|
59
|
-
loadGraphifyMap,
|
|
60
|
-
neighbours,
|
|
61
|
-
queryMap,
|
|
62
|
-
setupGraphify
|
|
63
|
-
} from "./chunk-L5AYZC3F.js";
|
|
64
|
-
import {
|
|
65
|
-
extractSymbolTable,
|
|
66
|
-
supportsSymbols
|
|
67
|
-
} from "./chunk-PQK3GKZH.js";
|
|
65
|
+
hookRoot
|
|
66
|
+
} from "./chunk-TGFTKWOR.js";
|
|
68
67
|
import {
|
|
69
|
-
MemoryFileStore,
|
|
70
68
|
bootstrapDatabase,
|
|
71
69
|
buildProviderFromConfig,
|
|
72
70
|
createDatabaseClient,
|
|
@@ -77,32 +75,56 @@ import {
|
|
|
77
75
|
pingDatabase,
|
|
78
76
|
runDoctor,
|
|
79
77
|
runMigrations
|
|
80
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-AK2UAE32.js";
|
|
81
79
|
import {
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
MemoryFileStore,
|
|
81
|
+
VERSION
|
|
82
|
+
} from "./chunk-JUAFCLRB.js";
|
|
84
83
|
import {
|
|
85
84
|
computeFactHash,
|
|
86
85
|
generateEntityId
|
|
87
|
-
} from "./chunk-
|
|
88
|
-
import "./chunk-
|
|
86
|
+
} from "./chunk-CAEPHLHC.js";
|
|
87
|
+
import "./chunk-6JCKMIQY.js";
|
|
89
88
|
import {
|
|
89
|
+
localRuntimeInstalled,
|
|
90
90
|
modelCacheDir
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-3QGW53GD.js";
|
|
92
|
+
import {
|
|
93
|
+
loadLlmSummaries,
|
|
94
|
+
summarizeRepository
|
|
95
|
+
} from "./chunk-BQM7FJ7D.js";
|
|
96
|
+
import {
|
|
97
|
+
chatJson,
|
|
98
|
+
coolingDown,
|
|
99
|
+
usageToday
|
|
100
|
+
} from "./chunk-ESZXCZIN.js";
|
|
101
|
+
import {
|
|
102
|
+
buildArchitectureMap,
|
|
103
|
+
generateGraphifyGraph,
|
|
104
|
+
indexRepository,
|
|
105
|
+
loadFreshIndex,
|
|
106
|
+
loadGraphifyMap,
|
|
107
|
+
neighbours,
|
|
108
|
+
queryMap,
|
|
109
|
+
setupGraphify,
|
|
110
|
+
syncFileVectors
|
|
111
|
+
} from "./chunk-5EDGAZQN.js";
|
|
112
|
+
import {
|
|
113
|
+
extractSymbolTable,
|
|
114
|
+
supportsSymbols
|
|
115
|
+
} from "./chunk-Y7D7PUBE.js";
|
|
116
|
+
import {
|
|
117
|
+
redactPersisted
|
|
118
|
+
} from "./chunk-AL6VBTNA.js";
|
|
92
119
|
import {
|
|
93
120
|
DEFAULT_CLOUD_EMBEDDING_MODELS,
|
|
94
121
|
DEFAULT_RERANK_MODELS,
|
|
95
122
|
LOCAL_EMBEDDING_MODEL,
|
|
96
123
|
getModelDefinition
|
|
97
|
-
} from "./chunk-
|
|
98
|
-
import {
|
|
99
|
-
DEFAULT_ZVEC_MODEL,
|
|
100
|
-
buildZvecIndex,
|
|
101
|
-
zvecStatus
|
|
102
|
-
} from "./chunk-QDBDYCM2.js";
|
|
124
|
+
} from "./chunk-HPOR6YXA.js";
|
|
103
125
|
import {
|
|
104
126
|
resolveLlmConfig
|
|
105
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-SFMIMLXR.js";
|
|
106
128
|
import {
|
|
107
129
|
PLAN_POLICIES,
|
|
108
130
|
configPath,
|
|
@@ -111,6 +133,7 @@ import {
|
|
|
111
133
|
initProjectScaffold,
|
|
112
134
|
loadPlanPolicy,
|
|
113
135
|
loadRuntimeConfig,
|
|
136
|
+
migrateLegacyNamespace,
|
|
114
137
|
readConfigFile,
|
|
115
138
|
redactSecrets,
|
|
116
139
|
resolveNamespaceFrom,
|
|
@@ -118,9 +141,11 @@ import {
|
|
|
118
141
|
setLlmEnabled,
|
|
119
142
|
setPlanPolicy,
|
|
120
143
|
setZvecEnabled,
|
|
121
|
-
writeAtomic,
|
|
122
144
|
writeConfigFile
|
|
123
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-KNR2P2UY.js";
|
|
146
|
+
import {
|
|
147
|
+
writeAtomic
|
|
148
|
+
} from "./chunk-CG5B3LYG.js";
|
|
124
149
|
import "./chunk-PZ5AY32C.js";
|
|
125
150
|
|
|
126
151
|
// src/cli/main.ts
|
|
@@ -226,9 +251,7 @@ import pc from "picocolors";
|
|
|
226
251
|
|
|
227
252
|
// src/change/engine.ts
|
|
228
253
|
import { spawn } from "child_process";
|
|
229
|
-
import {
|
|
230
|
-
import { access as access2, readFile } from "fs/promises";
|
|
231
|
-
import { extname, join as join2 } from "path";
|
|
254
|
+
import { extname } from "path";
|
|
232
255
|
var CODE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
233
256
|
var DEFAULT_TEST_TIMEOUT_MS = 12e4;
|
|
234
257
|
var MAX_TEST_OUTPUT_CHARS = 12e3;
|
|
@@ -277,7 +300,7 @@ async function buildChangeReport(input) {
|
|
|
277
300
|
}
|
|
278
301
|
async function verifyChange(input) {
|
|
279
302
|
const report = await buildChangeReport(input);
|
|
280
|
-
const detected = input.command ? { command: input.command, source: "explicit" } : await
|
|
303
|
+
const detected = input.command ? { command: input.command, source: "explicit" } : await detectedTestCommand(input.repositoryRoot ?? process.cwd());
|
|
281
304
|
if (!detected) {
|
|
282
305
|
return {
|
|
283
306
|
report,
|
|
@@ -288,7 +311,7 @@ async function verifyChange(input) {
|
|
|
288
311
|
exitCode: null,
|
|
289
312
|
signal: null,
|
|
290
313
|
durationMs: 0,
|
|
291
|
-
output: "No test command found. Pass --command
|
|
314
|
+
output: "No test command found. Pass --command, add a test script to package.json, or add pyproject.toml/pytest.ini/setup.cfg, go.mod or Cargo.toml."
|
|
292
315
|
}
|
|
293
316
|
};
|
|
294
317
|
}
|
|
@@ -302,44 +325,19 @@ async function verifyChange(input) {
|
|
|
302
325
|
)
|
|
303
326
|
};
|
|
304
327
|
}
|
|
305
|
-
async function
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
source: "package_script"
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
} catch (error) {
|
|
316
|
-
if (error.code !== "ENOENT") throw error;
|
|
317
|
-
}
|
|
318
|
-
for (const candidate of [
|
|
319
|
-
["pnpm-lock.yaml", "pnpm test"],
|
|
320
|
-
["yarn.lock", "yarn test"],
|
|
321
|
-
["bun.lockb", "bun test"],
|
|
322
|
-
["bun.lock", "bun test"],
|
|
323
|
-
["package-lock.json", "npm test"]
|
|
324
|
-
]) {
|
|
325
|
-
try {
|
|
326
|
-
await access2(join2(repositoryRoot, candidate[0]), constants2.F_OK);
|
|
327
|
-
return { command: candidate[1], source: "package_manager" };
|
|
328
|
-
} catch {
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
return null;
|
|
332
|
-
}
|
|
333
|
-
function packageManagerName(value) {
|
|
334
|
-
if (typeof value !== "string") return "npm";
|
|
335
|
-
const name = value.split(/[\s@]/, 1)[0] ?? "npm";
|
|
336
|
-
return ["npm", "pnpm", "yarn", "bun"].includes(name) ? name : "npm";
|
|
328
|
+
async function detectedTestCommand(repositoryRoot) {
|
|
329
|
+
const command = await detectTestCommand(repositoryRoot);
|
|
330
|
+
if (command === null) return null;
|
|
331
|
+
return {
|
|
332
|
+
command,
|
|
333
|
+
source: /^(npm|pnpm|yarn|bun) test$/.test(command) ? "package_script" : "project_marker"
|
|
334
|
+
};
|
|
337
335
|
}
|
|
338
336
|
function runTestCommand(command, source, repositoryRoot, timeoutMs) {
|
|
339
337
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
340
338
|
throw new Error("--timeout must be a positive number of milliseconds.");
|
|
341
339
|
}
|
|
342
|
-
return new Promise((
|
|
340
|
+
return new Promise((resolve13) => {
|
|
343
341
|
const startedAt = Date.now();
|
|
344
342
|
const child = spawn(command, {
|
|
345
343
|
cwd: repositoryRoot,
|
|
@@ -364,7 +362,7 @@ ${output.slice(-MAX_TEST_OUTPUT_CHARS)}`;
|
|
|
364
362
|
}, timeoutMs);
|
|
365
363
|
child.on("close", (exitCode, signal) => {
|
|
366
364
|
clearTimeout(timer);
|
|
367
|
-
|
|
365
|
+
resolve13({
|
|
368
366
|
status: timedOut ? "timed_out" : exitCode === 0 ? "passed" : "failed",
|
|
369
367
|
command,
|
|
370
368
|
source,
|
|
@@ -376,7 +374,7 @@ ${output.slice(-MAX_TEST_OUTPUT_CHARS)}`;
|
|
|
376
374
|
});
|
|
377
375
|
child.on("error", (error) => {
|
|
378
376
|
clearTimeout(timer);
|
|
379
|
-
|
|
377
|
+
resolve13({
|
|
380
378
|
status: "failed",
|
|
381
379
|
command,
|
|
382
380
|
source,
|
|
@@ -589,22 +587,22 @@ function testBadge(status) {
|
|
|
589
587
|
|
|
590
588
|
// src/cli/commands/claude-desktop.ts
|
|
591
589
|
import { existsSync } from "fs";
|
|
592
|
-
import { mkdir as mkdir2, readFile
|
|
593
|
-
import { dirname as dirname2, join as
|
|
590
|
+
import { mkdir as mkdir2, readFile } from "fs/promises";
|
|
591
|
+
import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
594
592
|
import { fileURLToPath } from "url";
|
|
595
593
|
function claudeDesktopConfigPath(home = process.env.HOME ?? "") {
|
|
596
594
|
if (process.platform === "darwin") {
|
|
597
|
-
return
|
|
595
|
+
return join2(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
598
596
|
}
|
|
599
597
|
if (process.platform === "win32") {
|
|
600
|
-
return
|
|
598
|
+
return join2(process.env.APPDATA ?? home, "Claude", "claude_desktop_config.json");
|
|
601
599
|
}
|
|
602
|
-
return
|
|
600
|
+
return join2(home, ".config", "Claude", "claude_desktop_config.json");
|
|
603
601
|
}
|
|
604
602
|
async function readClaudeConfig(path) {
|
|
605
603
|
if (!existsSync(path)) return {};
|
|
606
604
|
try {
|
|
607
|
-
return JSON.parse(await
|
|
605
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
608
606
|
} catch (error) {
|
|
609
607
|
throw new Error(
|
|
610
608
|
`Failed to parse Claude Desktop config at ${path}: ${error.message}`
|
|
@@ -641,7 +639,10 @@ function buildEntry(options) {
|
|
|
641
639
|
if (options.groqApiKey) env.GROQ_API_KEY = options.groqApiKey;
|
|
642
640
|
if (options.databaseUrl) env.DATABASE_URL = options.databaseUrl;
|
|
643
641
|
return {
|
|
644
|
-
|
|
642
|
+
// Absolute: Claude Desktop is a GUI app and does not inherit the shell's
|
|
643
|
+
// PATH (nvm, Homebrew), so a bare "node" may not resolve or may be another
|
|
644
|
+
// version. Re-run `codebuddy claude install` after switching Node.
|
|
645
|
+
command: process.execPath,
|
|
645
646
|
args: [resolveCliEntrypoint(), "serve"],
|
|
646
647
|
env
|
|
647
648
|
};
|
|
@@ -776,25 +777,25 @@ function sharedRulesReaders(client) {
|
|
|
776
777
|
// src/clients/cost.ts
|
|
777
778
|
import { mkdtemp, rm as rm3 } from "fs/promises";
|
|
778
779
|
import { tmpdir } from "os";
|
|
779
|
-
import { join as
|
|
780
|
+
import { join as join7, resolve as resolve7 } from "path";
|
|
780
781
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
781
782
|
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
782
783
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
783
784
|
|
|
784
785
|
// src/templates/install.ts
|
|
785
|
-
import { readFile as
|
|
786
|
-
import { join as
|
|
786
|
+
import { readFile as readFile6, rm as rm2 } from "fs/promises";
|
|
787
|
+
import { join as join6, resolve as resolve6 } from "path";
|
|
787
788
|
|
|
788
789
|
// src/hooks/hermes-plugin.ts
|
|
789
|
-
import { readFile as
|
|
790
|
-
import { dirname as dirname4, join as
|
|
790
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
791
|
+
import { dirname as dirname4, join as join3, resolve as resolve3 } from "path";
|
|
791
792
|
|
|
792
793
|
// src/hooks/managed-plugin.ts
|
|
793
|
-
import { mkdir as mkdir3, readFile as
|
|
794
|
+
import { mkdir as mkdir3, readFile as readFile2, rm, rmdir } from "fs/promises";
|
|
794
795
|
import { dirname as dirname3 } from "path";
|
|
795
796
|
async function read(path) {
|
|
796
797
|
try {
|
|
797
|
-
return await
|
|
798
|
+
return await readFile2(path, "utf8");
|
|
798
799
|
} catch (error) {
|
|
799
800
|
if (error.code === "ENOENT") return null;
|
|
800
801
|
throw error;
|
|
@@ -990,7 +991,7 @@ def register(ctx):
|
|
|
990
991
|
}
|
|
991
992
|
var HERMES_PLUGIN_SOURCE = renderHermesPlugin("full");
|
|
992
993
|
function hermesPluginDir(repositoryRoot) {
|
|
993
|
-
return
|
|
994
|
+
return join3(resolve3(repositoryRoot), ".hermes", "plugins", "codebuddy");
|
|
994
995
|
}
|
|
995
996
|
function plugin(repositoryRoot, variant = "full") {
|
|
996
997
|
const dir = hermesPluginDir(repositoryRoot);
|
|
@@ -998,10 +999,10 @@ function plugin(repositoryRoot, variant = "full") {
|
|
|
998
999
|
marker: HERMES_PLUGIN_MARKER,
|
|
999
1000
|
files: [
|
|
1000
1001
|
{
|
|
1001
|
-
path:
|
|
1002
|
+
path: join3(dir, "plugin.yaml"),
|
|
1002
1003
|
content: variant === "lean" ? HERMES_LEAN_MANIFEST : HERMES_PLUGIN_MANIFEST
|
|
1003
1004
|
},
|
|
1004
|
-
{ path:
|
|
1005
|
+
{ path: join3(dir, "__init__.py"), content: renderHermesPlugin(variant) }
|
|
1005
1006
|
],
|
|
1006
1007
|
dirs: [dir, dirname4(dir), dirname4(dirname4(dir))]
|
|
1007
1008
|
};
|
|
@@ -1014,13 +1015,13 @@ function setHermesPlugin(repositoryRoot, enabled, variant = "full") {
|
|
|
1014
1015
|
}
|
|
1015
1016
|
async function hermesPluginVariant(repositoryRoot) {
|
|
1016
1017
|
if (!await hermesPluginInstalled(repositoryRoot)) return null;
|
|
1017
|
-
const source = await
|
|
1018
|
+
const source = await readFile3(join3(hermesPluginDir(repositoryRoot), "__init__.py"), "utf8");
|
|
1018
1019
|
return source.startsWith(`${HERMES_PLUGIN_MARKER} v1 lean`) ? "lean" : "full";
|
|
1019
1020
|
}
|
|
1020
1021
|
|
|
1021
1022
|
// src/hooks/opencode-plugin.ts
|
|
1022
|
-
import { readFile as
|
|
1023
|
-
import { dirname as dirname5, join as
|
|
1023
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
1024
|
+
import { dirname as dirname5, join as join4, resolve as resolve4 } from "path";
|
|
1024
1025
|
var OPENCODE_PLUGIN_MARKER = "// codebuddy-managed: opencode-plugin";
|
|
1025
1026
|
var OPENCODE_RUNTIME = `const ID_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
1026
1027
|
let lastMs = 0;
|
|
@@ -1035,6 +1036,8 @@ function hook(command, payload) {
|
|
|
1035
1036
|
child = spawn("codebuddy", ["hooks", command], {
|
|
1036
1037
|
cwd: payload.cwd,
|
|
1037
1038
|
stdio: ["pipe", "pipe", "ignore"],
|
|
1039
|
+
// npm installs a codebuddy.cmd shim on Windows, which spawn only runs through a shell.
|
|
1040
|
+
shell: process.platform === "win32",
|
|
1038
1041
|
});
|
|
1039
1042
|
} catch {
|
|
1040
1043
|
done("");
|
|
@@ -1184,7 +1187,7 @@ export const CodeBuddyPlugin = async ({ directory }) => {
|
|
|
1184
1187
|
}
|
|
1185
1188
|
var OPENCODE_PLUGIN_SOURCE = renderOpencodePlugin("full");
|
|
1186
1189
|
function opencodePluginPath(repositoryRoot) {
|
|
1187
|
-
return
|
|
1190
|
+
return join4(resolve4(repositoryRoot), ".opencode", "plugins", "codebuddy.js");
|
|
1188
1191
|
}
|
|
1189
1192
|
function plugin2(repositoryRoot, variant = "full") {
|
|
1190
1193
|
const path = opencodePluginPath(repositoryRoot);
|
|
@@ -1202,17 +1205,17 @@ function setOpencodePlugin(repositoryRoot, enabled, variant = "full") {
|
|
|
1202
1205
|
}
|
|
1203
1206
|
async function opencodePluginVariant(repositoryRoot) {
|
|
1204
1207
|
if (!await opencodePluginInstalled(repositoryRoot)) return null;
|
|
1205
|
-
const source = await
|
|
1208
|
+
const source = await readFile4(opencodePluginPath(repositoryRoot), "utf8");
|
|
1206
1209
|
return source.startsWith(`${OPENCODE_PLUGIN_MARKER} v1 lean`) ? "lean" : "full";
|
|
1207
1210
|
}
|
|
1208
1211
|
|
|
1209
1212
|
// src/hooks/settings.ts
|
|
1210
|
-
import { mkdir as mkdir4, readFile as
|
|
1211
|
-
import { dirname as dirname6, join as
|
|
1213
|
+
import { mkdir as mkdir4, readFile as readFile5 } from "fs/promises";
|
|
1214
|
+
import { dirname as dirname6, join as join5, resolve as resolve5 } from "path";
|
|
1212
1215
|
var HOOK_COMMAND_PREFIX = "codebuddy hooks";
|
|
1213
1216
|
var TOOL_GUARD_DEF = {
|
|
1214
1217
|
event: "PreToolUse",
|
|
1215
|
-
matcher: "Read|Grep",
|
|
1218
|
+
matcher: "Read|Grep|Bash",
|
|
1216
1219
|
command: `${HOOK_COMMAND_PREFIX} pretool`
|
|
1217
1220
|
};
|
|
1218
1221
|
var HOOK_DEFS = [
|
|
@@ -1234,7 +1237,7 @@ var LEAN_HOOK_DEFS = [
|
|
|
1234
1237
|
TOOL_GUARD_DEF
|
|
1235
1238
|
];
|
|
1236
1239
|
function claudeSettingsPath(repositoryRoot = process.cwd()) {
|
|
1237
|
-
return
|
|
1240
|
+
return join5(resolve5(repositoryRoot), ".claude", "settings.json");
|
|
1238
1241
|
}
|
|
1239
1242
|
function upsertHooks(settings, variant = "full") {
|
|
1240
1243
|
const defs = variant === "lean" ? LEAN_HOOK_DEFS : HOOK_DEFS;
|
|
@@ -1313,7 +1316,7 @@ function hooksVariant(settings) {
|
|
|
1313
1316
|
}
|
|
1314
1317
|
async function readSettings(path) {
|
|
1315
1318
|
try {
|
|
1316
|
-
return JSON.parse(await
|
|
1319
|
+
return JSON.parse(await readFile5(path, "utf8"));
|
|
1317
1320
|
} catch (error) {
|
|
1318
1321
|
if (error.code === "ENOENT") return {};
|
|
1319
1322
|
throw error;
|
|
@@ -1417,12 +1420,16 @@ var START_HOOKS = [
|
|
|
1417
1420
|
"follow the agent-driven flow: `context_pack` first, `context_after_turn` last.",
|
|
1418
1421
|
"",
|
|
1419
1422
|
"1. Start from the injected block; do not call `context_bootstrap` for orientation",
|
|
1420
|
-
" it already covers.",
|
|
1421
|
-
"
|
|
1423
|
+
" it already covers. Its `task files` are CodeBuddy's best match; when it names",
|
|
1424
|
+
" none, call `context_pack` with the task before searching the repository yourself.",
|
|
1425
|
+
"2. Read ranges, not whole files: `Read` with offset/limit, or `sed -n 'A,Bp'`.",
|
|
1426
|
+
" Large files read whole (`Read` without a range, `cat`, `less`) are denied with an",
|
|
1427
|
+
" outline of their symbols and line ranges; read the range you need from it.",
|
|
1428
|
+
"3. Call `context_pack` (or `context_before_edit` with exact paths) when the",
|
|
1422
1429
|
" task needs symbols, neighbours, or file-level evidence the block lacks. Pass the",
|
|
1423
1430
|
" block's `session` value as `sessionId` and the previous `delivery.deliveryId`",
|
|
1424
1431
|
" as `ack` so unchanged sections are not resent.",
|
|
1425
|
-
"
|
|
1432
|
+
"4. Prior work from earlier chats arrives as handoffs with freshness; re-check",
|
|
1426
1433
|
" those files before relying on it.",
|
|
1427
1434
|
""
|
|
1428
1435
|
];
|
|
@@ -1525,7 +1532,7 @@ ${END_MARKER}
|
|
|
1525
1532
|
}
|
|
1526
1533
|
async function installWorkflowRules(options) {
|
|
1527
1534
|
const projectRoot = resolve6(options.projectRoot ?? process.cwd());
|
|
1528
|
-
const path = options.targetPath ??
|
|
1535
|
+
const path = options.targetPath ?? join6(projectRoot, defaultRulesFile(options.client));
|
|
1529
1536
|
const existing = await readIfPresent(path);
|
|
1530
1537
|
const mode = options.mode ?? await defaultRulesMode(options.client, projectRoot);
|
|
1531
1538
|
if (options.onlyIfManaged && (existing === null || !hasManagedBlock(existing))) {
|
|
@@ -1580,7 +1587,7 @@ function removeBlock(existing) {
|
|
|
1580
1587
|
}
|
|
1581
1588
|
async function readIfPresent(path) {
|
|
1582
1589
|
try {
|
|
1583
|
-
return await
|
|
1590
|
+
return await readFile6(path, "utf8");
|
|
1584
1591
|
} catch (error) {
|
|
1585
1592
|
if (error.code === "ENOENT") return null;
|
|
1586
1593
|
throw error;
|
|
@@ -1617,7 +1624,7 @@ async function hookBlockTokens(root, namespace) {
|
|
|
1617
1624
|
namespace,
|
|
1618
1625
|
useGit: true
|
|
1619
1626
|
}).catch(() => null);
|
|
1620
|
-
const scratch = await mkdtemp(
|
|
1627
|
+
const scratch = await mkdtemp(join7(tmpdir(), "codebuddy-cost-"));
|
|
1621
1628
|
try {
|
|
1622
1629
|
const ledger = new SessionCapsuleLedger(scratch);
|
|
1623
1630
|
const render = () => renderContextBlock(bootstrap, beforeEdit, ledger, "cost", true);
|
|
@@ -1670,14 +1677,14 @@ async function measureClientCosts(projectRoot = process.cwd(), namespace) {
|
|
|
1670
1677
|
}
|
|
1671
1678
|
|
|
1672
1679
|
// src/clients/install.ts
|
|
1673
|
-
import { access as
|
|
1674
|
-
import { join as
|
|
1680
|
+
import { access as access3 } from "fs/promises";
|
|
1681
|
+
import { join as join11, resolve as resolve9 } from "path";
|
|
1675
1682
|
|
|
1676
1683
|
// src/integrations/project-mcp.ts
|
|
1677
|
-
import { access as
|
|
1678
|
-
import { dirname as dirname7, join as
|
|
1684
|
+
import { access as access2, mkdir as mkdir5, readFile as readFile7, rm as rm4 } from "fs/promises";
|
|
1685
|
+
import { dirname as dirname7, join as join8, resolve as resolve8 } from "path";
|
|
1679
1686
|
async function writeProjectMcpConfig(options) {
|
|
1680
|
-
const path =
|
|
1687
|
+
const path = join8(options.repositoryRoot, ".mcp.json");
|
|
1681
1688
|
const current = await readProjectMcpConfig(path);
|
|
1682
1689
|
current.mcpServers ??= {};
|
|
1683
1690
|
current.mcpServers[`codebuddy-${options.namespace}`] = codebuddyMcpServer(
|
|
@@ -1714,12 +1721,12 @@ function codebuddyMcpServer(repositoryRoot, namespace) {
|
|
|
1714
1721
|
};
|
|
1715
1722
|
}
|
|
1716
1723
|
async function projectMcpPath(root, file, format) {
|
|
1717
|
-
const path =
|
|
1724
|
+
const path = join8(root, file);
|
|
1718
1725
|
if (format !== "opencode" || await exists(path)) return path;
|
|
1719
1726
|
return await exists(`${path}c`) ? `${path}c` : path;
|
|
1720
1727
|
}
|
|
1721
1728
|
async function exists(path) {
|
|
1722
|
-
return
|
|
1729
|
+
return access2(path).then(
|
|
1723
1730
|
() => true,
|
|
1724
1731
|
() => false
|
|
1725
1732
|
);
|
|
@@ -1780,7 +1787,7 @@ function parseJsonc(raw) {
|
|
|
1780
1787
|
}
|
|
1781
1788
|
async function readConfig(path) {
|
|
1782
1789
|
try {
|
|
1783
|
-
const { value, comments } = parseJsonc(await
|
|
1790
|
+
const { value, comments } = parseJsonc(await readFile7(path, "utf8"));
|
|
1784
1791
|
const config = value && typeof value === "object" ? value : {};
|
|
1785
1792
|
return { config, comments };
|
|
1786
1793
|
} catch (error) {
|
|
@@ -1794,15 +1801,15 @@ async function readProjectMcpConfig(path) {
|
|
|
1794
1801
|
|
|
1795
1802
|
// src/cli/commands/codex.ts
|
|
1796
1803
|
import { existsSync as existsSync2 } from "fs";
|
|
1797
|
-
import { mkdir as mkdir6, readFile as
|
|
1804
|
+
import { mkdir as mkdir6, readFile as readFile8 } from "fs/promises";
|
|
1798
1805
|
import { homedir } from "os";
|
|
1799
|
-
import { dirname as dirname8, join as
|
|
1806
|
+
import { dirname as dirname8, join as join9 } from "path";
|
|
1800
1807
|
function codexConfigPath(home = homedir()) {
|
|
1801
|
-
return
|
|
1808
|
+
return join9(home, ".codex", "config.toml");
|
|
1802
1809
|
}
|
|
1803
1810
|
async function readCodexConfig(path) {
|
|
1804
1811
|
if (!existsSync2(path)) return "";
|
|
1805
|
-
return
|
|
1812
|
+
return readFile8(path, "utf8");
|
|
1806
1813
|
}
|
|
1807
1814
|
async function writeCodexConfig(path, content) {
|
|
1808
1815
|
await mkdir6(dirname8(path), { recursive: true });
|
|
@@ -1908,17 +1915,17 @@ function escapeRegExp(value) {
|
|
|
1908
1915
|
}
|
|
1909
1916
|
|
|
1910
1917
|
// src/integrations/hermes-config.ts
|
|
1911
|
-
import { mkdir as mkdir7, readFile as
|
|
1918
|
+
import { mkdir as mkdir7, readFile as readFile9 } from "fs/promises";
|
|
1912
1919
|
import { homedir as homedir2 } from "os";
|
|
1913
|
-
import { dirname as dirname9, join as
|
|
1920
|
+
import { dirname as dirname9, join as join10 } from "path";
|
|
1914
1921
|
import { isDeepStrictEqual } from "util";
|
|
1915
1922
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
1916
1923
|
function hermesConfigPath(home = homedir2()) {
|
|
1917
|
-
return
|
|
1924
|
+
return join10(process.env.HERMES_HOME ?? join10(home, ".hermes"), "config.yaml");
|
|
1918
1925
|
}
|
|
1919
1926
|
async function readRaw(path) {
|
|
1920
1927
|
try {
|
|
1921
|
-
return await
|
|
1928
|
+
return await readFile9(path, "utf8");
|
|
1922
1929
|
} catch (error) {
|
|
1923
1930
|
if (error.code === "ENOENT") return "";
|
|
1924
1931
|
throw error;
|
|
@@ -2040,8 +2047,8 @@ async function installClient(options) {
|
|
|
2040
2047
|
return apply(options, options.mode, options.mode !== "lean");
|
|
2041
2048
|
}
|
|
2042
2049
|
async function ensureIndex(root) {
|
|
2043
|
-
const target =
|
|
2044
|
-
const existed = await
|
|
2050
|
+
const target = join11(root, ".codebuddy", "cache", "index.json");
|
|
2051
|
+
const existed = await access3(target).then(
|
|
2045
2052
|
() => true,
|
|
2046
2053
|
() => false
|
|
2047
2054
|
);
|
|
@@ -2061,7 +2068,7 @@ async function apply(options, mode, keepMcp) {
|
|
|
2061
2068
|
const shared = sharedRulesReaders(options.client);
|
|
2062
2069
|
const liveSiblings = mode === "mcp-only" || mode === "lean" ? await installedWithMcp(root, shared, namespace) : [];
|
|
2063
2070
|
if (liveSiblings.length > 0) {
|
|
2064
|
-
const path =
|
|
2071
|
+
const path = join11(root, adapter.rulesFile);
|
|
2065
2072
|
steps.push({ surface: "rules", target: path, action: "kept" });
|
|
2066
2073
|
notes.push(
|
|
2067
2074
|
`Kept the CodeBuddy block in ${adapter.rulesFile}: still used by ${liveSiblings.map((id) => CLIENT_ADAPTERS[id].name).join(", ")}.`
|
|
@@ -2141,7 +2148,7 @@ async function setHooks(root, enabled, client = "claude", variant = "full") {
|
|
|
2141
2148
|
async function detectClient(client, projectRoot = process.cwd(), namespace) {
|
|
2142
2149
|
const root = resolve9(projectRoot);
|
|
2143
2150
|
const adapter = CLIENT_ADAPTERS[client];
|
|
2144
|
-
const rulesMode = await readManagedMode(
|
|
2151
|
+
const rulesMode = await readManagedMode(join11(root, adapter.rulesFile));
|
|
2145
2152
|
const hooks = await clientHooksInstalled(root, client);
|
|
2146
2153
|
const name = `codebuddy-${namespace ?? await resolveNamespaceFrom(root)}`;
|
|
2147
2154
|
const mcp = "file" in adapter.mcp ? await hasMcpServer(
|
|
@@ -2167,8 +2174,8 @@ async function detectClient(client, projectRoot = process.cwd(), namespace) {
|
|
|
2167
2174
|
|
|
2168
2175
|
// src/clients/verify.ts
|
|
2169
2176
|
import { execFile } from "child_process";
|
|
2170
|
-
import { readFile as
|
|
2171
|
-
import { join as
|
|
2177
|
+
import { readFile as readFile10, realpath } from "fs/promises";
|
|
2178
|
+
import { join as join12, resolve as resolve10 } from "path";
|
|
2172
2179
|
import { pathToFileURL } from "url";
|
|
2173
2180
|
var runHost = (bin, args, cwd) => new Promise((done) => {
|
|
2174
2181
|
execFile(
|
|
@@ -2203,7 +2210,7 @@ var CONFORMANCE = {
|
|
|
2203
2210
|
if (!config) return [fail("config", "opencode debug config returned no JSON")];
|
|
2204
2211
|
const installed = await clientHooksInstalled(root, "opencode");
|
|
2205
2212
|
const href = pathToFileURL(
|
|
2206
|
-
|
|
2213
|
+
join12(await realpath(root).catch(() => root), ".opencode", "plugins", "codebuddy.js")
|
|
2207
2214
|
).href;
|
|
2208
2215
|
const loaded = config.plugin?.includes(href) === true;
|
|
2209
2216
|
return [
|
|
@@ -2230,7 +2237,7 @@ var CONFORMANCE = {
|
|
|
2230
2237
|
return checks;
|
|
2231
2238
|
}
|
|
2232
2239
|
const projectPlugins = /^(1|true|yes|on)$/i.test(env.HERMES_ENABLE_PROJECT_PLUGINS ?? "") || /^\s*HERMES_ENABLE_PROJECT_PLUGINS\s*=\s*["']?(1|true|yes|on)/im.test(
|
|
2233
|
-
await
|
|
2240
|
+
await readFile10(join12(hermesConfigPath(), "..", ".env"), "utf8").catch(() => "")
|
|
2234
2241
|
);
|
|
2235
2242
|
const plugins = (await readHermesConfig(hermesConfigPath()))?.plugins;
|
|
2236
2243
|
const enabled = Array.isArray(plugins?.enabled) && plugins.enabled.includes("codebuddy");
|
|
@@ -2646,13 +2653,16 @@ th.n { text-align: right; }
|
|
|
2646
2653
|
.chip { display: inline-block; font: 600 10px var(--mono); text-transform: uppercase; letter-spacing: .06em; padding: 2px 6px; border-radius: 4px; }
|
|
2647
2654
|
.chip.recall { background: var(--recall-soft); color: var(--recall); }
|
|
2648
2655
|
.chip.tool { background: var(--tool-soft); color: var(--tool); }
|
|
2649
|
-
.chip.capture, .chip.sync, .chip.kw { background: var(--line); color: var(--capture); }
|
|
2656
|
+
.chip.capture, .chip.sync, .chip.guard, .chip.kw { background: var(--line); color: var(--capture); }
|
|
2650
2657
|
.chip.err { background: var(--bad-soft); color: var(--bad); }
|
|
2651
2658
|
.feed { display: grid; gap: 10px; max-height: 520px; overflow: auto; }
|
|
2652
2659
|
.prompt { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
|
|
2653
2660
|
.prompt .q { font-weight: 500; overflow-wrap: anywhere; }
|
|
2654
2661
|
.prompt .meta { font: 12px var(--mono); color: var(--muted); margin-top: 4px; display: flex; flex-wrap: wrap; gap: 4px 12px; overflow-wrap: anywhere; }
|
|
2655
2662
|
.prompt ul { margin: 6px 0 0; padding-left: 18px; font-size: 13px; }
|
|
2663
|
+
.prompt details { margin-top: 6px; font-size: 12px; }
|
|
2664
|
+
.prompt summary { cursor: pointer; color: var(--muted); }
|
|
2665
|
+
.prompt pre { margin: 6px 0 0; padding: 8px 10px; background: var(--bg); border: 1px solid var(--line); border-radius: 6px; font: 12px/1.45 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 260px; overflow: auto; }
|
|
2656
2666
|
.prompt .none { font-size: 13px; color: var(--muted); margin-top: 6px; }
|
|
2657
2667
|
.mono { font-family: var(--mono); }
|
|
2658
2668
|
.muted { color: var(--muted); }
|
|
@@ -2731,7 +2741,10 @@ th.n { text-align: right; }
|
|
|
2731
2741
|
function kpis(list) {
|
|
2732
2742
|
var recalls = list.filter(function (e) { return e.kind === "recall"; });
|
|
2733
2743
|
var tools = list.filter(function (e) { return e.kind === "tool"; });
|
|
2734
|
-
var
|
|
2744
|
+
var injected = recalls.reduce(function (s, e) { return s + (e.tokensOut || 0); }, 0);
|
|
2745
|
+
var returned = tools.reduce(function (s, e) { return s + (e.tokensOut || 0); }, 0);
|
|
2746
|
+
var guards = list.filter(function (e) { return e.kind === "guard"; });
|
|
2747
|
+
var avoided = guards.reduce(function (s, e) { return s + ((e.detail && e.detail.avoided) || 0); }, 0);
|
|
2735
2748
|
var withFacts = recalls.filter(function (e) { return e.detail && e.detail.facts && e.detail.facts.length; });
|
|
2736
2749
|
var factCount = withFacts.reduce(function (s, e) { return s + e.detail.facts.length; }, 0);
|
|
2737
2750
|
var dense = recalls.reduce(function (s, e) { return s + ((e.detail && e.detail.dense) || 0); }, 0);
|
|
@@ -2742,7 +2755,8 @@ th.n { text-align: right; }
|
|
|
2742
2755
|
var tiles = [
|
|
2743
2756
|
["Prompts recalled", num(recalls.length), recalls.length ? Math.round(100 * withFacts.length / recalls.length) + "% got facts" : "no prompts yet"],
|
|
2744
2757
|
["Facts injected", num(factCount), factCount ? Math.round(100 * dense / factCount) + "% matched by meaning" : "-"],
|
|
2745
|
-
["Tokens
|
|
2758
|
+
["Tokens added to context", compact(injected + returned), compact(injected) + " by hooks, " + compact(returned) + " by MCP tools"],
|
|
2759
|
+
["Tokens kept out (measured)", compact(avoided), guards.length ? guards.length + " large read" + (guards.length === 1 ? "" : "s") + " replaced by an outline" : "no large reads blocked"],
|
|
2746
2760
|
["MCP tool calls", num(tools.length), tools.length ? new Set(tools.map(function (e) { return e.name; })).size + " distinct tools" : "-"],
|
|
2747
2761
|
["Recall latency", lat.length ? ms(pct(lat, 0.5)) : "-", lat.length ? "p95 " + ms(pct(lat, 0.95)) : "-"],
|
|
2748
2762
|
["Memories saved", num(saved), captures.length + " capture" + (captures.length === 1 ? "" : "s")],
|
|
@@ -2812,6 +2826,7 @@ th.n { text-align: right; }
|
|
|
2812
2826
|
(e.ok ? "" : '<span class="chip err">' + esc(d.dropped || "dropped") + "</span>") + "</div>" +
|
|
2813
2827
|
(facts.length ? "<ul>" + facts.map(function (f) { return "<li>" + esc(f) + "</li>"; }).join("") + "</ul>" : '<div class="none">No new facts: nothing matched, or already sent this session.</div>') +
|
|
2814
2828
|
(d.files && d.files.length ? '<div class="meta">files: ' + d.files.map(esc).join(", ") + "</div>" : "") +
|
|
2829
|
+
(d.block ? '<details><summary>What the agent received</summary><pre>' + esc(d.block) + "</pre></details>" : "") +
|
|
2815
2830
|
"</div>";
|
|
2816
2831
|
}).join("");
|
|
2817
2832
|
}
|
|
@@ -2836,6 +2851,7 @@ th.n { text-align: right; }
|
|
|
2836
2851
|
var d = e.detail || {};
|
|
2837
2852
|
if (e.kind === "recall") return (d.facts ? d.facts.length : 0) + " fact(s), " + (d.files ? d.files.length : 0) + " file(s)";
|
|
2838
2853
|
if (e.kind === "capture") return (d.saved || 0) + " saved, " + (d.queued || 0) + " queued, " + (d.changedFiles || 0) + " changed file(s)";
|
|
2854
|
+
if (e.kind === "guard") return "denied " + (d.file || "a large read") + ", \u2248" + num(d.avoided || 0) + " tokens kept out";
|
|
2839
2855
|
if (e.kind === "sync") return (d.imported || 0) + " new, " + (d.updated || 0) + " updated" + (d.reembedding ? ", " + d.reembedding + " re-embedding" : "");
|
|
2840
2856
|
return e.session ? "session " + e.session.slice(0, 12) : "";
|
|
2841
2857
|
}
|
|
@@ -2939,7 +2955,13 @@ data: ${data}
|
|
|
2939
2955
|
`);
|
|
2940
2956
|
};
|
|
2941
2957
|
watchFile(path, { interval: options.pollMs ?? 1e3 }, () => void onChange());
|
|
2958
|
+
let boundPort = 0;
|
|
2942
2959
|
const server = createServer(async (request, response) => {
|
|
2960
|
+
const host = request.headers.host ?? "";
|
|
2961
|
+
if (host !== `127.0.0.1:${boundPort}` && host !== `localhost:${boundPort}`) {
|
|
2962
|
+
response.writeHead(403, { "content-type": "text/plain" }).end("Forbidden host");
|
|
2963
|
+
return;
|
|
2964
|
+
}
|
|
2943
2965
|
const url = new URL(request.url ?? "/", "http://localhost");
|
|
2944
2966
|
if (request.method !== "GET") {
|
|
2945
2967
|
response.writeHead(405).end();
|
|
@@ -2979,18 +3001,19 @@ data: ${data}
|
|
|
2979
3001
|
response.writeHead(404, { "content-type": "text/plain" }).end("Not found");
|
|
2980
3002
|
});
|
|
2981
3003
|
const port = await listen(server, options.port ?? 4777);
|
|
3004
|
+
boundPort = port;
|
|
2982
3005
|
const heartbeat = setInterval(() => {
|
|
2983
3006
|
for (const client of clients) client.write(": ping\n\n");
|
|
2984
3007
|
}, 25e3);
|
|
2985
3008
|
heartbeat.unref();
|
|
2986
3009
|
return {
|
|
2987
3010
|
url: `http://127.0.0.1:${port}/`,
|
|
2988
|
-
close: () => new Promise((
|
|
3011
|
+
close: () => new Promise((resolve13) => {
|
|
2989
3012
|
clearInterval(heartbeat);
|
|
2990
3013
|
unwatchFile(path);
|
|
2991
3014
|
for (const client of clients) client.end();
|
|
2992
3015
|
server.closeAllConnections();
|
|
2993
|
-
server.close(() =>
|
|
3016
|
+
server.close(() => resolve13());
|
|
2994
3017
|
})
|
|
2995
3018
|
};
|
|
2996
3019
|
}
|
|
@@ -2998,11 +3021,11 @@ async function listen(server, port) {
|
|
|
2998
3021
|
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
2999
3022
|
const candidate = port === 0 ? 0 : port + attempt;
|
|
3000
3023
|
try {
|
|
3001
|
-
await new Promise((
|
|
3024
|
+
await new Promise((resolve13, reject) => {
|
|
3002
3025
|
server.once("error", reject);
|
|
3003
3026
|
server.listen(candidate, "127.0.0.1", () => {
|
|
3004
3027
|
server.off("error", reject);
|
|
3005
|
-
|
|
3028
|
+
resolve13();
|
|
3006
3029
|
});
|
|
3007
3030
|
});
|
|
3008
3031
|
return server.address().port;
|
|
@@ -3040,8 +3063,8 @@ function registerDashboardCommand(program, runSafely2) {
|
|
|
3040
3063
|
);
|
|
3041
3064
|
console.log(pc4.dim(" Ctrl+C to stop."));
|
|
3042
3065
|
if (opts.open) openBrowser(dashboard.url);
|
|
3043
|
-
await new Promise((
|
|
3044
|
-
const stop = () => void dashboard.close().then(
|
|
3066
|
+
await new Promise((resolve13) => {
|
|
3067
|
+
const stop = () => void dashboard.close().then(resolve13);
|
|
3045
3068
|
process.once("SIGINT", stop);
|
|
3046
3069
|
process.once("SIGTERM", stop);
|
|
3047
3070
|
});
|
|
@@ -3053,13 +3076,13 @@ function registerDashboardCommand(program, runSafely2) {
|
|
|
3053
3076
|
import pc5 from "picocolors";
|
|
3054
3077
|
|
|
3055
3078
|
// src/eval/runner.ts
|
|
3056
|
-
import { readFile as
|
|
3057
|
-
import { dirname as dirname10, isAbsolute, join as
|
|
3079
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
3080
|
+
import { dirname as dirname10, isAbsolute, join as join13, resolve as resolve11 } from "path";
|
|
3058
3081
|
async function runEvaluation(input = {}) {
|
|
3059
3082
|
const datasetPath = resolve11(
|
|
3060
|
-
input.datasetPath ??
|
|
3083
|
+
input.datasetPath ?? join13(process.cwd(), "evals", "change-readiness.json")
|
|
3061
3084
|
);
|
|
3062
|
-
const dataset = JSON.parse(await
|
|
3085
|
+
const dataset = JSON.parse(await readFile11(datasetPath, "utf8"));
|
|
3063
3086
|
if (dataset.version !== 1 || !Array.isArray(dataset.cases)) {
|
|
3064
3087
|
throw new Error(`Unsupported evaluation dataset: ${datasetPath}`);
|
|
3065
3088
|
}
|
|
@@ -3147,7 +3170,7 @@ function registerGitHubCommands(program, runSafely2) {
|
|
|
3147
3170
|
}
|
|
3148
3171
|
|
|
3149
3172
|
// src/cli/commands/hooks.ts
|
|
3150
|
-
import { spawn as spawn3 } from "child_process";
|
|
3173
|
+
import { execFile as execFile2, spawn as spawn3 } from "child_process";
|
|
3151
3174
|
import { relative as relative2 } from "path";
|
|
3152
3175
|
import pc7 from "picocolors";
|
|
3153
3176
|
function registerHooksCommands(program, runSafely2) {
|
|
@@ -3168,8 +3191,9 @@ function registerHooksCommands(program, runSafely2) {
|
|
|
3168
3191
|
console.log(
|
|
3169
3192
|
`${changed ? pc7.green("installed") : pc7.dim("unchanged")} CodeBuddy hooks in ${where}`
|
|
3170
3193
|
);
|
|
3171
|
-
await reconcileRules(client, "hooks");
|
|
3172
|
-
|
|
3194
|
+
await reconcileRules(client, "hooks", { create: true });
|
|
3195
|
+
warnIfHookCommandStale();
|
|
3196
|
+
syncInBackground(process.cwd(), true);
|
|
3173
3197
|
console.log(
|
|
3174
3198
|
pc7.dim(
|
|
3175
3199
|
` prompt\u2192recall \xB7 edit\u2192stage \xB7 turn end\u2192capture \xB7 compaction\u2192reset. Restart ${CLIENT_ADAPTERS[client].name} to activate.`
|
|
@@ -3227,18 +3251,18 @@ function registerHooksCommands(program, runSafely2) {
|
|
|
3227
3251
|
`codebuddy: captured from ${changedFiles.length} changed file(s) \u2014 ${result.saved.length} saved, ${result.queuedForReview.length} queued
|
|
3228
3252
|
`
|
|
3229
3253
|
);
|
|
3230
|
-
if (result.saved.length > 0) syncInBackground(input.cwd
|
|
3254
|
+
if (result.saved.length > 0) syncInBackground(hookRoot(input.cwd));
|
|
3231
3255
|
}
|
|
3232
3256
|
});
|
|
3233
3257
|
});
|
|
3234
3258
|
hooks.command("sync").description(
|
|
3235
3259
|
"[hook] Reindex Markdown memory into PostgreSQL and embed it locally (runs detached after capture)."
|
|
3236
|
-
).action(async () => {
|
|
3260
|
+
).option("--respace", "Also re-embed vectors made by another embedding model.").action(async (opts) => {
|
|
3237
3261
|
await failSoft(async () => {
|
|
3238
|
-
const result = await runSyncHook(process.cwd());
|
|
3262
|
+
const result = await runSyncHook(process.cwd(), opts.respace ? { respace: true } : {});
|
|
3239
3263
|
process.stderr.write(
|
|
3240
3264
|
result ? `codebuddy: synced ${result.reindex.facts.imported} new / ${result.reindex.facts.updated} updated fact(s)${result.reindex.reembedding ? `, ${result.reindex.reembedding} re-embedding` : ""}${result.drained ? "" : " (embeddings still pending)"}
|
|
3241
|
-
` : "codebuddy: no PostgreSQL configured
|
|
3265
|
+
` : "codebuddy: nothing to sync (no PostgreSQL configured, or another sync is running)\n"
|
|
3242
3266
|
);
|
|
3243
3267
|
});
|
|
3244
3268
|
});
|
|
@@ -3249,7 +3273,7 @@ function registerHooksCommands(program, runSafely2) {
|
|
|
3249
3273
|
});
|
|
3250
3274
|
hooks.command("reset").description("[hook] Forget what context was sent this session (after compaction or /clear).").action(async () => {
|
|
3251
3275
|
await failSoft(async () => {
|
|
3252
|
-
await runResetHook(await readHookInput());
|
|
3276
|
+
await runResetHook(await readHookInput(), writeStdout);
|
|
3253
3277
|
});
|
|
3254
3278
|
});
|
|
3255
3279
|
}
|
|
@@ -3263,24 +3287,55 @@ function assertHookClient(value) {
|
|
|
3263
3287
|
}
|
|
3264
3288
|
return client;
|
|
3265
3289
|
}
|
|
3266
|
-
async function reconcileRules(client, mode) {
|
|
3267
|
-
const result = await installWorkflowRules({
|
|
3290
|
+
async function reconcileRules(client, mode, options = {}) {
|
|
3291
|
+
const result = await installWorkflowRules({
|
|
3292
|
+
client,
|
|
3293
|
+
mode,
|
|
3294
|
+
...options.create ? {} : { onlyIfManaged: true }
|
|
3295
|
+
});
|
|
3268
3296
|
if (result.action !== "unchanged") {
|
|
3269
3297
|
const where = relative2(process.cwd(), result.path) || result.path;
|
|
3270
3298
|
console.log(
|
|
3271
|
-
`${pc7.cyan("updated")} ${where} workflow
|
|
3299
|
+
`${pc7.cyan(result.action === "created" ? "added" : "updated")} ${where} workflow (${mode === "hooks" ? "hook" : "agent"}-driven mode)`
|
|
3272
3300
|
);
|
|
3273
3301
|
}
|
|
3274
3302
|
}
|
|
3275
|
-
function
|
|
3303
|
+
function warnIfHookCommandStale() {
|
|
3304
|
+
execFile2(
|
|
3305
|
+
"codebuddy",
|
|
3306
|
+
["--version"],
|
|
3307
|
+
{ timeout: 1e4, shell: process.platform === "win32" },
|
|
3308
|
+
(error, stdout) => {
|
|
3309
|
+
const found = stdout.trim();
|
|
3310
|
+
if (error || !found) {
|
|
3311
|
+
console.log(
|
|
3312
|
+
pc7.yellow(
|
|
3313
|
+
" ! `codebuddy` is not on PATH, so the hooks cannot run. Install it globally: npm i -g @orquentra/codebuddy"
|
|
3314
|
+
)
|
|
3315
|
+
);
|
|
3316
|
+
} else if (found !== VERSION) {
|
|
3317
|
+
console.log(
|
|
3318
|
+
pc7.yellow(
|
|
3319
|
+
` ! The hooks will run codebuddy ${found} from PATH, not ${VERSION}. Update it: npm i -g @orquentra/codebuddy@${VERSION}`
|
|
3320
|
+
)
|
|
3321
|
+
);
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
);
|
|
3325
|
+
}
|
|
3326
|
+
function syncInBackground(cwd, respace = false) {
|
|
3276
3327
|
const entry = process.argv[1];
|
|
3277
3328
|
if (!entry) return;
|
|
3278
3329
|
try {
|
|
3279
|
-
spawn3(
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3330
|
+
spawn3(
|
|
3331
|
+
process.execPath,
|
|
3332
|
+
[...process.execArgv, entry, "hooks", "sync", ...respace ? ["--respace"] : []],
|
|
3333
|
+
{
|
|
3334
|
+
cwd,
|
|
3335
|
+
detached: true,
|
|
3336
|
+
stdio: "ignore"
|
|
3337
|
+
}
|
|
3338
|
+
).unref();
|
|
3284
3339
|
} catch {
|
|
3285
3340
|
}
|
|
3286
3341
|
}
|
|
@@ -3401,15 +3456,27 @@ function registerLlmCommands(program, runSafely2) {
|
|
|
3401
3456
|
}
|
|
3402
3457
|
|
|
3403
3458
|
// src/cli/commands/indexing.ts
|
|
3459
|
+
var VECTOR_BUDGET_MS = 10 * 6e4;
|
|
3404
3460
|
function registerIndexCommands(program, runSafely2) {
|
|
3405
|
-
program.command("index").option("--full", "Re-summarize every file, ignoring existing content hashes.").option("--json", "Print machine-readable JSON.").description("Index the repository: content hashes and lightweight file summaries.").action(async (opts) => {
|
|
3461
|
+
program.command("index").option("--full", "Re-summarize every file, ignoring existing content hashes.").option("--json", "Print machine-readable JSON.").option("--no-vectors", "Skip embedding source files for task \u2192 file ordering.").description("Index the repository: content hashes and lightweight file summaries.").action(async (opts) => {
|
|
3406
3462
|
await runSafely2(async () => {
|
|
3407
3463
|
const result = await indexRepository({ ...opts.full ? { full: true } : {} });
|
|
3464
|
+
const local = opts.vectors && (await loadRuntimeConfig(process.cwd(), { requireDatabase: false }).catch(() => null))?.provider.type === "local";
|
|
3465
|
+
const vectors = local ? await syncFileVectors(process.cwd(), VECTOR_BUDGET_MS) : null;
|
|
3408
3466
|
if (opts.json) {
|
|
3409
|
-
console.log(JSON.stringify(result, null, 2));
|
|
3467
|
+
console.log(JSON.stringify({ ...result, ...vectors ? { vectors } : {} }, null, 2));
|
|
3410
3468
|
return;
|
|
3411
3469
|
}
|
|
3412
3470
|
printResult(result);
|
|
3471
|
+
if (vectors) {
|
|
3472
|
+
console.log(
|
|
3473
|
+
pc9.dim(
|
|
3474
|
+
` file vectors: ${vectors.embedded} embedded, ${vectors.files} current` + (vectors.pending > 0 ? `, ${vectors.pending} left for the next run` : "")
|
|
3475
|
+
)
|
|
3476
|
+
);
|
|
3477
|
+
} else if (local) {
|
|
3478
|
+
console.log(pc9.dim(" file vectors: skipped (local embedding runtime not available)"));
|
|
3479
|
+
}
|
|
3413
3480
|
});
|
|
3414
3481
|
});
|
|
3415
3482
|
program.command("watch").option("--debounce <ms>", "Coalesce file-change bursts within this window.", Number).option("--no-llm", "Do not write BYOK model summaries after index passes.").description("Watch the repository and incrementally re-index on change (Ctrl+C to stop).").action(async (opts) => {
|
|
@@ -3447,81 +3514,6 @@ function printResult(result, compact = false) {
|
|
|
3447
3514
|
// src/cli/commands/init-wizard.ts
|
|
3448
3515
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
3449
3516
|
import { confirm, isCancel, log, note, password, spinner, text } from "@clack/prompts";
|
|
3450
|
-
|
|
3451
|
-
// src/cli/commands/postgres-docker.ts
|
|
3452
|
-
import { spawn as spawn4 } from "child_process";
|
|
3453
|
-
import { existsSync as existsSync3 } from "fs";
|
|
3454
|
-
import { dirname as dirname11, resolve as resolve12 } from "path";
|
|
3455
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3456
|
-
function resolveBundledComposeFile() {
|
|
3457
|
-
const here = dirname11(fileURLToPath2(import.meta.url));
|
|
3458
|
-
const candidates = [
|
|
3459
|
-
// installed package: dist/cli/commands/ -> root
|
|
3460
|
-
resolve12(here, "..", "..", "..", "docker-compose.yml"),
|
|
3461
|
-
// source layout: src/cli/commands/ -> root
|
|
3462
|
-
resolve12(here, "..", "..", "..", "..", "docker-compose.yml"),
|
|
3463
|
-
resolve12(here, "..", "..", "docker-compose.yml"),
|
|
3464
|
-
resolve12(process.cwd(), "docker-compose.yml")
|
|
3465
|
-
];
|
|
3466
|
-
for (const candidate of candidates) {
|
|
3467
|
-
if (existsSync3(candidate)) return candidate;
|
|
3468
|
-
}
|
|
3469
|
-
throw new Error(`Could not locate docker-compose.yml. Looked in:
|
|
3470
|
-
${candidates.join("\n ")}`);
|
|
3471
|
-
}
|
|
3472
|
-
async function runDockerCompose(args, options = {}) {
|
|
3473
|
-
const spawnImpl = options.spawnImpl ?? spawn4;
|
|
3474
|
-
const composeFile = resolveBundledComposeFile();
|
|
3475
|
-
const attempts = [
|
|
3476
|
-
{ kind: "v2", bin: "docker", args: ["compose", "-f", composeFile, ...args] },
|
|
3477
|
-
{ kind: "v1", bin: "docker-compose", args: ["-f", composeFile, ...args] }
|
|
3478
|
-
];
|
|
3479
|
-
let lastSpawnError = null;
|
|
3480
|
-
for (const attempt of attempts) {
|
|
3481
|
-
try {
|
|
3482
|
-
return await spawnOnce(spawnImpl, attempt);
|
|
3483
|
-
} catch (error) {
|
|
3484
|
-
const err = error;
|
|
3485
|
-
if (err.code !== "ENOENT") throw err;
|
|
3486
|
-
lastSpawnError = err;
|
|
3487
|
-
}
|
|
3488
|
-
}
|
|
3489
|
-
throw new Error(
|
|
3490
|
-
`Could not find docker. Install Docker Desktop (or docker-compose v1) and ensure it is on your PATH. (${lastSpawnError?.message ?? "spawn ENOENT"})`
|
|
3491
|
-
);
|
|
3492
|
-
}
|
|
3493
|
-
function spawnOnce(spawnImpl, attempt) {
|
|
3494
|
-
return new Promise((resolvePromise, rejectPromise) => {
|
|
3495
|
-
const child = spawnImpl(attempt.bin, attempt.args, {
|
|
3496
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
3497
|
-
});
|
|
3498
|
-
let stdout = "";
|
|
3499
|
-
let stderr = "";
|
|
3500
|
-
child.stdout?.on("data", (chunk) => {
|
|
3501
|
-
stdout += String(chunk);
|
|
3502
|
-
});
|
|
3503
|
-
child.stderr?.on("data", (chunk) => {
|
|
3504
|
-
stderr += String(chunk);
|
|
3505
|
-
});
|
|
3506
|
-
child.on("error", (error) => {
|
|
3507
|
-
rejectPromise(error);
|
|
3508
|
-
});
|
|
3509
|
-
child.on("close", (code) => {
|
|
3510
|
-
resolvePromise({ code: code ?? 0, stdout, stderr });
|
|
3511
|
-
});
|
|
3512
|
-
});
|
|
3513
|
-
}
|
|
3514
|
-
async function postgresUp(options) {
|
|
3515
|
-
return runDockerCompose(["up", "-d"], options ?? {});
|
|
3516
|
-
}
|
|
3517
|
-
async function postgresDown(options) {
|
|
3518
|
-
return runDockerCompose(["down"], options ?? {});
|
|
3519
|
-
}
|
|
3520
|
-
async function postgresStatus(options) {
|
|
3521
|
-
return runDockerCompose(["ps"], options ?? {});
|
|
3522
|
-
}
|
|
3523
|
-
|
|
3524
|
-
// src/cli/commands/init-wizard.ts
|
|
3525
3517
|
function bail() {
|
|
3526
3518
|
log.warn("Aborted. No config was written.");
|
|
3527
3519
|
process.exit(1);
|
|
@@ -3587,7 +3579,7 @@ async function runInitWizard() {
|
|
|
3587
3579
|
if (result.code === 0) {
|
|
3588
3580
|
dockerSpinner.stop("Postgres container started.");
|
|
3589
3581
|
for (let attempt = 0; attempt < 10 && !connected; attempt++) {
|
|
3590
|
-
await new Promise((
|
|
3582
|
+
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
3591
3583
|
connected = await pingOnce(databaseUrl);
|
|
3592
3584
|
}
|
|
3593
3585
|
if (!connected) {
|
|
@@ -3776,7 +3768,7 @@ function registerMapCommands(program, runSafely2) {
|
|
|
3776
3768
|
}
|
|
3777
3769
|
|
|
3778
3770
|
// src/cli/commands/memory-review.ts
|
|
3779
|
-
import { spawn as
|
|
3771
|
+
import { spawn as spawn4 } from "child_process";
|
|
3780
3772
|
import { relative as relative3 } from "path";
|
|
3781
3773
|
import pc12 from "picocolors";
|
|
3782
3774
|
function registerMemoryCommands(program, runSafely2) {
|
|
@@ -3872,15 +3864,15 @@ function truncate(value, max) {
|
|
|
3872
3864
|
function openEditor(path) {
|
|
3873
3865
|
const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
|
|
3874
3866
|
return new Promise((resolvePromise, reject) => {
|
|
3875
|
-
const child =
|
|
3867
|
+
const child = spawn4(editor, [path], { stdio: "inherit" });
|
|
3876
3868
|
child.on("error", reject);
|
|
3877
3869
|
child.on("close", () => resolvePromise());
|
|
3878
3870
|
});
|
|
3879
3871
|
}
|
|
3880
3872
|
|
|
3881
3873
|
// src/cli/commands/models.ts
|
|
3882
|
-
import { existsSync as
|
|
3883
|
-
import { join as
|
|
3874
|
+
import { existsSync as existsSync3 } from "fs";
|
|
3875
|
+
import { join as join14 } from "path";
|
|
3884
3876
|
import { spinner as spinner2 } from "@clack/prompts";
|
|
3885
3877
|
import pc13 from "picocolors";
|
|
3886
3878
|
|
|
@@ -4129,12 +4121,15 @@ async function calibrateEmbedder(embed) {
|
|
|
4129
4121
|
(_, i) => at(Math.round((0.05 + i * 0.01) * 100) / 100, "dev")
|
|
4130
4122
|
);
|
|
4131
4123
|
const best = sweep.reduce((left, right) => right.f05 > left.f05 ? right : left);
|
|
4124
|
+
const f2 = ({ precision, recall }) => precision + recall === 0 ? 0 : 5 * precision * recall / (4 * precision + recall);
|
|
4125
|
+
const recallBest = sweep.reduce((left, right) => f2(right) > f2(left) ? right : left);
|
|
4132
4126
|
return {
|
|
4133
4127
|
auc,
|
|
4134
4128
|
recallAt1: answered === 0 ? 0 : hits / answered,
|
|
4135
4129
|
mrr: answered === 0 ? 0 : reciprocal / answered,
|
|
4136
4130
|
best,
|
|
4137
4131
|
test: at(best.floor, "test"),
|
|
4132
|
+
recall: { dev: recallBest, test: at(recallBest.floor, "test") },
|
|
4138
4133
|
at
|
|
4139
4134
|
};
|
|
4140
4135
|
}
|
|
@@ -4154,7 +4149,7 @@ async function withSpinner(label, work, done) {
|
|
|
4154
4149
|
progress.stop(done(value));
|
|
4155
4150
|
return value;
|
|
4156
4151
|
} catch (error) {
|
|
4157
|
-
progress.
|
|
4152
|
+
progress.error(pc13.red(`\u2717 ${label}`));
|
|
4158
4153
|
throw error;
|
|
4159
4154
|
}
|
|
4160
4155
|
}
|
|
@@ -4162,8 +4157,8 @@ function keyPresent(provider, apiKey) {
|
|
|
4162
4157
|
return Boolean(process.env[KEY_ENV2[provider]] || provider === "huggingface" && apiKey);
|
|
4163
4158
|
}
|
|
4164
4159
|
function localModelDownloaded(id, revision) {
|
|
4165
|
-
const dir =
|
|
4166
|
-
return
|
|
4160
|
+
const dir = join14(modelCacheDir(), id, ...revision ? [revision] : []);
|
|
4161
|
+
return existsSync3(join14(dir, "onnx", "model_quantized.onnx"));
|
|
4167
4162
|
}
|
|
4168
4163
|
async function vectorCounts(postgresUrl, namespace, space) {
|
|
4169
4164
|
const client = createDatabaseClient({ postgresUrl, maxConnections: 1, connectTimeoutSeconds: 3 });
|
|
@@ -4195,7 +4190,12 @@ async function printStatus() {
|
|
|
4195
4190
|
const next = [];
|
|
4196
4191
|
console.log(pc13.bold("Embeddings"));
|
|
4197
4192
|
console.log(row("provider", `${provider.type} ${pc13.dim(model)}`));
|
|
4198
|
-
if (provider.type === "local") {
|
|
4193
|
+
if (provider.type === "local" && !localRuntimeInstalled()) {
|
|
4194
|
+
console.log(
|
|
4195
|
+
row("runtime", warn("@huggingface/transformers is not installed: dense recall is off"))
|
|
4196
|
+
);
|
|
4197
|
+
next.push("npm i -g @huggingface/transformers");
|
|
4198
|
+
} else if (provider.type === "local") {
|
|
4199
4199
|
const ready = localModelDownloaded(LOCAL_EMBEDDING_MODEL.id, LOCAL_EMBEDDING_MODEL.revision);
|
|
4200
4200
|
console.log(
|
|
4201
4201
|
row(
|
|
@@ -4331,7 +4331,7 @@ Examples:
|
|
|
4331
4331
|
);
|
|
4332
4332
|
}
|
|
4333
4333
|
if (!missingKey) {
|
|
4334
|
-
syncInBackground(process.cwd());
|
|
4334
|
+
syncInBackground(process.cwd(), true);
|
|
4335
4335
|
console.log(
|
|
4336
4336
|
pc13.dim(" Re-embedding existing memory in the background (codebuddy hooks sync).")
|
|
4337
4337
|
);
|
|
@@ -4371,7 +4371,7 @@ before keeping one on. A reranker never admits a fact, it only orders them.`
|
|
|
4371
4371
|
});
|
|
4372
4372
|
models.command("pull").description("Download the local models now instead of on first use.").action(async () => {
|
|
4373
4373
|
await runSafely2(async () => {
|
|
4374
|
-
const { LocalModelProvider, rerankLocally } = await import("./local-
|
|
4374
|
+
const { LocalModelProvider, rerankLocally } = await import("./local-ST4WMRCG.js");
|
|
4375
4375
|
const file = await readConfigFile();
|
|
4376
4376
|
let started = Date.now();
|
|
4377
4377
|
await withSpinner(
|
|
@@ -4416,19 +4416,30 @@ before keeping one on. A reranker never admits a fact, it only orders them.`
|
|
|
4416
4416
|
`${result.best.floor}: precision ${pct(result.test.precision)}, recall ${pct(result.test.recall)}, silent on ${pct(result.test.abstain)} of unrelated tasks ${pc13.dim("(chosen on dev, measured on test)")}`
|
|
4417
4417
|
)
|
|
4418
4418
|
);
|
|
4419
|
+
console.log(
|
|
4420
|
+
row(
|
|
4421
|
+
"recall floor",
|
|
4422
|
+
`${result.recall.dev.floor}: precision ${pct(result.recall.test.precision)}, recall ${pct(result.recall.test.recall)} ` + pc13.dim("(explicit recall: best F2 on dev, measured on test)")
|
|
4423
|
+
)
|
|
4424
|
+
);
|
|
4419
4425
|
if (opts.dryRun) return;
|
|
4420
4426
|
const file = await readConfigFile();
|
|
4421
4427
|
await setConfigBlock("provider", {
|
|
4422
4428
|
...file.provider ?? { type: config.provider.type },
|
|
4423
|
-
relevanceFloor: result.best.floor
|
|
4429
|
+
relevanceFloor: result.best.floor,
|
|
4430
|
+
recallFloor: result.recall.dev.floor
|
|
4424
4431
|
});
|
|
4425
|
-
console.log(
|
|
4432
|
+
console.log(
|
|
4433
|
+
ok(
|
|
4434
|
+
`Saved relevanceFloor ${result.best.floor} and recallFloor ${result.recall.dev.floor} to .codebuddy/config.json`
|
|
4435
|
+
)
|
|
4436
|
+
);
|
|
4426
4437
|
});
|
|
4427
4438
|
});
|
|
4428
4439
|
}
|
|
4429
4440
|
|
|
4430
4441
|
// src/cli/commands/plan.ts
|
|
4431
|
-
import { spawn as
|
|
4442
|
+
import { spawn as spawn5 } from "child_process";
|
|
4432
4443
|
import { relative as relative4 } from "path";
|
|
4433
4444
|
import pc14 from "picocolors";
|
|
4434
4445
|
function makeLifecycle(cwd = process.cwd()) {
|
|
@@ -4490,15 +4501,15 @@ function renderPlan(plan) {
|
|
|
4490
4501
|
}
|
|
4491
4502
|
function openEditor2(path) {
|
|
4492
4503
|
const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
|
|
4493
|
-
return new Promise((
|
|
4494
|
-
const child =
|
|
4504
|
+
return new Promise((resolve13, reject) => {
|
|
4505
|
+
const child = spawn5(editor, [path], { stdio: "inherit" });
|
|
4495
4506
|
child.on("error", reject);
|
|
4496
|
-
child.on("close", () =>
|
|
4507
|
+
child.on("close", () => resolve13());
|
|
4497
4508
|
});
|
|
4498
4509
|
}
|
|
4499
4510
|
function runGit(args) {
|
|
4500
|
-
return new Promise((
|
|
4501
|
-
const child =
|
|
4511
|
+
return new Promise((resolve13, reject) => {
|
|
4512
|
+
const child = spawn5("git", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4502
4513
|
let stdout = "";
|
|
4503
4514
|
let stderr = "";
|
|
4504
4515
|
child.stdout.on("data", (c) => {
|
|
@@ -4508,7 +4519,7 @@ function runGit(args) {
|
|
|
4508
4519
|
stderr += String(c);
|
|
4509
4520
|
});
|
|
4510
4521
|
child.on("error", reject);
|
|
4511
|
-
child.on("close", (code) =>
|
|
4522
|
+
child.on("close", (code) => resolve13({ code: code ?? 0, stdout, stderr }));
|
|
4512
4523
|
});
|
|
4513
4524
|
}
|
|
4514
4525
|
function registerPlanCommands(program, runSafely2) {
|
|
@@ -4822,8 +4833,8 @@ function severityBadge2(severity) {
|
|
|
4822
4833
|
}
|
|
4823
4834
|
|
|
4824
4835
|
// src/cli/commands/symbols.ts
|
|
4825
|
-
import { readFile as
|
|
4826
|
-
import { resolve as
|
|
4836
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
4837
|
+
import { resolve as resolve12 } from "path";
|
|
4827
4838
|
import pc18 from "picocolors";
|
|
4828
4839
|
function registerSymbolsCommand(program, runSafely2) {
|
|
4829
4840
|
program.command("symbols").argument("<path>", "Repo-relative or absolute path to a code file.").option("--json", "Print machine-readable JSON.").description("List a file's top-level symbols (functions, classes, types, exports).").action(async (path, opts) => {
|
|
@@ -4832,8 +4843,8 @@ function registerSymbolsCommand(program, runSafely2) {
|
|
|
4832
4843
|
console.log(pc18.dim(`no symbol extraction for ${path} (unsupported language)`));
|
|
4833
4844
|
return;
|
|
4834
4845
|
}
|
|
4835
|
-
const content = await
|
|
4836
|
-
const table = extractSymbolTable(content);
|
|
4846
|
+
const content = await readFile12(resolve12(path), "utf8");
|
|
4847
|
+
const table = extractSymbolTable(content, path);
|
|
4837
4848
|
if (opts.json) {
|
|
4838
4849
|
console.log(JSON.stringify({ path, symbols: table }, null, 2));
|
|
4839
4850
|
return;
|
|
@@ -4860,9 +4871,9 @@ import { confirm as confirm2, isCancel as isCancel2, log as log2, note as note2,
|
|
|
4860
4871
|
import pc19 from "picocolors";
|
|
4861
4872
|
|
|
4862
4873
|
// src/core/global-config.ts
|
|
4863
|
-
import { chmod, mkdir as mkdir8, readFile as
|
|
4874
|
+
import { chmod, mkdir as mkdir8, readFile as readFile13, writeFile as writeFile3 } from "fs/promises";
|
|
4864
4875
|
import { homedir as homedir3 } from "os";
|
|
4865
|
-
import { dirname as
|
|
4876
|
+
import { dirname as dirname11, join as join15 } from "path";
|
|
4866
4877
|
import { z as z2 } from "zod";
|
|
4867
4878
|
var GLOBAL_DIR = ".codebuddy";
|
|
4868
4879
|
var GLOBAL_FILE = "global.json";
|
|
@@ -4875,12 +4886,12 @@ var globalConfigSchema = z2.object({
|
|
|
4875
4886
|
installPath: z2.string().optional()
|
|
4876
4887
|
});
|
|
4877
4888
|
function globalConfigPath(home = homedir3()) {
|
|
4878
|
-
return
|
|
4889
|
+
return join15(home, GLOBAL_DIR, GLOBAL_FILE);
|
|
4879
4890
|
}
|
|
4880
4891
|
async function readGlobalConfig(home = homedir3()) {
|
|
4881
4892
|
const path = globalConfigPath(home);
|
|
4882
4893
|
try {
|
|
4883
|
-
const raw = await
|
|
4894
|
+
const raw = await readFile13(path, "utf8");
|
|
4884
4895
|
return globalConfigSchema.parse(JSON.parse(raw));
|
|
4885
4896
|
} catch (error) {
|
|
4886
4897
|
if (error.code === "ENOENT") return {};
|
|
@@ -4889,7 +4900,7 @@ async function readGlobalConfig(home = homedir3()) {
|
|
|
4889
4900
|
}
|
|
4890
4901
|
async function writeGlobalConfig(next, home = homedir3()) {
|
|
4891
4902
|
const path = globalConfigPath(home);
|
|
4892
|
-
await mkdir8(
|
|
4903
|
+
await mkdir8(dirname11(path), { recursive: true, mode: 448 });
|
|
4893
4904
|
await writeFile3(path, `${JSON.stringify(next, null, 2)}
|
|
4894
4905
|
`, { mode: 384 });
|
|
4895
4906
|
await chmod(path, 384);
|
|
@@ -4902,32 +4913,6 @@ async function mergeGlobalConfig(patch, home = homedir3()) {
|
|
|
4902
4913
|
return { path, merged };
|
|
4903
4914
|
}
|
|
4904
4915
|
|
|
4905
|
-
// src/cli/commands/docker-autostart.ts
|
|
4906
|
-
import { spawn as spawn7 } from "child_process";
|
|
4907
|
-
async function isDockerDaemonRunning() {
|
|
4908
|
-
return new Promise((resolve14) => {
|
|
4909
|
-
const child = spawn7("docker", ["info"], { stdio: "ignore" });
|
|
4910
|
-
child.on("error", () => resolve14(false));
|
|
4911
|
-
child.on("close", (code) => resolve14(code === 0));
|
|
4912
|
-
});
|
|
4913
|
-
}
|
|
4914
|
-
async function tryStartDockerDesktop() {
|
|
4915
|
-
if (process.platform !== "darwin") return { started: false };
|
|
4916
|
-
return new Promise((resolve14) => {
|
|
4917
|
-
const child = spawn7("open", ["-ga", "Docker"], { stdio: "ignore" });
|
|
4918
|
-
child.on("error", () => resolve14({ started: false }));
|
|
4919
|
-
child.on("close", (code) => resolve14({ started: code === 0 }));
|
|
4920
|
-
});
|
|
4921
|
-
}
|
|
4922
|
-
async function waitForDockerDaemon(timeoutMs = 6e4) {
|
|
4923
|
-
const deadline = Date.now() + timeoutMs;
|
|
4924
|
-
while (Date.now() < deadline) {
|
|
4925
|
-
if (await isDockerDaemonRunning()) return true;
|
|
4926
|
-
await new Promise((resolve14) => setTimeout(resolve14, 1e3));
|
|
4927
|
-
}
|
|
4928
|
-
return false;
|
|
4929
|
-
}
|
|
4930
|
-
|
|
4931
4916
|
// src/cli/commands/use-command.ts
|
|
4932
4917
|
function bail2() {
|
|
4933
4918
|
log2.warn("Aborted.");
|
|
@@ -4955,15 +4940,17 @@ async function runUseCommand(options = {}) {
|
|
|
4955
4940
|
const sigintHandler = () => bail2();
|
|
4956
4941
|
process.on("SIGINT", sigintHandler);
|
|
4957
4942
|
try {
|
|
4943
|
+
const interactive = options.interactive ?? process.stdin.isTTY === true;
|
|
4958
4944
|
const folderName = basename2(process.cwd());
|
|
4959
4945
|
const namespace = sanitizeNamespace(options.namespace ?? folderName);
|
|
4960
4946
|
await initProjectScaffold();
|
|
4961
|
-
|
|
4947
|
+
if (options.namespace === void 0) await migrateLegacyNamespace();
|
|
4948
|
+
const graphifyEnabled = options.graphify ?? (interactive && unwrap2(
|
|
4962
4949
|
await confirm2({
|
|
4963
4950
|
message: "Set up Graphify for richer architecture context?",
|
|
4964
4951
|
initialValue: true
|
|
4965
4952
|
})
|
|
4966
|
-
);
|
|
4953
|
+
));
|
|
4967
4954
|
note2(
|
|
4968
4955
|
`Project folder: ${pc19.bold(process.cwd())}
|
|
4969
4956
|
Namespace: ${pc19.bold(namespace)}`,
|
|
@@ -4974,6 +4961,8 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
4974
4961
|
let embeddings = projectConfig.provider?.type;
|
|
4975
4962
|
if (embeddings) {
|
|
4976
4963
|
log2.info(`Embeddings: ${embeddings} (change with ${pc19.cyan("codebuddy models use")}).`);
|
|
4964
|
+
} else if (!interactive) {
|
|
4965
|
+
embeddings = "local";
|
|
4977
4966
|
} else {
|
|
4978
4967
|
embeddings = unwrap2(
|
|
4979
4968
|
await select({
|
|
@@ -5013,6 +5002,10 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
5013
5002
|
} else if (stored.hfToken) {
|
|
5014
5003
|
hfToken = stored.hfToken;
|
|
5015
5004
|
log2.info(`Reusing saved Hugging Face token (${pc19.dim("~/.codebuddy/global.json")}).`);
|
|
5005
|
+
} else if (!interactive) {
|
|
5006
|
+
throw new Error(
|
|
5007
|
+
"Hugging Face embeddings need a token: set HF_TOKEN (no terminal to prompt for it)."
|
|
5008
|
+
);
|
|
5016
5009
|
} else {
|
|
5017
5010
|
hfToken = unwrap2(
|
|
5018
5011
|
await password2({
|
|
@@ -5022,13 +5015,13 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
5022
5015
|
if (!hfToken) log2.warn("No token: hosted embeddings will fail until HF_TOKEN is set.");
|
|
5023
5016
|
}
|
|
5024
5017
|
const initialUrl = options.postgresUrl ?? process.env.DATABASE_URL ?? stored.databaseUrl ?? DEFAULT_DB_URL;
|
|
5025
|
-
const databaseUrl = unwrap2(
|
|
5018
|
+
const databaseUrl = options.postgresUrl ?? (interactive ? unwrap2(
|
|
5026
5019
|
await text2({
|
|
5027
5020
|
message: "Postgres URL (press Enter to accept)",
|
|
5028
5021
|
initialValue: initialUrl,
|
|
5029
5022
|
validate: (value) => value && value.length > 0 ? void 0 : "Postgres URL is required."
|
|
5030
5023
|
})
|
|
5031
|
-
);
|
|
5024
|
+
) : initialUrl);
|
|
5032
5025
|
const dbSpinner = spinner3();
|
|
5033
5026
|
dbSpinner.start("Checking Postgres");
|
|
5034
5027
|
let connected = await pingOnce2(databaseUrl);
|
|
@@ -5036,12 +5029,12 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
5036
5029
|
if (!connected && databaseUrl === DEFAULT_DB_URL) {
|
|
5037
5030
|
dbSpinner.stop("Postgres unreachable on the default local URL.");
|
|
5038
5031
|
}
|
|
5039
|
-
const shouldUseDocker = !connected && databaseUrl === DEFAULT_DB_URL && (options.useDocker ?? unwrap2(
|
|
5032
|
+
const shouldUseDocker = !connected && databaseUrl === DEFAULT_DB_URL && (options.useDocker ?? (interactive && unwrap2(
|
|
5040
5033
|
await confirm2({
|
|
5041
5034
|
message: "Postgres is unavailable. Start the bundled Docker database now?",
|
|
5042
5035
|
initialValue: true
|
|
5043
5036
|
})
|
|
5044
|
-
));
|
|
5037
|
+
)));
|
|
5045
5038
|
if (shouldUseDocker) {
|
|
5046
5039
|
if (!await isDockerDaemonRunning()) {
|
|
5047
5040
|
const dockerSpinner = spinner3();
|
|
@@ -5061,7 +5054,7 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
5061
5054
|
if (result.code === 0) {
|
|
5062
5055
|
composeSpinner.stop("Postgres container started.");
|
|
5063
5056
|
for (let attempt = 0; attempt < 12 && !connected; attempt++) {
|
|
5064
|
-
await new Promise((
|
|
5057
|
+
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
5065
5058
|
connected = await pingOnce2(databaseUrl);
|
|
5066
5059
|
}
|
|
5067
5060
|
if (!connected) {
|
|
@@ -5076,7 +5069,7 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
5076
5069
|
} else if (!connected) {
|
|
5077
5070
|
dbSpinner.stop(connected ? "Postgres reachable." : "Postgres unreachable at this URL.");
|
|
5078
5071
|
log2.warn(
|
|
5079
|
-
"Local Postgres is required. Start it, set DATABASE_URL, pass --postgres-url, or allow the bundled Docker database."
|
|
5072
|
+
"Local Postgres is required. Start it, set DATABASE_URL, pass --postgres-url, or allow the bundled Docker database (--docker)."
|
|
5080
5073
|
);
|
|
5081
5074
|
bail2();
|
|
5082
5075
|
}
|
|
@@ -5282,9 +5275,7 @@ function registerZvecCommands(program, runSafely2) {
|
|
|
5282
5275
|
...opts.rebuild ? { rebuild: true } : {}
|
|
5283
5276
|
});
|
|
5284
5277
|
if (code !== 0) throw new Error(`zg index exited with code ${code}`);
|
|
5285
|
-
console.log(
|
|
5286
|
-
pc21.dim("tip: add .zvec-grep/ to .gitignore; enable with `codebuddy zvec enable`")
|
|
5287
|
-
);
|
|
5278
|
+
console.log(pc21.dim("next: codebuddy zvec enable (.zvec-grep/ ignores itself in git)"));
|
|
5288
5279
|
});
|
|
5289
5280
|
});
|
|
5290
5281
|
zvec.command("enable").description("Use zvec-grep candidates in context_pack / context_before_edit.").action(async () => {
|
|
@@ -5319,7 +5310,7 @@ function createCli() {
|
|
|
5319
5310
|
).argument("[namespace]", "Override the namespace (defaults to current folder name).").option("--postgres-url <url>", "Postgres URL to use for this project.").option("--skip-claude", "Do not register with Claude Desktop.").option("--skip-codex", "Do not register with Codex.").option("--graphify", "Enable Graphify setup without prompting.").option("--no-graphify", "Skip Graphify setup without prompting.").option(
|
|
5320
5311
|
"--docker",
|
|
5321
5312
|
"Start CodeBuddy's bundled Postgres container when the default DB is unavailable."
|
|
5322
|
-
).option("--no-docker", "Do not offer to start CodeBuddy's bundled Postgres container.").action(
|
|
5313
|
+
).option("--no-docker", "Do not offer to start CodeBuddy's bundled Postgres container.").option("-y, --yes", "Never prompt: use flags and defaults (automatic without a TTY).").option("--non-interactive", "Same as --yes.").action(
|
|
5323
5314
|
async (namespace, opts) => {
|
|
5324
5315
|
await runSafely(async () => {
|
|
5325
5316
|
await runUseCommand({
|
|
@@ -5328,7 +5319,8 @@ function createCli() {
|
|
|
5328
5319
|
...opts.skipClaude !== void 0 ? { skipClaude: opts.skipClaude } : {},
|
|
5329
5320
|
...opts.skipCodex !== void 0 ? { skipCodex: opts.skipCodex } : {},
|
|
5330
5321
|
...opts.graphify !== void 0 ? { graphify: opts.graphify } : {},
|
|
5331
|
-
...opts.docker !== void 0 ? { useDocker: opts.docker } : {}
|
|
5322
|
+
...opts.docker !== void 0 ? { useDocker: opts.docker } : {},
|
|
5323
|
+
...opts.yes || opts.nonInteractive ? { interactive: false } : {}
|
|
5332
5324
|
});
|
|
5333
5325
|
});
|
|
5334
5326
|
}
|
|
@@ -5472,7 +5464,7 @@ function createCli() {
|
|
|
5472
5464
|
console.log(`Claude Desktop config: ${result.path}`);
|
|
5473
5465
|
for (const entry of result.entries) {
|
|
5474
5466
|
console.log(
|
|
5475
|
-
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl
|
|
5467
|
+
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl ? String(redactSecrets(entry.databaseUrl)) : "?"}`
|
|
5476
5468
|
);
|
|
5477
5469
|
}
|
|
5478
5470
|
});
|
|
@@ -5517,7 +5509,7 @@ function createCli() {
|
|
|
5517
5509
|
console.log(`Codex config: ${result.path}`);
|
|
5518
5510
|
for (const entry of result.entries) {
|
|
5519
5511
|
console.log(
|
|
5520
|
-
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl
|
|
5512
|
+
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl ? String(redactSecrets(entry.databaseUrl)) : "?"}`
|
|
5521
5513
|
);
|
|
5522
5514
|
}
|
|
5523
5515
|
});
|
|
@@ -5703,6 +5695,9 @@ function printDoctor(report) {
|
|
|
5703
5695
|
console.log(
|
|
5704
5696
|
` runtime=${report.namespace.runtime ?? "unset"} default=${report.namespace.expectedDefault}`
|
|
5705
5697
|
);
|
|
5698
|
+
if (report.namespace.migrated) {
|
|
5699
|
+
console.log(` migrated legacy namespace "default" to "${report.namespace.migrated}"`);
|
|
5700
|
+
}
|
|
5706
5701
|
if (report.namespace.warning) console.log(` ${report.namespace.warning}`);
|
|
5707
5702
|
console.log(
|
|
5708
5703
|
`vectors: ${report.vectors.count} index=${report.vectors.index ?? "missing"} tuning=${report.vectors.needsTuning ? "recommended" : "not-needed"}`
|
|
@@ -5732,9 +5727,12 @@ function printDbDoctor(report) {
|
|
|
5732
5727
|
if (report.pgvector.error) console.log(` ${report.pgvector.error}`);
|
|
5733
5728
|
console.log(`namespace: ${report.namespace.ok ? ok2 : warn2}`);
|
|
5734
5729
|
console.log(` runtime=${report.namespace.runtime ?? "unset"}`);
|
|
5730
|
+
if (report.namespace.migrated) {
|
|
5731
|
+
console.log(` migrated legacy namespace "default" to "${report.namespace.migrated}"`);
|
|
5732
|
+
}
|
|
5735
5733
|
if (report.namespace.warning) console.log(` ${report.namespace.warning}`);
|
|
5736
5734
|
}
|
|
5737
5735
|
export {
|
|
5738
5736
|
createCli
|
|
5739
5737
|
};
|
|
5740
|
-
//# sourceMappingURL=main-
|
|
5738
|
+
//# sourceMappingURL=main-AHNGHC4L.js.map
|