@orquentra/codebuddy 0.0.0-stage → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/ARCHITECTURE.md +269 -0
  2. package/CLAUDE_CODEX.md +433 -0
  3. package/LICENSE +21 -0
  4. package/README.md +55 -2
  5. package/WORKFLOW.md +152 -0
  6. package/dist/chunk-3ZELDCR3.js +204 -0
  7. package/dist/chunk-3ZELDCR3.js.map +1 -0
  8. package/dist/chunk-5OWZVZSO.js +476 -0
  9. package/dist/chunk-5OWZVZSO.js.map +1 -0
  10. package/dist/chunk-DSN5CEHO.js +175 -0
  11. package/dist/chunk-DSN5CEHO.js.map +1 -0
  12. package/dist/chunk-GDJH7XJC.js +119 -0
  13. package/dist/chunk-GDJH7XJC.js.map +1 -0
  14. package/dist/chunk-IBMJYIEP.js +1578 -0
  15. package/dist/chunk-IBMJYIEP.js.map +1 -0
  16. package/dist/chunk-IE2OUO54.js +199 -0
  17. package/dist/chunk-IE2OUO54.js.map +1 -0
  18. package/dist/chunk-IHQM2ZDV.js +19 -0
  19. package/dist/chunk-IHQM2ZDV.js.map +1 -0
  20. package/dist/chunk-ITGRANYW.js +63 -0
  21. package/dist/chunk-ITGRANYW.js.map +1 -0
  22. package/dist/chunk-K63EOA4B.js +416 -0
  23. package/dist/chunk-K63EOA4B.js.map +1 -0
  24. package/dist/chunk-OLFCOR4U.js +8580 -0
  25. package/dist/chunk-OLFCOR4U.js.map +1 -0
  26. package/dist/chunk-PQK3GKZH.js +98 -0
  27. package/dist/chunk-PQK3GKZH.js.map +1 -0
  28. package/dist/chunk-PYLH4MH5.js +34 -0
  29. package/dist/chunk-PYLH4MH5.js.map +1 -0
  30. package/dist/chunk-PZ5AY32C.js +10 -0
  31. package/dist/chunk-PZ5AY32C.js.map +1 -0
  32. package/dist/chunk-TI5TQD6D.js +324 -0
  33. package/dist/chunk-TI5TQD6D.js.map +1 -0
  34. package/dist/chunk-WHZSVY2L.js +144 -0
  35. package/dist/chunk-WHZSVY2L.js.map +1 -0
  36. package/dist/cli/index.d.ts +1 -0
  37. package/dist/cli/index.js +15 -0
  38. package/dist/cli/index.js.map +1 -0
  39. package/dist/codebuddy-D2xJ6hFk.d.ts +841 -0
  40. package/dist/config-S2TULOMK.js +11 -0
  41. package/dist/config-S2TULOMK.js.map +1 -0
  42. package/dist/index.d.ts +2527 -0
  43. package/dist/index.js +116 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/langgraph/index.d.ts +53 -0
  46. package/dist/langgraph/index.js +143 -0
  47. package/dist/langgraph/index.js.map +1 -0
  48. package/dist/lean-command-D6TZJEFX.js +13 -0
  49. package/dist/lean-command-D6TZJEFX.js.map +1 -0
  50. package/dist/main-BFDVQHKO.js +4575 -0
  51. package/dist/main-BFDVQHKO.js.map +1 -0
  52. package/dist/memory-NIBFAMY4.js +57 -0
  53. package/dist/memory-NIBFAMY4.js.map +1 -0
  54. package/dist/pretool-command-MQQ2UNQM.js +10 -0
  55. package/dist/pretool-command-MQQ2UNQM.js.map +1 -0
  56. package/dist/rerank-Q7MIFNKA.js +60 -0
  57. package/dist/rerank-Q7MIFNKA.js.map +1 -0
  58. package/dist/summaries-TSE44KUQ.js +18 -0
  59. package/dist/summaries-TSE44KUQ.js.map +1 -0
  60. package/dist/zvec-F27AR357.js +23 -0
  61. package/dist/zvec-F27AR357.js.map +1 -0
  62. package/docker-compose.yml +20 -0
  63. package/examples/claude-code/README.md +67 -0
  64. package/examples/claude-desktop/README.md +54 -0
  65. package/examples/claude-desktop/claude_desktop_config.json +13 -0
  66. package/examples/langgraph-agent/README.md +32 -0
  67. package/examples/langgraph-agent/index.ts +71 -0
  68. package/examples/multi-agent-handoff/README.md +35 -0
  69. package/examples/multi-agent-handoff/index.ts +68 -0
  70. package/package.json +108 -4
  71. package/src/db/migrations/0000_cultured_satana.sql +144 -0
  72. package/src/db/migrations/0001_embedding_lease.sql +3 -0
  73. package/src/db/migrations/0002_embedding_lease_token.sql +1 -0
  74. package/src/db/migrations/0003_embedding_space.sql +9 -0
  75. package/src/db/migrations/0004_markdown_reconcile.sql +5 -0
  76. package/src/db/migrations/0005_fact_propositions.sql +1 -0
  77. package/src/db/migrations/meta/0000_snapshot.json +1169 -0
  78. package/src/db/migrations/meta/0002_snapshot.json +1181 -0
  79. package/src/db/migrations/meta/0003_snapshot.json +1214 -0
  80. package/src/db/migrations/meta/0004_snapshot.json +1225 -0
  81. package/src/db/migrations/meta/0005_snapshot.json +1231 -0
  82. package/src/db/migrations/meta/_journal.json +48 -0
