@cue-dev/retrieval-core 0.1.3

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.
@@ -0,0 +1,86 @@
1
+ import { createRequire } from "node:module";
2
+ import { describe, expect, it } from "vitest";
3
+ import Parser from "tree-sitter";
4
+ import JavaScriptV023 from "tree-sitter-javascript-v023";
5
+ import Java from "tree-sitter-java";
6
+ import PythonV023 from "tree-sitter-python-v023";
7
+ import Rust from "tree-sitter-rust";
8
+ import { Language as WebLanguage, Parser as WebParser } from "web-tree-sitter";
9
+ import {
10
+ __resetChunkingParserStateForTests,
11
+ getChunkingParserAvailabilitySnapshot
12
+ } from "../src/chunking.js";
13
+
14
+ const require = createRequire(import.meta.url);
15
+
16
+ describe("chunking parser availability PoC", () => {
17
+ it("captures current baseline parser availability for configured languages", () => {
18
+ __resetChunkingParserStateForTests();
19
+ const snapshot = getChunkingParserAvailabilitySnapshot({
20
+ enabled_languages: ["typescript", "javascript", "python", "go", "rust", "java"]
21
+ });
22
+ const byLanguage = new Map(snapshot.map((entry) => [entry.language, entry]));
23
+
24
+ expect(byLanguage.get("typescript")?.status).toBe("available");
25
+ expect(byLanguage.get("go")?.status).toBe("available");
26
+ expect(byLanguage.get("javascript")?.status).toBe("available");
27
+ expect(byLanguage.get("python")?.status).toBe("available");
28
+ expect(byLanguage.get("rust")?.status).toBe("available");
29
+ expect(byLanguage.get("java")?.status).toBe("available");
30
+ });
31
+
32
+ it("proves native availability with tree-sitter-compatible alias grammars", () => {
33
+ const javascriptParser = new Parser();
34
+ javascriptParser.setLanguage(JavaScriptV023 as unknown as Parser.Language);
35
+ const javascriptTree = javascriptParser.parse("function alpha(){ return 1; }\n");
36
+ expect(javascriptTree?.rootNode?.type).toBe("program");
37
+
38
+ const pythonParser = new Parser();
39
+ pythonParser.setLanguage(PythonV023 as unknown as Parser.Language);
40
+ const pythonTree = pythonParser.parse("def alpha():\n return 1\n");
41
+ expect(pythonTree?.rootNode?.type).toBe("module");
42
+
43
+ const rustParser = new Parser();
44
+ rustParser.setLanguage(Rust as unknown as Parser.Language);
45
+ const rustTree = rustParser.parse("fn alpha() -> i32 { 1 }\n");
46
+ expect(rustTree?.rootNode?.type).toBe("source_file");
47
+
48
+ const javaParser = new Parser();
49
+ javaParser.setLanguage(Java as unknown as Parser.Language);
50
+ const javaTree = javaParser.parse("class Alpha { int value() { return 1; } }\n");
51
+ expect(javaTree?.rootNode?.type).toBe("program");
52
+ });
53
+
54
+ it("proves wasm availability with web-tree-sitter for javascript, python, rust, and java", async () => {
55
+ const runtimeWasm = require.resolve("web-tree-sitter/web-tree-sitter.wasm");
56
+ await WebParser.init({
57
+ locateFile() {
58
+ return runtimeWasm;
59
+ }
60
+ });
61
+
62
+ const javascriptLanguage = await WebLanguage.load(require.resolve("tree-sitter-javascript/tree-sitter-javascript.wasm"));
63
+ const javascriptParser = new WebParser();
64
+ javascriptParser.setLanguage(javascriptLanguage);
65
+ const javascriptTree = javascriptParser.parse("function alpha(){ return 1; }\n");
66
+ expect(javascriptTree?.rootNode?.type).toBe("program");
67
+
68
+ const pythonLanguage = await WebLanguage.load(require.resolve("tree-sitter-python/tree-sitter-python.wasm"));
69
+ const pythonParser = new WebParser();
70
+ pythonParser.setLanguage(pythonLanguage);
71
+ const pythonTree = pythonParser.parse("def alpha():\n return 1\n");
72
+ expect(pythonTree?.rootNode?.type).toBe("module");
73
+
74
+ const rustLanguage = await WebLanguage.load(require.resolve("tree-sitter-rust/tree-sitter-rust.wasm"));
75
+ const rustParser = new WebParser();
76
+ rustParser.setLanguage(rustLanguage);
77
+ const rustTree = rustParser.parse("fn alpha() -> i32 { 1 }\n");
78
+ expect(rustTree?.rootNode?.type).toBe("source_file");
79
+
80
+ const javaLanguage = await WebLanguage.load(require.resolve("tree-sitter-java/tree-sitter-java.wasm"));
81
+ const javaParser = new WebParser();
82
+ javaParser.setLanguage(javaLanguage);
83
+ const javaTree = javaParser.parse("class Alpha { int value() { return 1; } }\n");
84
+ expect(javaTree?.rootNode?.type).toBe("program");
85
+ });
86
+ });
@@ -0,0 +1,209 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const queryMock = vi.fn();
4
+
5
+ vi.mock("@anthropic-ai/claude-agent-sdk", () => ({
6
+ query: queryMock
7
+ }));
8
+
9
+ describe("ClaudeAgentEnhancerProvider", () => {
10
+ beforeEach(() => {
11
+ vi.clearAllMocks();
12
+ vi.resetModules();
13
+ });
14
+
15
+ it("accepts assistant text emitted after an empty result event", async () => {
16
+ queryMock.mockImplementation(async function* () {
17
+ yield { type: "result", subtype: "success", result: "" };
18
+ yield {
19
+ type: "assistant",
20
+ message: {
21
+ content: [{ type: "text", text: "{\"enhanced_prompt\":\"Use post-result assistant text\"}" }]
22
+ }
23
+ };
24
+ });
25
+
26
+ const { ClaudeAgentEnhancerProvider } = await import("../src/index.js");
27
+ const provider = new ClaudeAgentEnhancerProvider({
28
+ api_key: "sk-test",
29
+ model: "claude-sonnet-4-5-20250929",
30
+ permission_mode: "default"
31
+ });
32
+
33
+ const output = await provider.generate({
34
+ trace_id: "trc-provider-post-result-text",
35
+ tenant_id: "tenant-dev",
36
+ workspace_id: "ws-dev",
37
+ request: {
38
+ prompt: "Harden tenant authorization and keep behavior stable",
39
+ conversation_history: [],
40
+ project_root_path: "/workspace/dev"
41
+ },
42
+ style_requested: "standard",
43
+ style_resolved: "standard",
44
+ intent: "feature",
45
+ query_intent: "impl-focused",
46
+ language: "en",
47
+ context_refs: [],
48
+ context_snippets: [],
49
+ warnings: [],
50
+ questions: [],
51
+ tool_mode: "none"
52
+ });
53
+
54
+ expect(output.enhanced_prompt).toBe("Use post-result assistant text");
55
+ });
56
+
57
+ it("parses JSON text from summary messages when result text is empty", async () => {
58
+ queryMock.mockImplementation(async function* () {
59
+ yield { type: "tool_use_summary", summary: "{\"enhanced_prompt\":\"Use summary fallback\"}" };
60
+ yield { type: "result", subtype: "success", result: "" };
61
+ });
62
+
63
+ const { ClaudeAgentEnhancerProvider } = await import("../src/index.js");
64
+ const provider = new ClaudeAgentEnhancerProvider({
65
+ api_key: "sk-test",
66
+ model: "claude-sonnet-4-5-20250929",
67
+ permission_mode: "default"
68
+ });
69
+
70
+ const output = await provider.generate({
71
+ trace_id: "trc-provider-summary-fallback",
72
+ tenant_id: "tenant-dev",
73
+ workspace_id: "ws-dev",
74
+ request: {
75
+ prompt: "Harden tenant authorization and keep behavior stable",
76
+ conversation_history: [],
77
+ project_root_path: "/workspace/dev"
78
+ },
79
+ style_requested: "standard",
80
+ style_resolved: "standard",
81
+ intent: "feature",
82
+ query_intent: "impl-focused",
83
+ language: "en",
84
+ context_refs: [],
85
+ context_snippets: [],
86
+ warnings: [],
87
+ questions: [],
88
+ tool_mode: "none"
89
+ });
90
+
91
+ expect(output.enhanced_prompt).toBe("Use summary fallback");
92
+ });
93
+
94
+ it("returns streamed text when sdk ends with error_max_turns", async () => {
95
+ queryMock.mockImplementation(async function* () {
96
+ yield {
97
+ type: "stream_event",
98
+ event: {
99
+ type: "content_block_delta",
100
+ delta: { text: "{\"enhanced_prompt\":\"Use streamed fallback on max turns\"}" }
101
+ }
102
+ };
103
+ yield {
104
+ type: "result",
105
+ subtype: "error_max_turns",
106
+ errors: ["turn limit reached"]
107
+ };
108
+ });
109
+
110
+ const { ClaudeAgentEnhancerProvider } = await import("../src/index.js");
111
+ const provider = new ClaudeAgentEnhancerProvider({
112
+ api_key: "sk-test",
113
+ model: "claude-sonnet-4-5-20250929",
114
+ permission_mode: "default"
115
+ });
116
+
117
+ const output = await provider.generate({
118
+ trace_id: "trc-provider-max-turns-fallback",
119
+ tenant_id: "tenant-dev",
120
+ workspace_id: "ws-dev",
121
+ request: {
122
+ prompt: "Harden tenant authorization and keep behavior stable",
123
+ conversation_history: [],
124
+ project_root_path: "/workspace/dev"
125
+ },
126
+ style_requested: "standard",
127
+ style_resolved: "standard",
128
+ intent: "feature",
129
+ query_intent: "impl-focused",
130
+ language: "en",
131
+ context_refs: [],
132
+ context_snippets: [],
133
+ warnings: [],
134
+ questions: [],
135
+ tool_mode: "none"
136
+ });
137
+
138
+ expect(output.enhanced_prompt).toBe("Use streamed fallback on max turns");
139
+ });
140
+
141
+ it("includes extracted project conventions and output contract in payload", async () => {
142
+ queryMock.mockImplementation(async function* () {
143
+ yield { type: "result", subtype: "success", result: "{\"enhanced_prompt\":\"ok\"}" };
144
+ });
145
+
146
+ const { ClaudeAgentEnhancerProvider } = await import("../src/index.js");
147
+ const provider = new ClaudeAgentEnhancerProvider({
148
+ api_key: "sk-test",
149
+ model: "claude-sonnet-4-5-20250929",
150
+ permission_mode: "default"
151
+ });
152
+
153
+ await provider.generate({
154
+ trace_id: "trc-provider-conventions",
155
+ tenant_id: "tenant-dev",
156
+ workspace_id: "ws-dev",
157
+ request: {
158
+ prompt: "Harden tenant authorization and keep behavior stable",
159
+ conversation_history: [{ role: "user", content: "Add regression tests and keep contracts stable." }],
160
+ project_root_path: "/workspace/dev"
161
+ },
162
+ style_requested: "deep",
163
+ style_resolved: "deep",
164
+ intent: "feature",
165
+ query_intent: "impl-focused",
166
+ language: "en",
167
+ context_refs: [
168
+ {
169
+ path: "AGENTS.md",
170
+ start_line: 1,
171
+ end_line: 20,
172
+ reason: "exact symbol match"
173
+ }
174
+ ],
175
+ context_snippets: [
176
+ {
177
+ path: "AGENTS.md",
178
+ start_line: 1,
179
+ end_line: 10,
180
+ reason: "path and token overlap",
181
+ score: 0.9,
182
+ snippet:
183
+ "- Always use bun for install, scripts, and tests.\n- Maintain deterministic fallback behavior when enhancer times out."
184
+ }
185
+ ],
186
+ warnings: [],
187
+ questions: [],
188
+ tool_mode: "none"
189
+ });
190
+
191
+ const call = queryMock.mock.calls[0]?.[0] as { prompt?: string } | undefined;
192
+ expect(call?.prompt).toContain("Input JSON:");
193
+ const payloadRaw = (call?.prompt ?? "").split("Input JSON:\n")[1] ?? "";
194
+ const payload = JSON.parse(payloadRaw) as {
195
+ output_contract?: { target_style?: string };
196
+ project_conventions?: string[];
197
+ non_negotiables?: string[];
198
+ query_intent?: string;
199
+ style_requested?: string;
200
+ style_resolved?: string;
201
+ };
202
+ expect(payload.query_intent).toBe("impl-focused");
203
+ expect(payload.style_requested).toBe("deep");
204
+ expect(payload.style_resolved).toBe("deep");
205
+ expect(payload.output_contract?.target_style).toBe("deep_implementation_plan");
206
+ expect(payload.project_conventions?.some((entry) => /always use bun/i.test(entry))).toBe(true);
207
+ expect(payload.non_negotiables?.some((entry) => /regression tests/i.test(entry))).toBe(true);
208
+ });
209
+ });
@@ -0,0 +1,101 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { InMemoryQueryCache } from "@cue-dev/data-plane";
3
+ import { InMemoryIndexStore, RetrievalCore, type EmbeddingProvider } from "../src/index.js";
4
+
5
+ class CaptureEmbeddingProvider implements EmbeddingProvider {
6
+ readonly calls: Array<{ texts: string[]; purpose: "index" | "query" }> = [];
7
+
8
+ async embed(input: { texts: string[]; purpose: "index" | "query" }): Promise<number[][]> {
9
+ this.calls.push({ texts: [...input.texts], purpose: input.purpose });
10
+ return input.texts.map(() => [0.1, 0.2, 0.3]);
11
+ }
12
+ }
13
+
14
+ describe("retrieval-core embedding context prefix", () => {
15
+ it("adds contextual prefix to index embedding text when enabled", async () => {
16
+ const store = new InMemoryIndexStore();
17
+ const embeddingProvider = new CaptureEmbeddingProvider();
18
+ const core = new RetrievalCore(store, new InMemoryQueryCache(), {
19
+ embeddingProvider,
20
+ embeddingDescriptor: {
21
+ provider: "test",
22
+ model: "capture",
23
+ dimensions: 3
24
+ },
25
+ chunkingConfig: {
26
+ embedding_context_prefix_enabled: true,
27
+ target_chunk_tokens: 420,
28
+ chunk_overlap_tokens: 90
29
+ }
30
+ });
31
+
32
+ await store.upsertWorkspace({
33
+ workspace_id: "ws-prefix-on",
34
+ tenant_id: "tenant-prefix",
35
+ name: "prefix-on",
36
+ project_root_path: "/workspace/prefix-on"
37
+ });
38
+
39
+ await core.indexArtifact({
40
+ tenant_id: "tenant-prefix",
41
+ workspace_id: "ws-prefix-on",
42
+ index_version: "idx-prefix-on-v1",
43
+ files: [
44
+ {
45
+ path: "src/sample.ts",
46
+ language: "typescript",
47
+ content: ["export function alpha(input: number): number {", " return input + 1;", "}"].join("\n")
48
+ }
49
+ ]
50
+ });
51
+
52
+ const indexCall = embeddingProvider.calls.find((call) => call.purpose === "index");
53
+ expect(indexCall).toBeDefined();
54
+ const firstText = indexCall?.texts[0] ?? "";
55
+ expect(firstText.startsWith("src/sample.ts:1-3")).toBe(true);
56
+ expect(firstText).toContain("export function alpha");
57
+ });
58
+
59
+ it("keeps index embedding text unchanged when contextual prefix is disabled", async () => {
60
+ const store = new InMemoryIndexStore();
61
+ const embeddingProvider = new CaptureEmbeddingProvider();
62
+ const core = new RetrievalCore(store, new InMemoryQueryCache(), {
63
+ embeddingProvider,
64
+ embeddingDescriptor: {
65
+ provider: "test",
66
+ model: "capture",
67
+ dimensions: 3
68
+ },
69
+ chunkingConfig: {
70
+ embedding_context_prefix_enabled: false,
71
+ target_chunk_tokens: 420,
72
+ chunk_overlap_tokens: 90
73
+ }
74
+ });
75
+
76
+ await store.upsertWorkspace({
77
+ workspace_id: "ws-prefix-off",
78
+ tenant_id: "tenant-prefix",
79
+ name: "prefix-off",
80
+ project_root_path: "/workspace/prefix-off"
81
+ });
82
+
83
+ const snippet = ["export function alpha(input: number): number {", " return input + 1;", "}"].join("\n");
84
+ await core.indexArtifact({
85
+ tenant_id: "tenant-prefix",
86
+ workspace_id: "ws-prefix-off",
87
+ index_version: "idx-prefix-off-v1",
88
+ files: [
89
+ {
90
+ path: "src/sample.ts",
91
+ language: "typescript",
92
+ content: snippet
93
+ }
94
+ ]
95
+ });
96
+
97
+ const indexCall = embeddingProvider.calls.find((call) => call.purpose === "index");
98
+ expect(indexCall).toBeDefined();
99
+ expect(indexCall?.texts[0]).toBe(snippet);
100
+ });
101
+ });