@orquentra/codebuddy 2.5.0 → 2.6.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/CLAUDE_CODEX.md +6 -4
- package/README.md +8 -0
- package/WORKFLOW.md +5 -5
- package/dist/{chunk-JDZ3VK26.js → chunk-2XDPKFUW.js} +114 -823
- package/dist/chunk-2XDPKFUW.js.map +1 -0
- package/dist/{chunk-QDBDYCM2.js → chunk-5FW3PMNP.js} +2 -2
- package/dist/{chunk-776EQXDV.js → chunk-5KZY6OTG.js} +82 -5
- package/dist/chunk-5KZY6OTG.js.map +1 -0
- package/dist/{chunk-UFZD3JAA.js → chunk-5MQOE4J6.js} +3 -3
- package/dist/chunk-5UH3BEQR.js +32 -0
- package/dist/chunk-5UH3BEQR.js.map +1 -0
- package/dist/{chunk-ROQTT5ZO.js → chunk-B6CO63SQ.js} +8 -7
- package/dist/chunk-B6CO63SQ.js.map +1 -0
- package/dist/chunk-CSRD5OQA.js +79 -0
- package/dist/chunk-CSRD5OQA.js.map +1 -0
- package/dist/{chunk-PYLH4MH5.js → chunk-FJOTP632.js} +1 -1
- package/dist/{chunk-3XYQGFPB.js → chunk-IBLJOHJL.js} +16 -3
- package/dist/chunk-IBLJOHJL.js.map +1 -0
- package/dist/chunk-IMFUYEZA.js +1607 -0
- package/dist/chunk-IMFUYEZA.js.map +1 -0
- package/dist/{chunk-CQPCHMBS.js → chunk-J2EAZ4MA.js} +21 -8
- package/dist/chunk-J2EAZ4MA.js.map +1 -0
- package/dist/{chunk-KYK6RPAJ.js → chunk-JFDRBPYF.js} +2 -2
- package/dist/{chunk-JMWJ7V6Y.js → chunk-JPHJBCZB.js} +2 -2
- package/dist/{chunk-JMWJ7V6Y.js.map → chunk-JPHJBCZB.js.map} +1 -1
- package/dist/{chunk-L5AYZC3F.js → chunk-NERKZSSE.js} +7 -7
- package/dist/{chunk-PCE4STAY.js → chunk-OWWCDRXW.js} +5 -5
- package/dist/{chunk-WHZSVY2L.js → chunk-QBDJXGG5.js} +2 -2
- package/dist/{chunk-Z5QB367W.js → chunk-R7CD6EXS.js} +367 -1798
- package/dist/chunk-R7CD6EXS.js.map +1 -0
- package/dist/{chunk-6MKEIDX5.js → chunk-RAJJSCIP.js} +2 -2
- package/dist/chunk-S6VEG4S2.js +991 -0
- package/dist/chunk-S6VEG4S2.js.map +1 -0
- package/dist/{chunk-4BYGTEJT.js → chunk-XBJQKCLU.js} +2 -2
- package/dist/cli/index.js +14 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/{cloud-GP6G3EAK.js → cloud-7WM3YLI4.js} +3 -3
- package/dist/{codebuddy-DM-i0Fu5.d.ts → codebuddy-B_pCaQrV.d.ts} +22 -2
- package/dist/{config-KFEHLV6W.js → config-DEVHUDIU.js} +3 -3
- package/dist/docker-autostart-KDME7TVC.js +12 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +22 -18
- package/dist/langgraph/index.d.ts +1 -1
- package/dist/lean-command-HTQCPH76.js +15 -0
- package/dist/local-5MZURLCZ.js +17 -0
- package/dist/{main-BDVQAGAS.js → main-MTBQZGJV.js} +333 -219
- package/dist/main-MTBQZGJV.js.map +1 -0
- package/dist/{memory-4RGVLPKG.js → memory-KIC5FJVW.js} +4 -4
- package/dist/{operations-EQGOFCBD.js → operations-POCHY3WR.js} +8 -7
- package/dist/postgres-docker-QQZQ2ABK.js +16 -0
- package/dist/{pretool-command-MQQ2UNQM.js → pretool-command-AX6JXP25.js} +3 -3
- package/dist/{rerank-3P3C2UHN.js → rerank-5QZ3PNUW.js} +4 -4
- package/dist/runtime-CUBOOPZO.js +43 -0
- package/dist/runtime-CUBOOPZO.js.map +1 -0
- package/dist/stdio-HOV4P3DQ.js +12 -0
- package/dist/stdio-HOV4P3DQ.js.map +1 -0
- package/dist/{summaries-ZBV5IN7Y.js → summaries-SB5L2TSW.js} +6 -6
- package/dist/summaries-SB5L2TSW.js.map +1 -0
- package/dist/{zvec-MAPSJQSR.js → zvec-MSRKT7IV.js} +3 -3
- package/dist/zvec-MSRKT7IV.js.map +1 -0
- package/package.json +7 -10
- package/dist/chunk-3XYQGFPB.js.map +0 -1
- package/dist/chunk-776EQXDV.js.map +0 -1
- package/dist/chunk-CQPCHMBS.js.map +0 -1
- package/dist/chunk-JDZ3VK26.js.map +0 -1
- package/dist/chunk-ROQTT5ZO.js.map +0 -1
- package/dist/chunk-Z5QB367W.js.map +0 -1
- package/dist/lean-command-DA4ZNKG3.js +0 -15
- package/dist/local-3NGNESNB.js +0 -13
- package/dist/main-BDVQAGAS.js.map +0 -1
- /package/dist/{chunk-QDBDYCM2.js.map → chunk-5FW3PMNP.js.map} +0 -0
- /package/dist/{chunk-UFZD3JAA.js.map → chunk-5MQOE4J6.js.map} +0 -0
- /package/dist/{chunk-PYLH4MH5.js.map → chunk-FJOTP632.js.map} +0 -0
- /package/dist/{chunk-KYK6RPAJ.js.map → chunk-JFDRBPYF.js.map} +0 -0
- /package/dist/{chunk-L5AYZC3F.js.map → chunk-NERKZSSE.js.map} +0 -0
- /package/dist/{chunk-PCE4STAY.js.map → chunk-OWWCDRXW.js.map} +0 -0
- /package/dist/{chunk-WHZSVY2L.js.map → chunk-QBDJXGG5.js.map} +0 -0
- /package/dist/{chunk-6MKEIDX5.js.map → chunk-RAJJSCIP.js.map} +0 -0
- /package/dist/{chunk-4BYGTEJT.js.map → chunk-XBJQKCLU.js.map} +0 -0
- /package/dist/{cloud-GP6G3EAK.js.map → cloud-7WM3YLI4.js.map} +0 -0
- /package/dist/{config-KFEHLV6W.js.map → config-DEVHUDIU.js.map} +0 -0
- /package/dist/{lean-command-DA4ZNKG3.js.map → docker-autostart-KDME7TVC.js.map} +0 -0
- /package/dist/{local-3NGNESNB.js.map → lean-command-HTQCPH76.js.map} +0 -0
- /package/dist/{operations-EQGOFCBD.js.map → local-5MZURLCZ.js.map} +0 -0
- /package/dist/{memory-4RGVLPKG.js.map → memory-KIC5FJVW.js.map} +0 -0
- /package/dist/{pretool-command-MQQ2UNQM.js.map → operations-POCHY3WR.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-AX6JXP25.js.map} +0 -0
- /package/dist/{rerank-3P3C2UHN.js.map → rerank-5QZ3PNUW.js.map} +0 -0
|
@@ -1,40 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runPreToolHookCommand
|
|
3
|
+
} from "./chunk-QBDJXGG5.js";
|
|
1
4
|
import {
|
|
2
5
|
loadLlmSummaries,
|
|
3
6
|
summarizeRepository
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OWWCDRXW.js";
|
|
5
8
|
import {
|
|
6
9
|
chatJson,
|
|
7
10
|
coolingDown,
|
|
8
11
|
usageToday
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5MQOE4J6.js";
|
|
13
|
+
import {
|
|
14
|
+
isDockerDaemonRunning,
|
|
15
|
+
tryStartDockerDesktop,
|
|
16
|
+
waitForDockerDaemon
|
|
17
|
+
} from "./chunk-5UH3BEQR.js";
|
|
18
|
+
import {
|
|
19
|
+
postgresDown,
|
|
20
|
+
postgresStatus,
|
|
21
|
+
postgresUp
|
|
22
|
+
} from "./chunk-CSRD5OQA.js";
|
|
10
23
|
import {
|
|
11
24
|
renderLeanBlock,
|
|
12
25
|
runLeanHookCommand
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import {
|
|
15
|
-
runPreToolHookCommand
|
|
16
|
-
} from "./chunk-WHZSVY2L.js";
|
|
26
|
+
} from "./chunk-B6CO63SQ.js";
|
|
17
27
|
import {
|
|
18
28
|
failSoft,
|
|
19
29
|
readHookInput,
|
|
20
30
|
writeStdout
|
|
21
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-FJOTP632.js";
|
|
32
|
+
import {
|
|
33
|
+
generateSuggestions,
|
|
34
|
+
migrateMemoryToFiles,
|
|
35
|
+
registerCodeBuddyTools,
|
|
36
|
+
startMcpServer,
|
|
37
|
+
watchRepository
|
|
38
|
+
} from "./chunk-IMFUYEZA.js";
|
|
22
39
|
import {
|
|
23
40
|
PlanFileStore,
|
|
24
41
|
PlanLifecycle,
|
|
25
42
|
ReviewStore,
|
|
26
|
-
VERSION,
|
|
27
43
|
WorklogStore,
|
|
28
44
|
approveReviewItem,
|
|
29
45
|
assessRisk,
|
|
30
46
|
buildBeforeEditContext,
|
|
31
47
|
buildBootstrapContext,
|
|
32
|
-
generateSuggestions,
|
|
33
|
-
migrateMemoryToFiles,
|
|
34
48
|
openHookSemantics,
|
|
35
49
|
parseTraceLines,
|
|
36
50
|
readTraces,
|
|
37
|
-
registerCodeBuddyTools,
|
|
38
51
|
renderContextBlock,
|
|
39
52
|
resolveRiskPaths,
|
|
40
53
|
runCaptureHook,
|
|
@@ -42,15 +55,14 @@ import {
|
|
|
42
55
|
runResetHook,
|
|
43
56
|
runStageHook,
|
|
44
57
|
runSyncHook,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
watchRepository
|
|
48
|
-
} from "./chunk-Z5QB367W.js";
|
|
58
|
+
tracePath
|
|
59
|
+
} from "./chunk-R7CD6EXS.js";
|
|
49
60
|
import "./chunk-IHQM2ZDV.js";
|
|
50
61
|
import {
|
|
51
62
|
SessionCapsuleLedger,
|
|
52
|
-
estimateTokens
|
|
53
|
-
|
|
63
|
+
estimateTokens,
|
|
64
|
+
hookRoot
|
|
65
|
+
} from "./chunk-J2EAZ4MA.js";
|
|
54
66
|
import {
|
|
55
67
|
buildArchitectureMap,
|
|
56
68
|
generateGraphifyGraph,
|
|
@@ -60,13 +72,12 @@ import {
|
|
|
60
72
|
neighbours,
|
|
61
73
|
queryMap,
|
|
62
74
|
setupGraphify
|
|
63
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-NERKZSSE.js";
|
|
64
76
|
import {
|
|
65
77
|
extractSymbolTable,
|
|
66
78
|
supportsSymbols
|
|
67
79
|
} from "./chunk-PQK3GKZH.js";
|
|
68
80
|
import {
|
|
69
|
-
MemoryFileStore,
|
|
70
81
|
bootstrapDatabase,
|
|
71
82
|
buildProviderFromConfig,
|
|
72
83
|
createDatabaseClient,
|
|
@@ -77,39 +88,46 @@ import {
|
|
|
77
88
|
pingDatabase,
|
|
78
89
|
runDoctor,
|
|
79
90
|
runMigrations
|
|
80
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-2XDPKFUW.js";
|
|
92
|
+
import {
|
|
93
|
+
MemoryFileStore,
|
|
94
|
+
VERSION
|
|
95
|
+
} from "./chunk-S6VEG4S2.js";
|
|
81
96
|
import {
|
|
82
97
|
redactPersisted
|
|
83
98
|
} from "./chunk-GDJH7XJC.js";
|
|
84
99
|
import {
|
|
85
100
|
computeFactHash,
|
|
86
101
|
generateEntityId
|
|
87
|
-
} from "./chunk-
|
|
88
|
-
import "./chunk-
|
|
102
|
+
} from "./chunk-XBJQKCLU.js";
|
|
103
|
+
import "./chunk-JFDRBPYF.js";
|
|
89
104
|
import {
|
|
105
|
+
localRuntimeInstalled,
|
|
90
106
|
modelCacheDir
|
|
91
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-IBLJOHJL.js";
|
|
92
108
|
import {
|
|
93
109
|
DEFAULT_CLOUD_EMBEDDING_MODELS,
|
|
94
110
|
DEFAULT_RERANK_MODELS,
|
|
95
111
|
LOCAL_EMBEDDING_MODEL,
|
|
96
112
|
getModelDefinition
|
|
97
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-JPHJBCZB.js";
|
|
98
114
|
import {
|
|
99
115
|
DEFAULT_ZVEC_MODEL,
|
|
100
116
|
buildZvecIndex,
|
|
101
117
|
zvecStatus
|
|
102
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-5FW3PMNP.js";
|
|
103
119
|
import {
|
|
104
120
|
resolveLlmConfig
|
|
105
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-RAJJSCIP.js";
|
|
106
122
|
import {
|
|
107
123
|
PLAN_POLICIES,
|
|
108
124
|
configPath,
|
|
125
|
+
defaultNamespaceForCwd,
|
|
109
126
|
initConfigFile,
|
|
110
127
|
initProjectScaffold,
|
|
111
128
|
loadPlanPolicy,
|
|
112
129
|
loadRuntimeConfig,
|
|
130
|
+
migrateLegacyNamespace,
|
|
113
131
|
readConfigFile,
|
|
114
132
|
redactSecrets,
|
|
115
133
|
resolveNamespaceFrom,
|
|
@@ -119,7 +137,7 @@ import {
|
|
|
119
137
|
setZvecEnabled,
|
|
120
138
|
writeAtomic,
|
|
121
139
|
writeConfigFile
|
|
122
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-5KZY6OTG.js";
|
|
123
141
|
import "./chunk-PZ5AY32C.js";
|
|
124
142
|
|
|
125
143
|
// src/cli/main.ts
|
|
@@ -338,7 +356,7 @@ function runTestCommand(command, source, repositoryRoot, timeoutMs) {
|
|
|
338
356
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
339
357
|
throw new Error("--timeout must be a positive number of milliseconds.");
|
|
340
358
|
}
|
|
341
|
-
return new Promise((
|
|
359
|
+
return new Promise((resolve13) => {
|
|
342
360
|
const startedAt = Date.now();
|
|
343
361
|
const child = spawn(command, {
|
|
344
362
|
cwd: repositoryRoot,
|
|
@@ -363,7 +381,7 @@ ${output.slice(-MAX_TEST_OUTPUT_CHARS)}`;
|
|
|
363
381
|
}, timeoutMs);
|
|
364
382
|
child.on("close", (exitCode, signal) => {
|
|
365
383
|
clearTimeout(timer);
|
|
366
|
-
|
|
384
|
+
resolve13({
|
|
367
385
|
status: timedOut ? "timed_out" : exitCode === 0 ? "passed" : "failed",
|
|
368
386
|
command,
|
|
369
387
|
source,
|
|
@@ -375,7 +393,7 @@ ${output.slice(-MAX_TEST_OUTPUT_CHARS)}`;
|
|
|
375
393
|
});
|
|
376
394
|
child.on("error", (error) => {
|
|
377
395
|
clearTimeout(timer);
|
|
378
|
-
|
|
396
|
+
resolve13({
|
|
379
397
|
status: "failed",
|
|
380
398
|
command,
|
|
381
399
|
source,
|
|
@@ -633,14 +651,17 @@ function resolveCliEntrypoint() {
|
|
|
633
651
|
}
|
|
634
652
|
function buildEntry(options) {
|
|
635
653
|
const env = {
|
|
636
|
-
CODEBUDDY_NAMESPACE: options.namespace
|
|
654
|
+
CODEBUDDY_NAMESPACE: options.namespace,
|
|
655
|
+
CODEBUDDY_PROJECT_ROOT: resolve2(options.projectRoot ?? process.cwd())
|
|
637
656
|
};
|
|
638
|
-
if (options.projectRoot) env.CODEBUDDY_PROJECT_ROOT = options.projectRoot;
|
|
639
657
|
if (options.hfToken) env.HF_TOKEN = options.hfToken;
|
|
640
658
|
if (options.groqApiKey) env.GROQ_API_KEY = options.groqApiKey;
|
|
641
659
|
if (options.databaseUrl) env.DATABASE_URL = options.databaseUrl;
|
|
642
660
|
return {
|
|
643
|
-
|
|
661
|
+
// Absolute: Claude Desktop is a GUI app and does not inherit the shell's
|
|
662
|
+
// PATH (nvm, Homebrew), so a bare "node" may not resolve or may be another
|
|
663
|
+
// version. Re-run `codebuddy claude install` after switching Node.
|
|
664
|
+
command: process.execPath,
|
|
644
665
|
args: [resolveCliEntrypoint(), "serve"],
|
|
645
666
|
env
|
|
646
667
|
};
|
|
@@ -1034,6 +1055,8 @@ function hook(command, payload) {
|
|
|
1034
1055
|
child = spawn("codebuddy", ["hooks", command], {
|
|
1035
1056
|
cwd: payload.cwd,
|
|
1036
1057
|
stdio: ["pipe", "pipe", "ignore"],
|
|
1058
|
+
// npm installs a codebuddy.cmd shim on Windows, which spawn only runs through a shell.
|
|
1059
|
+
shell: process.platform === "win32",
|
|
1037
1060
|
});
|
|
1038
1061
|
} catch {
|
|
1039
1062
|
done("");
|
|
@@ -2938,7 +2961,13 @@ data: ${data}
|
|
|
2938
2961
|
`);
|
|
2939
2962
|
};
|
|
2940
2963
|
watchFile(path, { interval: options.pollMs ?? 1e3 }, () => void onChange());
|
|
2964
|
+
let boundPort = 0;
|
|
2941
2965
|
const server = createServer(async (request, response) => {
|
|
2966
|
+
const host = request.headers.host ?? "";
|
|
2967
|
+
if (host !== `127.0.0.1:${boundPort}` && host !== `localhost:${boundPort}`) {
|
|
2968
|
+
response.writeHead(403, { "content-type": "text/plain" }).end("Forbidden host");
|
|
2969
|
+
return;
|
|
2970
|
+
}
|
|
2942
2971
|
const url = new URL(request.url ?? "/", "http://localhost");
|
|
2943
2972
|
if (request.method !== "GET") {
|
|
2944
2973
|
response.writeHead(405).end();
|
|
@@ -2978,18 +3007,19 @@ data: ${data}
|
|
|
2978
3007
|
response.writeHead(404, { "content-type": "text/plain" }).end("Not found");
|
|
2979
3008
|
});
|
|
2980
3009
|
const port = await listen(server, options.port ?? 4777);
|
|
3010
|
+
boundPort = port;
|
|
2981
3011
|
const heartbeat = setInterval(() => {
|
|
2982
3012
|
for (const client of clients) client.write(": ping\n\n");
|
|
2983
3013
|
}, 25e3);
|
|
2984
3014
|
heartbeat.unref();
|
|
2985
3015
|
return {
|
|
2986
3016
|
url: `http://127.0.0.1:${port}/`,
|
|
2987
|
-
close: () => new Promise((
|
|
3017
|
+
close: () => new Promise((resolve13) => {
|
|
2988
3018
|
clearInterval(heartbeat);
|
|
2989
3019
|
unwatchFile(path);
|
|
2990
3020
|
for (const client of clients) client.end();
|
|
2991
3021
|
server.closeAllConnections();
|
|
2992
|
-
server.close(() =>
|
|
3022
|
+
server.close(() => resolve13());
|
|
2993
3023
|
})
|
|
2994
3024
|
};
|
|
2995
3025
|
}
|
|
@@ -2997,11 +3027,11 @@ async function listen(server, port) {
|
|
|
2997
3027
|
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
2998
3028
|
const candidate = port === 0 ? 0 : port + attempt;
|
|
2999
3029
|
try {
|
|
3000
|
-
await new Promise((
|
|
3030
|
+
await new Promise((resolve13, reject) => {
|
|
3001
3031
|
server.once("error", reject);
|
|
3002
3032
|
server.listen(candidate, "127.0.0.1", () => {
|
|
3003
3033
|
server.off("error", reject);
|
|
3004
|
-
|
|
3034
|
+
resolve13();
|
|
3005
3035
|
});
|
|
3006
3036
|
});
|
|
3007
3037
|
return server.address().port;
|
|
@@ -3039,8 +3069,8 @@ function registerDashboardCommand(program, runSafely2) {
|
|
|
3039
3069
|
);
|
|
3040
3070
|
console.log(pc4.dim(" Ctrl+C to stop."));
|
|
3041
3071
|
if (opts.open) openBrowser(dashboard.url);
|
|
3042
|
-
await new Promise((
|
|
3043
|
-
const stop = () => void dashboard.close().then(
|
|
3072
|
+
await new Promise((resolve13) => {
|
|
3073
|
+
const stop = () => void dashboard.close().then(resolve13);
|
|
3044
3074
|
process.once("SIGINT", stop);
|
|
3045
3075
|
process.once("SIGTERM", stop);
|
|
3046
3076
|
});
|
|
@@ -3146,7 +3176,7 @@ function registerGitHubCommands(program, runSafely2) {
|
|
|
3146
3176
|
}
|
|
3147
3177
|
|
|
3148
3178
|
// src/cli/commands/hooks.ts
|
|
3149
|
-
import { spawn as spawn3 } from "child_process";
|
|
3179
|
+
import { execFile as execFile2, spawn as spawn3 } from "child_process";
|
|
3150
3180
|
import { relative as relative2 } from "path";
|
|
3151
3181
|
import pc7 from "picocolors";
|
|
3152
3182
|
function registerHooksCommands(program, runSafely2) {
|
|
@@ -3168,7 +3198,8 @@ function registerHooksCommands(program, runSafely2) {
|
|
|
3168
3198
|
`${changed ? pc7.green("installed") : pc7.dim("unchanged")} CodeBuddy hooks in ${where}`
|
|
3169
3199
|
);
|
|
3170
3200
|
await reconcileRules(client, "hooks");
|
|
3171
|
-
|
|
3201
|
+
warnIfHookCommandStale();
|
|
3202
|
+
syncInBackground(process.cwd(), true);
|
|
3172
3203
|
console.log(
|
|
3173
3204
|
pc7.dim(
|
|
3174
3205
|
` prompt\u2192recall \xB7 edit\u2192stage \xB7 turn end\u2192capture \xB7 compaction\u2192reset. Restart ${CLIENT_ADAPTERS[client].name} to activate.`
|
|
@@ -3226,18 +3257,18 @@ function registerHooksCommands(program, runSafely2) {
|
|
|
3226
3257
|
`codebuddy: captured from ${changedFiles.length} changed file(s) \u2014 ${result.saved.length} saved, ${result.queuedForReview.length} queued
|
|
3227
3258
|
`
|
|
3228
3259
|
);
|
|
3229
|
-
if (result.saved.length > 0) syncInBackground(input.cwd
|
|
3260
|
+
if (result.saved.length > 0) syncInBackground(hookRoot(input.cwd));
|
|
3230
3261
|
}
|
|
3231
3262
|
});
|
|
3232
3263
|
});
|
|
3233
3264
|
hooks.command("sync").description(
|
|
3234
3265
|
"[hook] Reindex Markdown memory into PostgreSQL and embed it locally (runs detached after capture)."
|
|
3235
|
-
).action(async () => {
|
|
3266
|
+
).option("--respace", "Also re-embed vectors made by another embedding model.").action(async (opts) => {
|
|
3236
3267
|
await failSoft(async () => {
|
|
3237
|
-
const result = await runSyncHook(process.cwd());
|
|
3268
|
+
const result = await runSyncHook(process.cwd(), opts.respace ? { respace: true } : {});
|
|
3238
3269
|
process.stderr.write(
|
|
3239
3270
|
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)"}
|
|
3240
|
-
` : "codebuddy: no PostgreSQL configured
|
|
3271
|
+
` : "codebuddy: nothing to sync (no PostgreSQL configured, or another sync is running)\n"
|
|
3241
3272
|
);
|
|
3242
3273
|
});
|
|
3243
3274
|
});
|
|
@@ -3271,15 +3302,42 @@ async function reconcileRules(client, mode) {
|
|
|
3271
3302
|
);
|
|
3272
3303
|
}
|
|
3273
3304
|
}
|
|
3274
|
-
function
|
|
3305
|
+
function warnIfHookCommandStale() {
|
|
3306
|
+
execFile2(
|
|
3307
|
+
"codebuddy",
|
|
3308
|
+
["--version"],
|
|
3309
|
+
{ timeout: 1e4, shell: process.platform === "win32" },
|
|
3310
|
+
(error, stdout) => {
|
|
3311
|
+
const found = stdout.trim();
|
|
3312
|
+
if (error || !found) {
|
|
3313
|
+
console.log(
|
|
3314
|
+
pc7.yellow(
|
|
3315
|
+
" ! `codebuddy` is not on PATH, so the hooks cannot run. Install it globally: npm i -g @orquentra/codebuddy"
|
|
3316
|
+
)
|
|
3317
|
+
);
|
|
3318
|
+
} else if (found !== VERSION) {
|
|
3319
|
+
console.log(
|
|
3320
|
+
pc7.yellow(
|
|
3321
|
+
` ! The hooks will run codebuddy ${found} from PATH, not ${VERSION}. Update it: npm i -g @orquentra/codebuddy@${VERSION}`
|
|
3322
|
+
)
|
|
3323
|
+
);
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
function syncInBackground(cwd, respace = false) {
|
|
3275
3329
|
const entry = process.argv[1];
|
|
3276
3330
|
if (!entry) return;
|
|
3277
3331
|
try {
|
|
3278
|
-
spawn3(
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3332
|
+
spawn3(
|
|
3333
|
+
process.execPath,
|
|
3334
|
+
[...process.execArgv, entry, "hooks", "sync", ...respace ? ["--respace"] : []],
|
|
3335
|
+
{
|
|
3336
|
+
cwd,
|
|
3337
|
+
detached: true,
|
|
3338
|
+
stdio: "ignore"
|
|
3339
|
+
}
|
|
3340
|
+
).unref();
|
|
3283
3341
|
} catch {
|
|
3284
3342
|
}
|
|
3285
3343
|
}
|
|
@@ -3446,81 +3504,6 @@ function printResult(result, compact = false) {
|
|
|
3446
3504
|
// src/cli/commands/init-wizard.ts
|
|
3447
3505
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
3448
3506
|
import { confirm, isCancel, log, note, password, spinner, text } from "@clack/prompts";
|
|
3449
|
-
|
|
3450
|
-
// src/cli/commands/postgres-docker.ts
|
|
3451
|
-
import { spawn as spawn4 } from "child_process";
|
|
3452
|
-
import { existsSync as existsSync3 } from "fs";
|
|
3453
|
-
import { dirname as dirname11, resolve as resolve12 } from "path";
|
|
3454
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3455
|
-
function resolveBundledComposeFile() {
|
|
3456
|
-
const here = dirname11(fileURLToPath2(import.meta.url));
|
|
3457
|
-
const candidates = [
|
|
3458
|
-
// installed package: dist/cli/commands/ -> root
|
|
3459
|
-
resolve12(here, "..", "..", "..", "docker-compose.yml"),
|
|
3460
|
-
// source layout: src/cli/commands/ -> root
|
|
3461
|
-
resolve12(here, "..", "..", "..", "..", "docker-compose.yml"),
|
|
3462
|
-
resolve12(here, "..", "..", "docker-compose.yml"),
|
|
3463
|
-
resolve12(process.cwd(), "docker-compose.yml")
|
|
3464
|
-
];
|
|
3465
|
-
for (const candidate of candidates) {
|
|
3466
|
-
if (existsSync3(candidate)) return candidate;
|
|
3467
|
-
}
|
|
3468
|
-
throw new Error(`Could not locate docker-compose.yml. Looked in:
|
|
3469
|
-
${candidates.join("\n ")}`);
|
|
3470
|
-
}
|
|
3471
|
-
async function runDockerCompose(args, options = {}) {
|
|
3472
|
-
const spawnImpl = options.spawnImpl ?? spawn4;
|
|
3473
|
-
const composeFile = resolveBundledComposeFile();
|
|
3474
|
-
const attempts = [
|
|
3475
|
-
{ kind: "v2", bin: "docker", args: ["compose", "-f", composeFile, ...args] },
|
|
3476
|
-
{ kind: "v1", bin: "docker-compose", args: ["-f", composeFile, ...args] }
|
|
3477
|
-
];
|
|
3478
|
-
let lastSpawnError = null;
|
|
3479
|
-
for (const attempt of attempts) {
|
|
3480
|
-
try {
|
|
3481
|
-
return await spawnOnce(spawnImpl, attempt);
|
|
3482
|
-
} catch (error) {
|
|
3483
|
-
const err = error;
|
|
3484
|
-
if (err.code !== "ENOENT") throw err;
|
|
3485
|
-
lastSpawnError = err;
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
throw new Error(
|
|
3489
|
-
`Could not find docker. Install Docker Desktop (or docker-compose v1) and ensure it is on your PATH. (${lastSpawnError?.message ?? "spawn ENOENT"})`
|
|
3490
|
-
);
|
|
3491
|
-
}
|
|
3492
|
-
function spawnOnce(spawnImpl, attempt) {
|
|
3493
|
-
return new Promise((resolvePromise, rejectPromise) => {
|
|
3494
|
-
const child = spawnImpl(attempt.bin, attempt.args, {
|
|
3495
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
3496
|
-
});
|
|
3497
|
-
let stdout = "";
|
|
3498
|
-
let stderr = "";
|
|
3499
|
-
child.stdout?.on("data", (chunk) => {
|
|
3500
|
-
stdout += String(chunk);
|
|
3501
|
-
});
|
|
3502
|
-
child.stderr?.on("data", (chunk) => {
|
|
3503
|
-
stderr += String(chunk);
|
|
3504
|
-
});
|
|
3505
|
-
child.on("error", (error) => {
|
|
3506
|
-
rejectPromise(error);
|
|
3507
|
-
});
|
|
3508
|
-
child.on("close", (code) => {
|
|
3509
|
-
resolvePromise({ code: code ?? 0, stdout, stderr });
|
|
3510
|
-
});
|
|
3511
|
-
});
|
|
3512
|
-
}
|
|
3513
|
-
async function postgresUp(options) {
|
|
3514
|
-
return runDockerCompose(["up", "-d"], options ?? {});
|
|
3515
|
-
}
|
|
3516
|
-
async function postgresDown(options) {
|
|
3517
|
-
return runDockerCompose(["down"], options ?? {});
|
|
3518
|
-
}
|
|
3519
|
-
async function postgresStatus(options) {
|
|
3520
|
-
return runDockerCompose(["ps"], options ?? {});
|
|
3521
|
-
}
|
|
3522
|
-
|
|
3523
|
-
// src/cli/commands/init-wizard.ts
|
|
3524
3507
|
function bail() {
|
|
3525
3508
|
log.warn("Aborted. No config was written.");
|
|
3526
3509
|
process.exit(1);
|
|
@@ -3540,6 +3523,7 @@ async function pingOnce(databaseUrl) {
|
|
|
3540
3523
|
}
|
|
3541
3524
|
}
|
|
3542
3525
|
async function runInitWizard() {
|
|
3526
|
+
const projectRoot = process.cwd();
|
|
3543
3527
|
const sigintHandler = () => bail();
|
|
3544
3528
|
process.on("SIGINT", sigintHandler);
|
|
3545
3529
|
try {
|
|
@@ -3562,7 +3546,7 @@ async function runInitWizard() {
|
|
|
3562
3546
|
const namespace = unwrap(
|
|
3563
3547
|
await text({
|
|
3564
3548
|
message: "Default namespace",
|
|
3565
|
-
initialValue: process.env.CODEBUDDY_NAMESPACE ??
|
|
3549
|
+
initialValue: process.env.CODEBUDDY_NAMESPACE ?? defaultNamespaceForCwd(projectRoot),
|
|
3566
3550
|
validate: (value) => value && /^[a-zA-Z0-9_.:-]+$/.test(value) ? void 0 : "Letters, digits, _ . : - only."
|
|
3567
3551
|
})
|
|
3568
3552
|
);
|
|
@@ -3585,7 +3569,7 @@ async function runInitWizard() {
|
|
|
3585
3569
|
if (result.code === 0) {
|
|
3586
3570
|
dockerSpinner.stop("Postgres container started.");
|
|
3587
3571
|
for (let attempt = 0; attempt < 10 && !connected; attempt++) {
|
|
3588
|
-
await new Promise((
|
|
3572
|
+
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
3589
3573
|
connected = await pingOnce(databaseUrl);
|
|
3590
3574
|
}
|
|
3591
3575
|
if (!connected) {
|
|
@@ -3638,6 +3622,7 @@ async function runInitWizard() {
|
|
|
3638
3622
|
try {
|
|
3639
3623
|
const install = await installClaudeEntry({
|
|
3640
3624
|
namespace,
|
|
3625
|
+
projectRoot,
|
|
3641
3626
|
hfToken,
|
|
3642
3627
|
databaseUrl
|
|
3643
3628
|
});
|
|
@@ -3773,7 +3758,7 @@ function registerMapCommands(program, runSafely2) {
|
|
|
3773
3758
|
}
|
|
3774
3759
|
|
|
3775
3760
|
// src/cli/commands/memory-review.ts
|
|
3776
|
-
import { spawn as
|
|
3761
|
+
import { spawn as spawn4 } from "child_process";
|
|
3777
3762
|
import { relative as relative3 } from "path";
|
|
3778
3763
|
import pc12 from "picocolors";
|
|
3779
3764
|
function registerMemoryCommands(program, runSafely2) {
|
|
@@ -3869,22 +3854,22 @@ function truncate(value, max) {
|
|
|
3869
3854
|
function openEditor(path) {
|
|
3870
3855
|
const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
|
|
3871
3856
|
return new Promise((resolvePromise, reject) => {
|
|
3872
|
-
const child =
|
|
3857
|
+
const child = spawn4(editor, [path], { stdio: "inherit" });
|
|
3873
3858
|
child.on("error", reject);
|
|
3874
3859
|
child.on("close", () => resolvePromise());
|
|
3875
3860
|
});
|
|
3876
3861
|
}
|
|
3877
3862
|
|
|
3878
3863
|
// src/cli/commands/models.ts
|
|
3879
|
-
import { existsSync as
|
|
3864
|
+
import { existsSync as existsSync3 } from "fs";
|
|
3880
3865
|
import { join as join15 } from "path";
|
|
3881
3866
|
import { spinner as spinner2 } from "@clack/prompts";
|
|
3882
3867
|
import pc13 from "picocolors";
|
|
3883
3868
|
|
|
3884
3869
|
// evals/fact-relevance.json
|
|
3885
3870
|
var fact_relevance_default = {
|
|
3886
|
-
version:
|
|
3887
|
-
note: "Task prompts vs durable project facts. Queries are paraphrased so most share few or no words with their fact; every unlisted (query, fact) pair is irrelevant.",
|
|
3871
|
+
version: 2,
|
|
3872
|
+
note: "Task prompts vs durable project facts. Queries are paraphrased so most share few or no words with their fact; every unlisted (query, fact) pair is irrelevant. Hard negatives share a subsystem with a relevant fact but do not answer its task. Queries alternate dev/test by position (even index = dev): floors are chosen on dev and reported on test.",
|
|
3888
3873
|
facts: {
|
|
3889
3874
|
cookie: "OAuth callback breaks unless the session cookie is SameSite=Lax; Strict drops it on the cross-site redirect.",
|
|
3890
3875
|
pool: "Postgres connections go through one bounded pool of 10; never open ad-hoc clients in request handlers.",
|
|
@@ -3905,43 +3890,174 @@ var fact_relevance_default = {
|
|
|
3905
3890
|
avatar: "Profile images are resized to 256px and stored as WebP in the media bucket.",
|
|
3906
3891
|
flags: "Feature flags are read once at boot; changing one requires a restart of the worker.",
|
|
3907
3892
|
pagination: "List endpoints use cursor pagination with an opaque base64url cursor of createdAt and id.",
|
|
3908
|
-
i18n: "UI strings live in locales/en.json; never hard-code user-facing text in components."
|
|
3893
|
+
i18n: "UI strings live in locales/en.json; never hard-code user-facing text in components.",
|
|
3894
|
+
cookieDomain: "Session cookies are scoped to the app subdomain; never set them on the apex domain.",
|
|
3895
|
+
poolMetrics: "Database pool metrics are exported to Prometheus under the codebuddy_pool_ prefix.",
|
|
3896
|
+
releaseNotes: "Release notes are drafted from merged pull request titles by the changelog script.",
|
|
3897
|
+
hookInstall: "Hooks are written to .claude/settings.json and merged idempotently with the user's own hooks.",
|
|
3898
|
+
migrationNaming: "Migration files are numbered by drizzle-kit; never rename or edit a migration that has been applied.",
|
|
3899
|
+
testsParallel: "Vitest runs test files in parallel, so every test must use its own temporary directory.",
|
|
3900
|
+
logsStderr: "Server logs go to stderr through pino; never log full request bodies.",
|
|
3901
|
+
retry5xx: "The HTTP client retries 5xx responses twice with jittered backoff.",
|
|
3902
|
+
dateFormat: "Dates in the UI are formatted with the user's locale through Intl.DateTimeFormat.",
|
|
3903
|
+
flagNames: "Feature flag names use kebab-case and are declared in flags.yaml."
|
|
3909
3904
|
},
|
|
3910
3905
|
queries: [
|
|
3911
3906
|
{
|
|
3912
3907
|
q: "users get bounced back to sign-in forever after the identity provider returns",
|
|
3913
3908
|
relevant: ["cookie"]
|
|
3914
3909
|
},
|
|
3915
|
-
{
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
{
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
{
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3910
|
+
{
|
|
3911
|
+
q: "handlers are exhausting connections to the database under load",
|
|
3912
|
+
relevant: ["pool"]
|
|
3913
|
+
},
|
|
3914
|
+
{
|
|
3915
|
+
q: "cut a new version and push the package to the registry",
|
|
3916
|
+
relevant: ["release"]
|
|
3917
|
+
},
|
|
3918
|
+
{
|
|
3919
|
+
q: "the injected block sometimes never shows up in the chat",
|
|
3920
|
+
relevant: ["hook"]
|
|
3921
|
+
},
|
|
3922
|
+
{
|
|
3923
|
+
q: "fresh database setup fails on the embedding column",
|
|
3924
|
+
relevant: ["migration"]
|
|
3925
|
+
},
|
|
3926
|
+
{
|
|
3927
|
+
q: "an API key ended up in a saved note",
|
|
3928
|
+
relevant: ["redaction"]
|
|
3929
|
+
},
|
|
3930
|
+
{
|
|
3931
|
+
q: "context is sent again after I switch tasks and come back",
|
|
3932
|
+
relevant: ["ledger"]
|
|
3933
|
+
},
|
|
3934
|
+
{
|
|
3935
|
+
q: "semantic code search crashes and the agent gets no files",
|
|
3936
|
+
relevant: ["zvec"]
|
|
3937
|
+
},
|
|
3938
|
+
{
|
|
3939
|
+
q: "why do the db tests not run on my machine",
|
|
3940
|
+
relevant: ["tests"]
|
|
3941
|
+
},
|
|
3942
|
+
{
|
|
3943
|
+
q: "module not found when importing a sibling ts file at runtime",
|
|
3944
|
+
relevant: ["esm"]
|
|
3945
|
+
},
|
|
3946
|
+
{
|
|
3947
|
+
q: "Claude Desktop says Unexpected token in the server response",
|
|
3948
|
+
relevant: ["stdout"]
|
|
3949
|
+
},
|
|
3950
|
+
{
|
|
3951
|
+
q: "the summarizer quietly stopped calling Groq in the afternoon",
|
|
3952
|
+
relevant: ["budget"]
|
|
3953
|
+
},
|
|
3954
|
+
{
|
|
3955
|
+
q: "my uncommitted changes vanished after another session ran",
|
|
3956
|
+
relevant: ["worktree"]
|
|
3957
|
+
},
|
|
3927
3958
|
{
|
|
3928
3959
|
q: "clients see too many requests errors during the import job",
|
|
3929
3960
|
relevant: ["rateLimit"]
|
|
3930
3961
|
},
|
|
3931
|
-
{
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
{
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
{
|
|
3940
|
-
|
|
3962
|
+
{
|
|
3963
|
+
q: "meeting times show up one hour off for users in Berlin",
|
|
3964
|
+
relevant: ["timezone"]
|
|
3965
|
+
},
|
|
3966
|
+
{
|
|
3967
|
+
q: "uploaded profile pictures look blurry",
|
|
3968
|
+
relevant: ["avatar"]
|
|
3969
|
+
},
|
|
3970
|
+
{
|
|
3971
|
+
q: "I toggled the new checkout switch but nothing changed",
|
|
3972
|
+
relevant: ["flags"]
|
|
3973
|
+
},
|
|
3974
|
+
{
|
|
3975
|
+
q: "infinite scroll repeats items on the second page",
|
|
3976
|
+
relevant: ["pagination"]
|
|
3977
|
+
},
|
|
3978
|
+
{
|
|
3979
|
+
q: "translate the onboarding screen to German",
|
|
3980
|
+
relevant: ["i18n"]
|
|
3981
|
+
},
|
|
3982
|
+
{
|
|
3983
|
+
q: "format the code before I commit",
|
|
3984
|
+
relevant: ["biome"]
|
|
3985
|
+
},
|
|
3986
|
+
{
|
|
3987
|
+
q: "make the sidebar collapsible",
|
|
3988
|
+
relevant: []
|
|
3989
|
+
},
|
|
3990
|
+
{
|
|
3991
|
+
q: "add dark mode to the dashboard",
|
|
3992
|
+
relevant: []
|
|
3993
|
+
},
|
|
3994
|
+
{
|
|
3995
|
+
q: "write a haiku about the project",
|
|
3996
|
+
relevant: []
|
|
3997
|
+
},
|
|
3998
|
+
{
|
|
3999
|
+
q: "rename the button label on the settings page",
|
|
4000
|
+
relevant: []
|
|
4001
|
+
},
|
|
4002
|
+
{
|
|
4003
|
+
q: "where do I declare a new feature flag",
|
|
4004
|
+
relevant: ["flagNames"]
|
|
4005
|
+
},
|
|
4006
|
+
{
|
|
4007
|
+
q: "show dates in the user's own language and order",
|
|
4008
|
+
relevant: ["dateFormat"]
|
|
4009
|
+
},
|
|
4010
|
+
{
|
|
4011
|
+
q: "can I tidy up the name of the 0004 migration file",
|
|
4012
|
+
relevant: ["migrationNaming"]
|
|
4013
|
+
},
|
|
4014
|
+
{
|
|
4015
|
+
q: "tests interfere with each other when the whole suite runs",
|
|
4016
|
+
relevant: ["testsParallel"]
|
|
4017
|
+
},
|
|
4018
|
+
{
|
|
4019
|
+
q: "where can I see how busy the connection pool is",
|
|
4020
|
+
relevant: ["poolMetrics"]
|
|
4021
|
+
},
|
|
4022
|
+
{
|
|
4023
|
+
q: "how is the text for the changelog produced",
|
|
4024
|
+
relevant: ["releaseNotes"]
|
|
4025
|
+
},
|
|
4026
|
+
{
|
|
4027
|
+
q: "the login cookie shows up on example.com instead of app.example.com",
|
|
4028
|
+
relevant: ["cookieDomain"]
|
|
4029
|
+
},
|
|
4030
|
+
{
|
|
4031
|
+
q: "is it fine to print the incoming payload for debugging",
|
|
4032
|
+
relevant: ["logsStderr"]
|
|
4033
|
+
},
|
|
4034
|
+
{
|
|
4035
|
+
q: "our hook setup appears twice in the Claude settings file",
|
|
4036
|
+
relevant: ["hookInstall"]
|
|
4037
|
+
},
|
|
4038
|
+
{
|
|
4039
|
+
q: "flaky upstream 502s should not fail the request on the first try",
|
|
4040
|
+
relevant: ["retry5xx"]
|
|
4041
|
+
},
|
|
4042
|
+
{
|
|
4043
|
+
q: "rewrite the marketing copy on the landing page",
|
|
4044
|
+
relevant: []
|
|
4045
|
+
},
|
|
4046
|
+
{
|
|
4047
|
+
q: "upgrade React to the next major version",
|
|
4048
|
+
relevant: []
|
|
4049
|
+
},
|
|
4050
|
+
{
|
|
4051
|
+
q: "add a CSV export button to the reports table",
|
|
4052
|
+
relevant: []
|
|
4053
|
+
}
|
|
3941
4054
|
]
|
|
3942
4055
|
};
|
|
3943
4056
|
|
|
3944
4057
|
// src/providers/calibration.ts
|
|
4058
|
+
function splitOf(index) {
|
|
4059
|
+
return index % 2 === 0 ? "dev" : "test";
|
|
4060
|
+
}
|
|
3945
4061
|
async function calibrateEmbedder(embed) {
|
|
3946
4062
|
const data = fact_relevance_default;
|
|
3947
4063
|
const factIds = Object.keys(data.facts);
|
|
@@ -3950,47 +4066,59 @@ async function calibrateEmbedder(embed) {
|
|
|
3950
4066
|
const dot = (a, b) => a.reduce((sum, value, index) => sum + value * (b[index] ?? 0), 0);
|
|
3951
4067
|
const scores = queryVectors.map((query) => factVectors.map((fact) => dot(query, fact)));
|
|
3952
4068
|
const relevant = (qi, fi) => data.queries[qi]?.relevant.includes(factIds[fi] ?? "") ?? false;
|
|
4069
|
+
const answerable = (qi) => (data.queries[qi]?.relevant.length ?? 0) > 0;
|
|
4070
|
+
const rows = (split) => scores.flatMap((row2, qi) => splitOf(qi) === split ? [{ row: row2, qi }] : []);
|
|
3953
4071
|
const positives = [];
|
|
3954
4072
|
const negatives = [];
|
|
3955
|
-
for (const [qi, row2] of scores.entries()) {
|
|
3956
|
-
for (const [fi, score] of row2.entries()) (relevant(qi, fi) ? positives : negatives).push(score);
|
|
3957
|
-
}
|
|
3958
|
-
const auc = positives.reduce((wins, p) => wins + negatives.filter((n) => p > n).length, 0) / (positives.length * negatives.length);
|
|
3959
4073
|
let hits = 0;
|
|
3960
4074
|
let reciprocal = 0;
|
|
3961
|
-
let
|
|
3962
|
-
for (const
|
|
3963
|
-
|
|
3964
|
-
answerable
|
|
4075
|
+
let answered = 0;
|
|
4076
|
+
for (const { row: row2, qi } of rows("test")) {
|
|
4077
|
+
for (const [fi, score] of row2.entries()) (relevant(qi, fi) ? positives : negatives).push(score);
|
|
4078
|
+
if (!answerable(qi)) continue;
|
|
4079
|
+
answered += 1;
|
|
3965
4080
|
const order = row2.map((score, fi) => ({ score, fi })).sort((a, b) => b.score - a.score);
|
|
3966
4081
|
const rank = order.findIndex(({ fi }) => relevant(qi, fi)) + 1;
|
|
3967
4082
|
if (rank === 1) hits += 1;
|
|
3968
4083
|
reciprocal += 1 / rank;
|
|
3969
4084
|
}
|
|
3970
|
-
const
|
|
4085
|
+
const auc = positives.reduce((wins, p) => wins + negatives.filter((n) => p > n).length, 0) / (positives.length * negatives.length);
|
|
4086
|
+
const at = (floor, split = "test") => {
|
|
3971
4087
|
let tp = 0;
|
|
3972
4088
|
let fp = 0;
|
|
4089
|
+
let relevantPairs = 0;
|
|
3973
4090
|
let abstained = 0;
|
|
3974
4091
|
let unrelated = 0;
|
|
3975
|
-
for (const
|
|
4092
|
+
for (const { row: row2, qi } of rows(split)) {
|
|
4093
|
+
relevantPairs += data.queries[qi]?.relevant.length ?? 0;
|
|
3976
4094
|
const admitted = row2.flatMap((score, fi) => score >= floor ? [fi] : []);
|
|
3977
4095
|
for (const fi of admitted) {
|
|
3978
4096
|
if (relevant(qi, fi)) tp += 1;
|
|
3979
4097
|
else fp += 1;
|
|
3980
4098
|
}
|
|
3981
|
-
if (!
|
|
4099
|
+
if (!answerable(qi)) {
|
|
3982
4100
|
unrelated += 1;
|
|
3983
4101
|
if (admitted.length === 0) abstained += 1;
|
|
3984
4102
|
}
|
|
3985
4103
|
}
|
|
3986
4104
|
const precision = tp + fp === 0 ? 1 : tp / (tp + fp);
|
|
3987
|
-
const recall = tp /
|
|
4105
|
+
const recall = relevantPairs === 0 ? 0 : tp / relevantPairs;
|
|
3988
4106
|
const f05 = precision + recall === 0 ? 0 : 1.25 * precision * recall / (0.25 * precision + recall);
|
|
3989
|
-
return { floor, precision, recall, f05, abstain: abstained / unrelated };
|
|
4107
|
+
return { floor, precision, recall, f05, abstain: unrelated === 0 ? 1 : abstained / unrelated };
|
|
3990
4108
|
};
|
|
3991
|
-
const sweep = Array.from(
|
|
4109
|
+
const sweep = Array.from(
|
|
4110
|
+
{ length: 96 },
|
|
4111
|
+
(_, i) => at(Math.round((0.05 + i * 0.01) * 100) / 100, "dev")
|
|
4112
|
+
);
|
|
3992
4113
|
const best = sweep.reduce((left, right) => right.f05 > left.f05 ? right : left);
|
|
3993
|
-
return {
|
|
4114
|
+
return {
|
|
4115
|
+
auc,
|
|
4116
|
+
recallAt1: answered === 0 ? 0 : hits / answered,
|
|
4117
|
+
mrr: answered === 0 ? 0 : reciprocal / answered,
|
|
4118
|
+
best,
|
|
4119
|
+
test: at(best.floor, "test"),
|
|
4120
|
+
at
|
|
4121
|
+
};
|
|
3994
4122
|
}
|
|
3995
4123
|
|
|
3996
4124
|
// src/cli/commands/models.ts
|
|
@@ -4008,7 +4136,7 @@ async function withSpinner(label, work, done) {
|
|
|
4008
4136
|
progress.stop(done(value));
|
|
4009
4137
|
return value;
|
|
4010
4138
|
} catch (error) {
|
|
4011
|
-
progress.
|
|
4139
|
+
progress.error(pc13.red(`\u2717 ${label}`));
|
|
4012
4140
|
throw error;
|
|
4013
4141
|
}
|
|
4014
4142
|
}
|
|
@@ -4017,7 +4145,7 @@ function keyPresent(provider, apiKey) {
|
|
|
4017
4145
|
}
|
|
4018
4146
|
function localModelDownloaded(id, revision) {
|
|
4019
4147
|
const dir = join15(modelCacheDir(), id, ...revision ? [revision] : []);
|
|
4020
|
-
return
|
|
4148
|
+
return existsSync3(join15(dir, "onnx", "model_quantized.onnx"));
|
|
4021
4149
|
}
|
|
4022
4150
|
async function vectorCounts(postgresUrl, namespace, space) {
|
|
4023
4151
|
const client = createDatabaseClient({ postgresUrl, maxConnections: 1, connectTimeoutSeconds: 3 });
|
|
@@ -4049,7 +4177,12 @@ async function printStatus() {
|
|
|
4049
4177
|
const next = [];
|
|
4050
4178
|
console.log(pc13.bold("Embeddings"));
|
|
4051
4179
|
console.log(row("provider", `${provider.type} ${pc13.dim(model)}`));
|
|
4052
|
-
if (provider.type === "local") {
|
|
4180
|
+
if (provider.type === "local" && !localRuntimeInstalled()) {
|
|
4181
|
+
console.log(
|
|
4182
|
+
row("runtime", warn("@huggingface/transformers is not installed: dense recall is off"))
|
|
4183
|
+
);
|
|
4184
|
+
next.push("npm i -g @huggingface/transformers");
|
|
4185
|
+
} else if (provider.type === "local") {
|
|
4053
4186
|
const ready = localModelDownloaded(LOCAL_EMBEDDING_MODEL.id, LOCAL_EMBEDDING_MODEL.revision);
|
|
4054
4187
|
console.log(
|
|
4055
4188
|
row(
|
|
@@ -4185,7 +4318,7 @@ Examples:
|
|
|
4185
4318
|
);
|
|
4186
4319
|
}
|
|
4187
4320
|
if (!missingKey) {
|
|
4188
|
-
syncInBackground(process.cwd());
|
|
4321
|
+
syncInBackground(process.cwd(), true);
|
|
4189
4322
|
console.log(
|
|
4190
4323
|
pc13.dim(" Re-embedding existing memory in the background (codebuddy hooks sync).")
|
|
4191
4324
|
);
|
|
@@ -4225,7 +4358,7 @@ before keeping one on. A reranker never admits a fact, it only orders them.`
|
|
|
4225
4358
|
});
|
|
4226
4359
|
models.command("pull").description("Download the local models now instead of on first use.").action(async () => {
|
|
4227
4360
|
await runSafely2(async () => {
|
|
4228
|
-
const { LocalModelProvider, rerankLocally } = await import("./local-
|
|
4361
|
+
const { LocalModelProvider, rerankLocally } = await import("./local-5MZURLCZ.js");
|
|
4229
4362
|
const file = await readConfigFile();
|
|
4230
4363
|
let started = Date.now();
|
|
4231
4364
|
await withSpinner(
|
|
@@ -4261,13 +4394,13 @@ before keeping one on. A reranker never admits a fact, it only orders them.`
|
|
|
4261
4394
|
console.log(
|
|
4262
4395
|
row(
|
|
4263
4396
|
"ranking",
|
|
4264
|
-
`AUC ${result.auc.toFixed(3)} \xB7 right fact first ${pct(result.recallAt1)}`
|
|
4397
|
+
`AUC ${result.auc.toFixed(3)} \xB7 right fact first ${pct(result.recallAt1)} ${pc13.dim("(held-out tasks)")}`
|
|
4265
4398
|
)
|
|
4266
4399
|
);
|
|
4267
4400
|
console.log(
|
|
4268
4401
|
row(
|
|
4269
4402
|
"floor",
|
|
4270
|
-
`${result.best.floor}: precision ${pct(result.
|
|
4403
|
+
`${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)")}`
|
|
4271
4404
|
)
|
|
4272
4405
|
);
|
|
4273
4406
|
if (opts.dryRun) return;
|
|
@@ -4282,7 +4415,7 @@ before keeping one on. A reranker never admits a fact, it only orders them.`
|
|
|
4282
4415
|
}
|
|
4283
4416
|
|
|
4284
4417
|
// src/cli/commands/plan.ts
|
|
4285
|
-
import { spawn as
|
|
4418
|
+
import { spawn as spawn5 } from "child_process";
|
|
4286
4419
|
import { relative as relative4 } from "path";
|
|
4287
4420
|
import pc14 from "picocolors";
|
|
4288
4421
|
function makeLifecycle(cwd = process.cwd()) {
|
|
@@ -4344,15 +4477,15 @@ function renderPlan(plan) {
|
|
|
4344
4477
|
}
|
|
4345
4478
|
function openEditor2(path) {
|
|
4346
4479
|
const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
|
|
4347
|
-
return new Promise((
|
|
4348
|
-
const child =
|
|
4480
|
+
return new Promise((resolve13, reject) => {
|
|
4481
|
+
const child = spawn5(editor, [path], { stdio: "inherit" });
|
|
4349
4482
|
child.on("error", reject);
|
|
4350
|
-
child.on("close", () =>
|
|
4483
|
+
child.on("close", () => resolve13());
|
|
4351
4484
|
});
|
|
4352
4485
|
}
|
|
4353
4486
|
function runGit(args) {
|
|
4354
|
-
return new Promise((
|
|
4355
|
-
const child =
|
|
4487
|
+
return new Promise((resolve13, reject) => {
|
|
4488
|
+
const child = spawn5("git", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
4356
4489
|
let stdout = "";
|
|
4357
4490
|
let stderr = "";
|
|
4358
4491
|
child.stdout.on("data", (c) => {
|
|
@@ -4362,7 +4495,7 @@ function runGit(args) {
|
|
|
4362
4495
|
stderr += String(c);
|
|
4363
4496
|
});
|
|
4364
4497
|
child.on("error", reject);
|
|
4365
|
-
child.on("close", (code) =>
|
|
4498
|
+
child.on("close", (code) => resolve13({ code: code ?? 0, stdout, stderr }));
|
|
4366
4499
|
});
|
|
4367
4500
|
}
|
|
4368
4501
|
function registerPlanCommands(program, runSafely2) {
|
|
@@ -4677,7 +4810,7 @@ function severityBadge2(severity) {
|
|
|
4677
4810
|
|
|
4678
4811
|
// src/cli/commands/symbols.ts
|
|
4679
4812
|
import { readFile as readFile13 } from "fs/promises";
|
|
4680
|
-
import { resolve as
|
|
4813
|
+
import { resolve as resolve12 } from "path";
|
|
4681
4814
|
import pc18 from "picocolors";
|
|
4682
4815
|
function registerSymbolsCommand(program, runSafely2) {
|
|
4683
4816
|
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) => {
|
|
@@ -4686,7 +4819,7 @@ function registerSymbolsCommand(program, runSafely2) {
|
|
|
4686
4819
|
console.log(pc18.dim(`no symbol extraction for ${path} (unsupported language)`));
|
|
4687
4820
|
return;
|
|
4688
4821
|
}
|
|
4689
|
-
const content = await readFile13(
|
|
4822
|
+
const content = await readFile13(resolve12(path), "utf8");
|
|
4690
4823
|
const table = extractSymbolTable(content);
|
|
4691
4824
|
if (opts.json) {
|
|
4692
4825
|
console.log(JSON.stringify({ path, symbols: table }, null, 2));
|
|
@@ -4716,7 +4849,7 @@ import pc19 from "picocolors";
|
|
|
4716
4849
|
// src/core/global-config.ts
|
|
4717
4850
|
import { chmod, mkdir as mkdir8, readFile as readFile14, writeFile as writeFile3 } from "fs/promises";
|
|
4718
4851
|
import { homedir as homedir3 } from "os";
|
|
4719
|
-
import { dirname as
|
|
4852
|
+
import { dirname as dirname11, join as join16 } from "path";
|
|
4720
4853
|
import { z as z2 } from "zod";
|
|
4721
4854
|
var GLOBAL_DIR = ".codebuddy";
|
|
4722
4855
|
var GLOBAL_FILE = "global.json";
|
|
@@ -4743,7 +4876,7 @@ async function readGlobalConfig(home = homedir3()) {
|
|
|
4743
4876
|
}
|
|
4744
4877
|
async function writeGlobalConfig(next, home = homedir3()) {
|
|
4745
4878
|
const path = globalConfigPath(home);
|
|
4746
|
-
await mkdir8(
|
|
4879
|
+
await mkdir8(dirname11(path), { recursive: true, mode: 448 });
|
|
4747
4880
|
await writeFile3(path, `${JSON.stringify(next, null, 2)}
|
|
4748
4881
|
`, { mode: 384 });
|
|
4749
4882
|
await chmod(path, 384);
|
|
@@ -4756,32 +4889,6 @@ async function mergeGlobalConfig(patch, home = homedir3()) {
|
|
|
4756
4889
|
return { path, merged };
|
|
4757
4890
|
}
|
|
4758
4891
|
|
|
4759
|
-
// src/cli/commands/docker-autostart.ts
|
|
4760
|
-
import { spawn as spawn7 } from "child_process";
|
|
4761
|
-
async function isDockerDaemonRunning() {
|
|
4762
|
-
return new Promise((resolve14) => {
|
|
4763
|
-
const child = spawn7("docker", ["info"], { stdio: "ignore" });
|
|
4764
|
-
child.on("error", () => resolve14(false));
|
|
4765
|
-
child.on("close", (code) => resolve14(code === 0));
|
|
4766
|
-
});
|
|
4767
|
-
}
|
|
4768
|
-
async function tryStartDockerDesktop() {
|
|
4769
|
-
if (process.platform !== "darwin") return { started: false };
|
|
4770
|
-
return new Promise((resolve14) => {
|
|
4771
|
-
const child = spawn7("open", ["-ga", "Docker"], { stdio: "ignore" });
|
|
4772
|
-
child.on("error", () => resolve14({ started: false }));
|
|
4773
|
-
child.on("close", (code) => resolve14({ started: code === 0 }));
|
|
4774
|
-
});
|
|
4775
|
-
}
|
|
4776
|
-
async function waitForDockerDaemon(timeoutMs = 6e4) {
|
|
4777
|
-
const deadline = Date.now() + timeoutMs;
|
|
4778
|
-
while (Date.now() < deadline) {
|
|
4779
|
-
if (await isDockerDaemonRunning()) return true;
|
|
4780
|
-
await new Promise((resolve14) => setTimeout(resolve14, 1e3));
|
|
4781
|
-
}
|
|
4782
|
-
return false;
|
|
4783
|
-
}
|
|
4784
|
-
|
|
4785
4892
|
// src/cli/commands/use-command.ts
|
|
4786
4893
|
function bail2() {
|
|
4787
4894
|
log2.warn("Aborted.");
|
|
@@ -4812,6 +4919,7 @@ async function runUseCommand(options = {}) {
|
|
|
4812
4919
|
const folderName = basename2(process.cwd());
|
|
4813
4920
|
const namespace = sanitizeNamespace(options.namespace ?? folderName);
|
|
4814
4921
|
await initProjectScaffold();
|
|
4922
|
+
if (options.namespace === void 0) await migrateLegacyNamespace();
|
|
4815
4923
|
const graphifyEnabled = options.graphify ?? unwrap2(
|
|
4816
4924
|
await confirm2({
|
|
4817
4925
|
message: "Set up Graphify for richer architecture context?",
|
|
@@ -4915,7 +5023,7 @@ Namespace: ${pc19.bold(namespace)}`,
|
|
|
4915
5023
|
if (result.code === 0) {
|
|
4916
5024
|
composeSpinner.stop("Postgres container started.");
|
|
4917
5025
|
for (let attempt = 0; attempt < 12 && !connected; attempt++) {
|
|
4918
|
-
await new Promise((
|
|
5026
|
+
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
4919
5027
|
connected = await pingOnce2(databaseUrl);
|
|
4920
5028
|
}
|
|
4921
5029
|
if (!connected) {
|
|
@@ -5326,7 +5434,7 @@ function createCli() {
|
|
|
5326
5434
|
console.log(`Claude Desktop config: ${result.path}`);
|
|
5327
5435
|
for (const entry of result.entries) {
|
|
5328
5436
|
console.log(
|
|
5329
|
-
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl
|
|
5437
|
+
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl ? String(redactSecrets(entry.databaseUrl)) : "?"}`
|
|
5330
5438
|
);
|
|
5331
5439
|
}
|
|
5332
5440
|
});
|
|
@@ -5371,7 +5479,7 @@ function createCli() {
|
|
|
5371
5479
|
console.log(`Codex config: ${result.path}`);
|
|
5372
5480
|
for (const entry of result.entries) {
|
|
5373
5481
|
console.log(
|
|
5374
|
-
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl
|
|
5482
|
+
` ${entry.key} namespace=${entry.namespace ?? "?"} db=${entry.databaseUrl ? String(redactSecrets(entry.databaseUrl)) : "?"}`
|
|
5375
5483
|
);
|
|
5376
5484
|
}
|
|
5377
5485
|
});
|
|
@@ -5557,6 +5665,9 @@ function printDoctor(report) {
|
|
|
5557
5665
|
console.log(
|
|
5558
5666
|
` runtime=${report.namespace.runtime ?? "unset"} default=${report.namespace.expectedDefault}`
|
|
5559
5667
|
);
|
|
5668
|
+
if (report.namespace.migrated) {
|
|
5669
|
+
console.log(` migrated legacy namespace "default" to "${report.namespace.migrated}"`);
|
|
5670
|
+
}
|
|
5560
5671
|
if (report.namespace.warning) console.log(` ${report.namespace.warning}`);
|
|
5561
5672
|
console.log(
|
|
5562
5673
|
`vectors: ${report.vectors.count} index=${report.vectors.index ?? "missing"} tuning=${report.vectors.needsTuning ? "recommended" : "not-needed"}`
|
|
@@ -5586,9 +5697,12 @@ function printDbDoctor(report) {
|
|
|
5586
5697
|
if (report.pgvector.error) console.log(` ${report.pgvector.error}`);
|
|
5587
5698
|
console.log(`namespace: ${report.namespace.ok ? ok2 : warn2}`);
|
|
5588
5699
|
console.log(` runtime=${report.namespace.runtime ?? "unset"}`);
|
|
5700
|
+
if (report.namespace.migrated) {
|
|
5701
|
+
console.log(` migrated legacy namespace "default" to "${report.namespace.migrated}"`);
|
|
5702
|
+
}
|
|
5589
5703
|
if (report.namespace.warning) console.log(` ${report.namespace.warning}`);
|
|
5590
5704
|
}
|
|
5591
5705
|
export {
|
|
5592
5706
|
createCli
|
|
5593
5707
|
};
|
|
5594
|
-
//# sourceMappingURL=main-
|
|
5708
|
+
//# sourceMappingURL=main-MTBQZGJV.js.map
|