@@ -0,0 +1,57 @@
1
+ import {
2
+ memoryCandidateSchema
3
+ } from "./chunk-IHQM2ZDV.js";
4
+ import {
5
+ chatJson
6
+ } from "./chunk-IE2OUO54.js";
7
+ import {
8
+ redactSensitive
9
+ } from "./chunk-GDJH7XJC.js";
10
+ import {
11
+ resolveLlmConfig
12
+ } from "./chunk-ITGRANYW.js";
13
+ import "./chunk-K63EOA4B.js";
14
+ import "./chunk-PZ5AY32C.js";
15
+
16
+ // src/llm/memory.ts
17
+ import { z } from "zod";
18
+ var TIMEOUT_MS = 2e4;
19
+ var schema = z.object({ candidates: z.array(memoryCandidateSchema).max(10) });
20
+ var SYSTEM = [
21
+ "You turn the summary of one coding turn into durable project memory.",
22
+ 'Answer with JSON only: {"candidates":[{"class":"fact|decision|incident|note|ignored","content":"...","subject":"...","predicate":"...","object":"...","confidence":0.0,"paths":["..."],"severity":null}]}.',
23
+ "Keep only what will still be true and useful in a later session: decisions, confirmed bugs and their causes, project facts.",
24
+ "Use only paths named in the input. Confidence below 0.7 for anything uncertain. Chatter is class ignored.",
25
+ "Never include secrets."
26
+ ].join(" ");
27
+ function createLlmMemoryExtractor(root, config) {
28
+ return {
29
+ async extract(input) {
30
+ const result = await chatJson(config, {
31
+ system: SYSTEM,
32
+ user: JSON.stringify({
33
+ summary: redactSensitive(input.summary),
34
+ changedFiles: (input.changedFiles ?? []).map(redactSensitive),
35
+ verification: (input.verification ?? []).map(redactSensitive)
36
+ }),
37
+ schema,
38
+ maxTokens: 800,
39
+ deadlineMs: TIMEOUT_MS,
40
+ purpose: "background",
41
+ repositoryRoot: root
42
+ });
43
+ if (!result.ok) throw new Error(`llm memory extraction: ${result.reason}`);
44
+ return result.value.candidates;
45
+ }
46
+ };
47
+ }
48
+ async function llmCaptureOptions(root, env = process.env) {
49
+ const config = await resolveLlmConfig(root, env);
50
+ if (!config.enabled || !config.features.memory) return {};
51
+ return { extractor: createLlmMemoryExtractor(root, config), retries: 0 };
52
+ }
53
+ export {
54
+ createLlmMemoryExtractor,
55
+ llmCaptureOptions
56
+ };
57
+ //# sourceMappingURL=memory-NIBFAMY4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/llm/memory.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { MemoryExtractor } from \"../memory-extract/llm.js\";\nimport { redactSensitive } from \"../memory-extract/sensitive.js\";\nimport { type ExtractionInput, memoryCandidateSchema } from \"../memory-extract/types.js\";\nimport { chatJson } from \"./client.js\";\nimport { type EnabledLlmConfig, resolveLlmConfig } from \"./config.js\";\n\n/**\n * Optional BYOK memory extraction through the existing `MemoryExtractor`\n * seam. Output must match `memoryCandidateSchema` and then passes the same\n * gate as deterministic candidates (sensitive scan, confidence, review);\n * any failure falls back to deterministic extraction.\n */\nconst TIMEOUT_MS = 20_000;\nconst schema = z.object({ candidates: z.array(memoryCandidateSchema).max(10) });\n\nconst SYSTEM = [\n \"You turn the summary of one coding turn into durable project memory.\",\n 'Answer with JSON only: {\"candidates\":[{\"class\":\"fact|decision|incident|note|ignored\",\"content\":\"...\",\"subject\":\"...\",\"predicate\":\"...\",\"object\":\"...\",\"confidence\":0.0,\"paths\":[\"...\"],\"severity\":null}]}.',\n \"Keep only what will still be true and useful in a later session: decisions, confirmed bugs and their causes, project facts.\",\n \"Use only paths named in the input. Confidence below 0.7 for anything uncertain. Chatter is class ignored.\",\n \"Never include secrets.\",\n].join(\" \");\n\nexport function createLlmMemoryExtractor(root: string, config: EnabledLlmConfig): MemoryExtractor {\n return {\n async extract(input: ExtractionInput) {\n const result = await chatJson(config, {\n system: SYSTEM,\n user: JSON.stringify({\n summary: redactSensitive(input.summary),\n changedFiles: (input.changedFiles ?? []).map(redactSensitive),\n verification: (input.verification ?? []).map(redactSensitive),\n }),\n schema,\n maxTokens: 800,\n deadlineMs: TIMEOUT_MS,\n purpose: \"background\",\n repositoryRoot: root,\n });\n if (!result.ok) throw new Error(`llm memory extraction: ${result.reason}`);\n return result.value.candidates;\n },\n };\n}\n\n/** Extra `captureAfterTurn` options when the memory feature is on: one attempt, then deterministic. */\nexport async function llmCaptureOptions(\n root: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<{ extractor?: MemoryExtractor; retries?: number }> {\n const config = await resolveLlmConfig(root, env);\n if (!config.enabled || !config.features.memory) return {};\n return { extractor: createLlmMemoryExtractor(root, config), retries: 0 };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS,SAAS;AAalB,IAAM,aAAa;AACnB,IAAM,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,EAAE,IAAI,EAAE,EAAE,CAAC;AAE9E,IAAM,SAAS;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAEH,SAAS,yBAAyB,MAAc,QAA2C;AAChG,SAAO;AAAA,IACL,MAAM,QAAQ,OAAwB;AACpC,YAAM,SAAS,MAAM,SAAS,QAAQ;AAAA,QACpC,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS,gBAAgB,MAAM,OAAO;AAAA,UACtC,eAAe,MAAM,gBAAgB,CAAC,GAAG,IAAI,eAAe;AAAA,UAC5D,eAAe,MAAM,gBAAgB,CAAC,GAAG,IAAI,eAAe;AAAA,QAC9D,CAAC;AAAA,QACD;AAAA,QACA,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,gBAAgB;AAAA,MAClB,CAAC;AACD,UAAI,CAAC,OAAO,GAAI,OAAM,IAAI,MAAM,0BAA0B,OAAO,MAAM,EAAE;AACzE,aAAO,OAAO,MAAM;AAAA,IACtB;AAAA,EACF;AACF;AAGA,eAAsB,kBACpB,MACA,MAAyB,QAAQ,KAC2B;AAC5D,QAAM,SAAS,MAAM,iBAAiB,MAAM,GAAG;AAC/C,MAAI,CAAC,OAAO,WAAW,CAAC,OAAO,SAAS,OAAQ,QAAO,CAAC;AACxD,SAAO,EAAE,WAAW,yBAAyB,MAAM,MAAM,GAAG,SAAS,EAAE;AACzE;","names":[]}
@@ -0,0 +1,10 @@
1
+ import {
2
+ runPreToolHookCommand
3
+ } from "./chunk-WHZSVY2L.js";
4
+ import "./chunk-PYLH4MH5.js";
5
+ import "./chunk-PQK3GKZH.js";
6
+ import "./chunk-PZ5AY32C.js";
7
+ export {
8
+ runPreToolHookCommand
9
+ };
10
+ //# sourceMappingURL=pretool-command-MQQ2UNQM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,60 @@
1
+ import {
2
+ chatJson
3
+ } from "./chunk-IE2OUO54.js";
4
+ import {
5
+ redactSensitive
6
+ } from "./chunk-GDJH7XJC.js";
7
+ import "./chunk-ITGRANYW.js";
8
+ import "./chunk-K63EOA4B.js";
9
+ import "./chunk-PZ5AY32C.js";
10
+
11
+ // src/llm/rerank.ts
12
+ import { createHash } from "crypto";
13
+ import { z } from "zod";
14
+ var RERANK_PROMPT_VERSION = 1;
15
+ var LIMITS = { candidates: 15, picks: 3, signatures: 5, reason: 80, maxTokens: 300 };
16
+ var schema = z.object({
17
+ files: z.array(
18
+ z.object({
19
+ path: z.string(),
20
+ symbols: z.array(z.string()).default([]),
21
+ reason: z.string().default("")
22
+ })
23
+ ).default([]),
24
+ abstain: z.boolean().default(false)
25
+ });
26
+ var SYSTEM = [
27
+ "You pick the source files a coding agent must open for a task.",
28
+ 'Answer with JSON only: {"files":[{"path":"...","symbols":["..."],"reason":"..."}],"abstain":false}.',
29
+ `Choose at most ${LIMITS.picks} files, best first, only from the candidates given;`,
30
+ "name the functions or classes to look at when you can (from the listed signatures);",
31
+ "reason: a few words. If no candidate fits the task, answer with an empty files list and abstain true."
32
+ ].join(" ");
33
+ async function rerankCandidates(root, config, task, candidates, deadlineMs) {
34
+ const sent = candidates.slice(0, LIMITS.candidates).map((candidate) => ({
35
+ path: candidate.path,
36
+ summary: redactSensitive(candidate.summary),
37
+ signatures: candidate.signatures.slice(0, LIMITS.signatures).map(redactSensitive)
38
+ }));
39
+ const user = JSON.stringify({ task: redactSensitive(task), candidates: sent });
40
+ const result = await chatJson(config, {
41
+ system: SYSTEM,
42
+ user,
43
+ schema,
44
+ maxTokens: LIMITS.maxTokens,
45
+ deadlineMs,
46
+ purpose: "prompt",
47
+ repositoryRoot: root,
48
+ cacheKey: createHash("sha256").update(`rerank:${RERANK_PROMPT_VERSION}:${user}`).digest("hex")
49
+ });
50
+ if (!result.ok) return result;
51
+ const allowed = new Set(sent.map((candidate) => candidate.path));
52
+ const seen = /* @__PURE__ */ new Set();
53
+ const files = result.value.files.filter((file) => allowed.has(file.path) && !seen.has(file.path) && seen.add(file.path)).slice(0, LIMITS.picks).map((file) => ({ ...file, reason: file.reason.slice(0, LIMITS.reason) }));
54
+ return { ...result, value: { files, abstain: result.value.abstain && files.length === 0 } };
55
+ }
56
+ export {
57
+ RERANK_PROMPT_VERSION,
58
+ rerankCandidates
59
+ };
60
+ //# sourceMappingURL=rerank-Q7MIFNKA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/llm/rerank.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { z } from \"zod\";\nimport { redactSensitive } from \"../memory-extract/sensitive.js\";\nimport { chatJson, type LlmResult } from \"./client.js\";\nimport type { EnabledLlmConfig } from \"./config.js\";\n\n/**\n * Prompt-time rerank: the model sees the task and up to 15 candidate files\n * (path, one-line summary, a few signatures, never bodies) and picks at most\n * three, or abstains. The caller validates every pick against the candidates,\n * the symbol table and the evidence rules; this module only asks.\n */\nexport const RERANK_PROMPT_VERSION = 1;\nconst LIMITS = { candidates: 15, picks: 3, signatures: 5, reason: 80, maxTokens: 300 } as const;\n\nexport type RerankCandidate = { path: string; summary: string; signatures: string[] };\nexport type RerankPick = { path: string; symbols: string[]; reason: string };\n\nconst schema = z.object({\n files: z\n .array(\n z.object({\n path: z.string(),\n symbols: z.array(z.string()).default([]),\n reason: z.string().default(\"\"),\n }),\n )\n .default([]),\n abstain: z.boolean().default(false),\n});\n\nconst SYSTEM = [\n \"You pick the source files a coding agent must open for a task.\",\n 'Answer with JSON only: {\"files\":[{\"path\":\"...\",\"symbols\":[\"...\"],\"reason\":\"...\"}],\"abstain\":false}.',\n `Choose at most ${LIMITS.picks} files, best first, only from the candidates given;`,\n \"name the functions or classes to look at when you can (from the listed signatures);\",\n \"reason: a few words. If no candidate fits the task, answer with an empty files list and abstain true.\",\n].join(\" \");\n\nexport async function rerankCandidates(\n root: string,\n config: EnabledLlmConfig,\n task: string,\n candidates: RerankCandidate[],\n deadlineMs: number,\n): Promise<LlmResult<{ files: RerankPick[]; abstain: boolean }>> {\n const sent = candidates.slice(0, LIMITS.candidates).map((candidate) => ({\n path: candidate.path,\n summary: redactSensitive(candidate.summary),\n signatures: candidate.signatures.slice(0, LIMITS.signatures).map(redactSensitive),\n }));\n const user = JSON.stringify({ task: redactSensitive(task), candidates: sent });\n const result = await chatJson(config, {\n system: SYSTEM,\n user,\n schema,\n maxTokens: LIMITS.maxTokens,\n deadlineMs,\n purpose: \"prompt\",\n repositoryRoot: root,\n cacheKey: createHash(\"sha256\").update(`rerank:${RERANK_PROMPT_VERSION}:${user}`).digest(\"hex\"),\n });\n if (!result.ok) return result;\n const allowed = new Set(sent.map((candidate) => candidate.path));\n const seen = new Set<string>();\n const files = result.value.files\n .filter((file) => allowed.has(file.path) && !seen.has(file.path) && seen.add(file.path))\n .slice(0, LIMITS.picks)\n .map((file) => ({ ...file, reason: file.reason.slice(0, LIMITS.reason) }));\n return { ...result, value: { files, abstain: result.value.abstain && files.length === 0 } };\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS;AAWX,IAAM,wBAAwB;AACrC,IAAM,SAAS,EAAE,YAAY,IAAI,OAAO,GAAG,YAAY,GAAG,QAAQ,IAAI,WAAW,IAAI;AAKrF,IAAM,SAAS,EAAE,OAAO;AAAA,EACtB,OAAO,EACJ;AAAA,IACC,EAAE,OAAO;AAAA,MACP,MAAM,EAAE,OAAO;AAAA,MACf,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,MACvC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,IAC/B,CAAC;AAAA,EACH,EACC,QAAQ,CAAC,CAAC;AAAA,EACb,SAAS,EAAE,QAAQ,EAAE,QAAQ,KAAK;AACpC,CAAC;AAED,IAAM,SAAS;AAAA,EACb;AAAA,EACA;AAAA,EACA,kBAAkB,OAAO,KAAK;AAAA,EAC9B;AAAA,EACA;AACF,EAAE,KAAK,GAAG;AAEV,eAAsB,iBACpB,MACA,QACA,MACA,YACA,YAC+D;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,OAAO,UAAU,EAAE,IAAI,CAAC,eAAe;AAAA,IACtE,MAAM,UAAU;AAAA,IAChB,SAAS,gBAAgB,UAAU,OAAO;AAAA,IAC1C,YAAY,UAAU,WAAW,MAAM,GAAG,OAAO,UAAU,EAAE,IAAI,eAAe;AAAA,EAClF,EAAE;AACF,QAAM,OAAO,KAAK,UAAU,EAAE,MAAM,gBAAgB,IAAI,GAAG,YAAY,KAAK,CAAC;AAC7E,QAAM,SAAS,MAAM,SAAS,QAAQ;AAAA,IACpC,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,WAAW,OAAO;AAAA,IAClB;AAAA,IACA,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,UAAU,WAAW,QAAQ,EAAE,OAAO,UAAU,qBAAqB,IAAI,IAAI,EAAE,EAAE,OAAO,KAAK;AAAA,EAC/F,CAAC;AACD,MAAI,CAAC,OAAO,GAAI,QAAO;AACvB,QAAM,UAAU,IAAI,IAAI,KAAK,IAAI,CAAC,cAAc,UAAU,IAAI,CAAC;AAC/D,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAQ,OAAO,MAAM,MACxB,OAAO,CAAC,SAAS,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,EACtF,MAAM,GAAG,OAAO,KAAK,EACrB,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,QAAQ,KAAK,OAAO,MAAM,GAAG,OAAO,MAAM,EAAE,EAAE;AAC3E,SAAO,EAAE,GAAG,QAAQ,OAAO,EAAE,OAAO,SAAS,OAAO,MAAM,WAAW,MAAM,WAAW,EAAE,EAAE;AAC5F;","names":[]}
@@ -0,0 +1,18 @@
1
+ import {
2
+ SUMMARY_PROMPT_VERSION,
3
+ loadLlmSummaries,
4
+ summarizeRepository
5
+ } from "./chunk-3ZELDCR3.js";
6
+ import "./chunk-IBMJYIEP.js";
7
+ import "./chunk-PQK3GKZH.js";
8
+ import "./chunk-IE2OUO54.js";
9
+ import "./chunk-GDJH7XJC.js";
10
+ import "./chunk-ITGRANYW.js";
11
+ import "./chunk-K63EOA4B.js";
12
+ import "./chunk-PZ5AY32C.js";
13
+ export {
14
+ SUMMARY_PROMPT_VERSION,
15
+ loadLlmSummaries,
16
+ summarizeRepository
17
+ };
18
+ //# sourceMappingURL=summaries-TSE44KUQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,23 @@
1
+ import {
2
+ DEFAULT_ZVEC_MODEL,
3
+ buildZvecIndex,
4
+ parseHits,
5
+ refreshZvecIndex,
6
+ resetZvecCache,
7
+ zvecCandidates,
8
+ zvecExcludeGlobs,
9
+ zvecStatus
10
+ } from "./chunk-TI5TQD6D.js";
11
+ import "./chunk-K63EOA4B.js";
12
+ import "./chunk-PZ5AY32C.js";
13
+ export {
14
+ DEFAULT_ZVEC_MODEL,
15
+ buildZvecIndex,
16
+ parseHits,
17
+ refreshZvecIndex,
18
+ resetZvecCache,
19
+ zvecCandidates,
20
+ zvecExcludeGlobs,
21
+ zvecStatus
22
+ };
23
+ //# sourceMappingURL=zvec-F27AR357.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,20 @@
1
+ services:
2
+ postgres:
3
+ image: pgvector/pgvector:pg16
4
+ container_name: codebuddy-postgres
5
+ environment:
6
+ POSTGRES_USER: codebuddy
7
+ POSTGRES_PASSWORD: codebuddy
8
+ POSTGRES_DB: codebuddy
9
+ ports:
10
+ - "5432:5432"
11
+ volumes:
12
+ - codebuddy-postgres-data:/var/lib/postgresql/data
13
+ healthcheck:
14
+ test: ["CMD-SHELL", "pg_isready -U codebuddy -d codebuddy"]
15
+ interval: 5s
16
+ timeout: 5s
17
+ retries: 10
18
+
19
+ volumes:
20
+ codebuddy-postgres-data:
@@ -0,0 +1,67 @@
1
+ # Claude Code MCP Example
2
+
3
+ Use CodeBuddy as a Claude Code memory server through MCP stdio.
4
+
5
+ ## Local Package Development
6
+
7
+ From this repository:
8
+
9
+ ```bash
10
+ npm install
11
+ npm run build
12
+ docker compose up -d
13
+ ```
14
+
15
+ Set your environment:
16
+
17
+ ```bash
18
+ export DATABASE_URL=postgres://codebuddy:codebuddy@localhost:5432/codebuddy
19
+ export HF_TOKEN=hf_your_token
20
+ export CODEBUDDY_NAMESPACE=claude-code
21
+ ```
22
+
23
+ Run a quick health check:
24
+
25
+ ```bash
26
+ node dist/cli/index.js doctor --skip-model-check
27
+ ```
28
+
29
+ ## Project MCP Config
30
+
31
+ Add a `.mcp.json` file to the project where you use Claude Code:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "codebuddy": {
37
+ "command": "node",
38
+ "args": ["/absolute/path/to/codebuddy/dist/cli/index.js", "serve"],
39
+ "env": {
40
+ "DATABASE_URL": "postgres://codebuddy:codebuddy@localhost:5432/codebuddy",
41
+ "HF_TOKEN": "hf_your_token",
42
+ "CODEBUDDY_NAMESPACE": "claude-code"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ For an installed package, use:
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "codebuddy": {
55
+ "command": "codebuddy",
56
+ "args": ["serve"],
57
+ "env": {
58
+ "DATABASE_URL": "postgres://codebuddy:codebuddy@localhost:5432/codebuddy",
59
+ "HF_TOKEN": "hf_your_token",
60
+ "CODEBUDDY_NAMESPACE": "claude-code"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ Restart Claude Code after adding or changing MCP config. The available tools are `remember`, `remember_batch`, `recall`, `list_facts`, `list_namespaces`, `forget`, and `share`.
@@ -0,0 +1,54 @@
1
+ # Claude Desktop MCP Example
2
+
3
+ This example runs CodeBuddy as an MCP stdio server for Claude Desktop.
4
+
5
+ ## Prerequisites
6
+
7
+ ```bash
8
+ docker compose up -d
9
+ export DATABASE_URL=postgres://codebuddy:codebuddy@localhost:5432/codebuddy
10
+ export HF_TOKEN=hf_your_token
11
+ npm run build
12
+ node dist/cli/index.js init
13
+ node dist/cli/index.js doctor --skip-model-check
14
+ ```
15
+
16
+ ## Claude Desktop Config
17
+
18
+ Copy `claude_desktop_config.json` into your Claude Desktop MCP configuration location and replace `hf_replace_me` with your Hugging Face token.
19
+
20
+ The server command is:
21
+
22
+ ```bash
23
+ npx codebuddy serve
24
+ ```
25
+
26
+ For local development from this repository, use:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "codebuddy": {
32
+ "command": "node",
33
+ "args": ["/absolute/path/to/codebuddy/dist/cli/index.js", "serve"],
34
+ "env": {
35
+ "DATABASE_URL": "postgres://codebuddy:codebuddy@localhost:5432/codebuddy",
36
+ "HF_TOKEN": "hf_your_token",
37
+ "CODEBUDDY_NAMESPACE": "claude-desktop"
38
+ }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## Available Tools
45
+
46
+ - `remember`
47
+ - `remember_batch`
48
+ - `recall`
49
+ - `list_facts`
50
+ - `list_namespaces`
51
+ - `forget`
52
+ - `share`
53
+
54
+ v0.1 intentionally ships MCP tools only over stdio. Resources, prompts, and HTTP transport are deferred.
@@ -0,0 +1,13 @@
1
+ {
2
+ "mcpServers": {
3
+ "codebuddy": {
4
+ "command": "npx",
5
+ "args": ["codebuddy", "serve"],
6
+ "env": {
7
+ "DATABASE_URL": "postgres://codebuddy:codebuddy@localhost:5432/codebuddy",
8
+ "HF_TOKEN": "hf_replace_me",
9
+ "CODEBUDDY_NAMESPACE": "claude-desktop"
10
+ }
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,32 @@
1
+ # LangGraph Agent Example
2
+
3
+ This example shows CodeBuddy inside a LangGraph flow with recall before the agent step and remember after the agent step.
4
+
5
+ It demonstrates:
6
+
7
+ - `CodeBuddyNode` in `recall` mode
8
+ - `CodeBuddyNode` in `remember` mode
9
+ - `CodeBuddyCheckpointer`
10
+ - expected state fields: `messages`, `memory`, `sessionId`, `agentId`
11
+ - `cacheTtlSeconds: 30`
12
+
13
+ ## Run
14
+
15
+ ```bash
16
+ docker compose up -d
17
+ export DATABASE_URL=postgres://codebuddy:codebuddy@localhost:5432/codebuddy
18
+ export HF_TOKEN=hf_your_token
19
+ npm install
20
+ npm run build
21
+ npm install @langchain/langgraph @langchain/core
22
+ npx tsx examples/langgraph-agent/index.ts
23
+ ```
24
+
25
+ The example imports from the public package surface:
26
+
27
+ ```ts
28
+ import { createRuntime } from "codebuddy";
29
+ import { CodeBuddyCheckpointer, CodeBuddyNode } from "codebuddy/langgraph";
30
+ ```
31
+
32
+ If Hugging Face is cold or rate-limited, the embedding worker may need time to prepare vectors. Recall still falls back to recent context while embeddings are pending.
@@ -0,0 +1,71 @@
1
+ import { type BaseMessage, HumanMessage } from "@langchain/core/messages";
2
+ import { Annotation, StateGraph } from "@langchain/langgraph";
3
+ import type { PlannedContext } from "codebuddy";
4
+ import { createRuntime } from "codebuddy";
5
+ import { CodeBuddyCheckpointer, CodeBuddyNode } from "codebuddy/langgraph";
6
+
7
+ const postgresUrl = process.env.DATABASE_URL;
8
+ if (!postgresUrl) {
9
+ throw new Error("DATABASE_URL is required.");
10
+ }
11
+
12
+ const runtime = await createRuntime({
13
+ postgresUrl,
14
+ provider: { type: "huggingface", apiKey: process.env.HF_TOKEN },
15
+ namespace: "langgraph-agent",
16
+ tokenBudget: 4000,
17
+ });
18
+ const { memory } = runtime;
19
+
20
+ const State = Annotation.Root({
21
+ messages: Annotation<BaseMessage[]>({
22
+ reducer: (left, right) => left.concat(right),
23
+ default: () => [],
24
+ }),
25
+ memory: Annotation<PlannedContext | undefined>({
26
+ reducer: (_, right) => right,
27
+ default: () => undefined,
28
+ }),
29
+ sessionId: Annotation<string>({
30
+ reducer: (_, right) => right,
31
+ }),
32
+ agentId: Annotation<string | undefined>({
33
+ reducer: (_, right) => right,
34
+ default: () => undefined,
35
+ }),
36
+ });
37
+
38
+ async function agentNode(state: typeof State.State) {
39
+ const facts = state.memory?.messages.map((message) => message.content).join("\n") ?? "";
40
+ return {
41
+ messages: [
42
+ new HumanMessage(
43
+ facts
44
+ ? `Agent saw recalled memory:\n${facts}`
45
+ : "Agent had no recalled memory for this turn.",
46
+ ),
47
+ ],
48
+ };
49
+ }
50
+
51
+ const graph = new StateGraph(State)
52
+ .addNode("recall", new CodeBuddyNode({ memory, mode: "recall", cacheTtlSeconds: 30 }))
53
+ .addNode("agent", agentNode)
54
+ .addNode("remember", new CodeBuddyNode({ memory, mode: "remember" }))
55
+ .addEdge("__start__", "recall")
56
+ .addEdge("recall", "agent")
57
+ .addEdge("agent", "remember")
58
+ .addEdge("remember", "__end__")
59
+ .compile({ checkpointer: new CodeBuddyCheckpointer({ namespace: "langgraph-agent" }) });
60
+
61
+ const result = await graph.invoke(
62
+ {
63
+ messages: [new HumanMessage("What do we know about deployment?")],
64
+ sessionId: "sess_langgraph_example",
65
+ agentId: "agent-langgraph",
66
+ },
67
+ { configurable: { thread_id: "thread_langgraph_example" } },
68
+ );
69
+
70
+ console.log(result.messages.at(-1)?.content);
71
+ await runtime.close();
@@ -0,0 +1,35 @@
1
+ # Multi-Agent Handoff Example
2
+
3
+ This example shows two namespaces sharing memory.
4
+
5
+ Flow:
6
+
7
+ 1. `research-agent` writes a fact with `agentId` and `idempotencyKey`.
8
+ 2. `research-agent` shares that fact to `ops-agent` in `reference` mode.
9
+ 3. `ops-agent` recalls deployment context from its own namespace.
10
+ 4. `research-agent` also creates a `snapshot` share to show the second share mode.
11
+
12
+ ## Run
13
+
14
+ ```bash
15
+ docker compose up -d
16
+ export DATABASE_URL=postgres://codebuddy:codebuddy@localhost:5432/codebuddy
17
+ export HF_TOKEN=hf_your_token
18
+ npm run build
19
+ npx tsx examples/multi-agent-handoff/index.ts
20
+ ```
21
+
22
+ ## Behaviors To Notice
23
+
24
+ - namespaces isolate memory until a share is created
25
+ - `reference` shares point to the live source fact
26
+ - `snapshot` shares copy the fact for the target namespace
27
+ - repeating the example returns `deduplicated: true` for the same `idempotencyKey`
28
+ - `agentId` gives inspect and audit views a stable writer attribution
29
+
30
+ Inspect after running:
31
+
32
+ ```bash
33
+ node dist/cli/index.js inspect research-agent
34
+ node dist/cli/index.js inspect ops-agent
35
+ ```
@@ -0,0 +1,68 @@
1
+ import { createRuntime } from "codebuddy";
2
+
3
+ const postgresUrl = process.env.DATABASE_URL;
4
+ if (!postgresUrl) {
5
+ throw new Error("DATABASE_URL is required.");
6
+ }
7
+
8
+ const base = {
9
+ postgresUrl,
10
+ provider: { type: "huggingface" as const, apiKey: process.env.HF_TOKEN },
11
+ tokenBudget: 4000,
12
+ };
13
+
14
+ const research = await createRuntime({
15
+ ...base,
16
+ namespace: "research-agent",
17
+ });
18
+
19
+ const ops = await createRuntime({
20
+ ...base,
21
+ namespace: "ops-agent",
22
+ });
23
+
24
+ try {
25
+ const remembered = await research.memory.remember({
26
+ sessionId: "sess_handoff_example",
27
+ content: "The deployment target is eu-west-1 and requires layer-cached Docker builds.",
28
+ type: "fact",
29
+ idempotencyKey: "handoff:deployment-target:v1",
30
+ agentId: "agent-research",
31
+ });
32
+
33
+ console.log("remembered", remembered);
34
+
35
+ const referenceShare = await research.memory.share({
36
+ from: "research-agent",
37
+ to: "ops-agent",
38
+ factIds: [remembered.id],
39
+ mode: "reference",
40
+ agentId: "agent-research",
41
+ });
42
+
43
+ console.log("reference share", referenceShare);
44
+
45
+ const opsRecall = await ops.memory.recall({
46
+ sessionId: "sess_handoff_example",
47
+ query: "What deployment target should ops use?",
48
+ callerModel: "meta-llama/Llama-3.2-3B-Instruct",
49
+ });
50
+
51
+ console.log("ops recalled messages");
52
+ for (const message of opsRecall.messages) {
53
+ console.log("-", message.content);
54
+ }
55
+
56
+ const snapshotShare = await research.memory.share({
57
+ from: "research-agent",
58
+ to: "ops-agent",
59
+ factIds: [remembered.id],
60
+ mode: "snapshot",
61
+ agentId: "agent-research",
62
+ });
63
+
64
+ console.log("snapshot share", snapshotShare);
65
+ } finally {
66
+ await research.close();
67
+ await ops.close();
68
+ }