@tienne/gestalt 0.87.0 → 0.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +12 -4
- package/README.ko.md +2 -1
- package/README.md +3 -1
- package/dist/bin/gestalt-hook.d.ts +5 -0
- package/dist/bin/gestalt-hook.d.ts.map +1 -0
- package/dist/bin/gestalt-hook.js +51 -0
- package/dist/bin/gestalt-hook.js.map +1 -0
- package/dist/package.json +5 -3
- package/dist/plugin/skills/_shared/proactive-routing.md +1 -0
- package/dist/plugin/skills/architecture/SKILL.md +913 -0
- package/dist/plugin/skills/blast-radius/SKILL.md +11 -1
- package/dist/plugin/skills/diff-radius/SKILL.md +11 -0
- package/dist/schemas/architecture-ir.schema.json +596 -0
- package/dist/schemas/gestalt.schema.json +19 -0
- package/dist/src/architecture/canvas-geometry.d.ts +40 -0
- package/dist/src/architecture/canvas-geometry.d.ts.map +1 -0
- package/dist/src/architecture/canvas-geometry.js +212 -0
- package/dist/src/architecture/canvas-geometry.js.map +1 -0
- package/dist/src/architecture/codeowners.d.ts +16 -0
- package/dist/src/architecture/codeowners.d.ts.map +1 -0
- package/dist/src/architecture/codeowners.js +58 -0
- package/dist/src/architecture/codeowners.js.map +1 -0
- package/dist/src/architecture/compare-layout.d.ts +27 -0
- package/dist/src/architecture/compare-layout.d.ts.map +1 -0
- package/dist/src/architecture/compare-layout.js +72 -0
- package/dist/src/architecture/compare-layout.js.map +1 -0
- package/dist/src/architecture/dataflow-layout.d.ts +29 -0
- package/dist/src/architecture/dataflow-layout.d.ts.map +1 -0
- package/dist/src/architecture/dataflow-layout.js +229 -0
- package/dist/src/architecture/dataflow-layout.js.map +1 -0
- package/dist/src/architecture/doc-fresh.d.ts +31 -0
- package/dist/src/architecture/doc-fresh.d.ts.map +1 -0
- package/dist/src/architecture/doc-fresh.js +84 -0
- package/dist/src/architecture/doc-fresh.js.map +1 -0
- package/dist/src/architecture/doc-link.d.ts +84 -0
- package/dist/src/architecture/doc-link.d.ts.map +1 -0
- package/dist/src/architecture/doc-link.js +396 -0
- package/dist/src/architecture/doc-link.js.map +1 -0
- package/dist/src/architecture/doc-routes.d.ts +39 -0
- package/dist/src/architecture/doc-routes.d.ts.map +1 -0
- package/dist/src/architecture/doc-routes.js +123 -0
- package/dist/src/architecture/doc-routes.js.map +1 -0
- package/dist/src/architecture/doc-scan.d.ts +107 -0
- package/dist/src/architecture/doc-scan.d.ts.map +1 -0
- package/dist/src/architecture/doc-scan.js +617 -0
- package/dist/src/architecture/doc-scan.js.map +1 -0
- package/dist/src/architecture/doc-stale.d.ts +32 -0
- package/dist/src/architecture/doc-stale.d.ts.map +1 -0
- package/dist/src/architecture/doc-stale.js +60 -0
- package/dist/src/architecture/doc-stale.js.map +1 -0
- package/dist/src/architecture/drilldown.d.ts +51 -0
- package/dist/src/architecture/drilldown.d.ts.map +1 -0
- package/dist/src/architecture/drilldown.js +1160 -0
- package/dist/src/architecture/drilldown.js.map +1 -0
- package/dist/src/architecture/endpoint-match.d.ts +43 -0
- package/dist/src/architecture/endpoint-match.d.ts.map +1 -0
- package/dist/src/architecture/endpoint-match.js +133 -0
- package/dist/src/architecture/endpoint-match.js.map +1 -0
- package/dist/src/architecture/flow-layout.d.ts +79 -0
- package/dist/src/architecture/flow-layout.d.ts.map +1 -0
- package/dist/src/architecture/flow-layout.js +519 -0
- package/dist/src/architecture/flow-layout.js.map +1 -0
- package/dist/src/architecture/focus.d.ts +14 -0
- package/dist/src/architecture/focus.d.ts.map +1 -0
- package/dist/src/architecture/focus.js +107 -0
- package/dist/src/architecture/focus.js.map +1 -0
- package/dist/src/architecture/global-context.d.ts +23 -0
- package/dist/src/architecture/global-context.d.ts.map +1 -0
- package/dist/src/architecture/global-context.js +67 -0
- package/dist/src/architecture/global-context.js.map +1 -0
- package/dist/src/architecture/html-client.d.ts +35 -0
- package/dist/src/architecture/html-client.d.ts.map +1 -0
- package/dist/src/architecture/html-client.js +1852 -0
- package/dist/src/architecture/html-client.js.map +1 -0
- package/dist/src/architecture/html-renderer.d.ts +22 -0
- package/dist/src/architecture/html-renderer.d.ts.map +1 -0
- package/dist/src/architecture/html-renderer.js +1290 -0
- package/dist/src/architecture/html-renderer.js.map +1 -0
- package/dist/src/architecture/html-theme.d.ts +25 -0
- package/dist/src/architecture/html-theme.d.ts.map +1 -0
- package/dist/src/architecture/html-theme.js +681 -0
- package/dist/src/architecture/html-theme.js.map +1 -0
- package/dist/src/architecture/index.d.ts +9 -0
- package/dist/src/architecture/index.d.ts.map +1 -0
- package/dist/src/architecture/index.js +9 -0
- package/dist/src/architecture/index.js.map +1 -0
- package/dist/src/architecture/ir-schema.d.ts +1832 -0
- package/dist/src/architecture/ir-schema.d.ts.map +1 -0
- package/dist/src/architecture/ir-schema.js +343 -0
- package/dist/src/architecture/ir-schema.js.map +1 -0
- package/dist/src/architecture/kind-text.d.ts +21 -0
- package/dist/src/architecture/kind-text.d.ts.map +1 -0
- package/dist/src/architecture/kind-text.js +42 -0
- package/dist/src/architecture/kind-text.js.map +1 -0
- package/dist/src/architecture/layout.d.ts +227 -0
- package/dist/src/architecture/layout.d.ts.map +1 -0
- package/dist/src/architecture/layout.js +627 -0
- package/dist/src/architecture/layout.js.map +1 -0
- package/dist/src/architecture/mcp-tool-match.d.ts +49 -0
- package/dist/src/architecture/mcp-tool-match.d.ts.map +1 -0
- package/dist/src/architecture/mcp-tool-match.js +53 -0
- package/dist/src/architecture/mcp-tool-match.js.map +1 -0
- package/dist/src/architecture/merge.d.ts +54 -0
- package/dist/src/architecture/merge.d.ts.map +1 -0
- package/dist/src/architecture/merge.js +681 -0
- package/dist/src/architecture/merge.js.map +1 -0
- package/dist/src/architecture/micro-app.d.ts +20 -0
- package/dist/src/architecture/micro-app.d.ts.map +1 -0
- package/dist/src/architecture/micro-app.js +41 -0
- package/dist/src/architecture/micro-app.js.map +1 -0
- package/dist/src/architecture/name-ref-match.d.ts +43 -0
- package/dist/src/architecture/name-ref-match.d.ts.map +1 -0
- package/dist/src/architecture/name-ref-match.js +127 -0
- package/dist/src/architecture/name-ref-match.js.map +1 -0
- package/dist/src/architecture/packs/data.d.ts +109 -0
- package/dist/src/architecture/packs/data.d.ts.map +1 -0
- package/dist/src/architecture/packs/data.js +64 -0
- package/dist/src/architecture/packs/data.js.map +1 -0
- package/dist/src/architecture/packs/generic.d.ts +47 -0
- package/dist/src/architecture/packs/generic.d.ts.map +1 -0
- package/dist/src/architecture/packs/generic.js +35 -0
- package/dist/src/architecture/packs/generic.js.map +1 -0
- package/dist/src/architecture/packs/harness.d.ts +96 -0
- package/dist/src/architecture/packs/harness.d.ts.map +1 -0
- package/dist/src/architecture/packs/harness.js +66 -0
- package/dist/src/architecture/packs/harness.js.map +1 -0
- package/dist/src/architecture/packs/index.d.ts +840 -0
- package/dist/src/architecture/packs/index.d.ts.map +1 -0
- package/dist/src/architecture/packs/index.js +87 -0
- package/dist/src/architecture/packs/index.js.map +1 -0
- package/dist/src/architecture/packs/infra.d.ts +91 -0
- package/dist/src/architecture/packs/infra.d.ts.map +1 -0
- package/dist/src/architecture/packs/infra.js +57 -0
- package/dist/src/architecture/packs/infra.js.map +1 -0
- package/dist/src/architecture/packs/knowledge.d.ts +72 -0
- package/dist/src/architecture/packs/knowledge.d.ts.map +1 -0
- package/dist/src/architecture/packs/knowledge.js +58 -0
- package/dist/src/architecture/packs/knowledge.js.map +1 -0
- package/dist/src/architecture/packs/process.d.ts +87 -0
- package/dist/src/architecture/packs/process.d.ts.map +1 -0
- package/dist/src/architecture/packs/process.js +52 -0
- package/dist/src/architecture/packs/process.js.map +1 -0
- package/dist/src/architecture/packs/render-classes.d.ts +11 -0
- package/dist/src/architecture/packs/render-classes.d.ts.map +1 -0
- package/dist/src/architecture/packs/render-classes.js +92 -0
- package/dist/src/architecture/packs/render-classes.js.map +1 -0
- package/dist/src/architecture/packs/types.d.ts +66 -0
- package/dist/src/architecture/packs/types.d.ts.map +1 -0
- package/dist/src/architecture/packs/types.js +18 -0
- package/dist/src/architecture/packs/types.js.map +1 -0
- package/dist/src/architecture/packs/web-product.d.ts +348 -0
- package/dist/src/architecture/packs/web-product.d.ts.map +1 -0
- package/dist/src/architecture/packs/web-product.js +226 -0
- package/dist/src/architecture/packs/web-product.js.map +1 -0
- package/dist/src/architecture/sequence-layout.d.ts +50 -0
- package/dist/src/architecture/sequence-layout.d.ts.map +1 -0
- package/dist/src/architecture/sequence-layout.js +140 -0
- package/dist/src/architecture/sequence-layout.js.map +1 -0
- package/dist/src/architecture/service-facts.d.ts +30 -0
- package/dist/src/architecture/service-facts.d.ts.map +1 -0
- package/dist/src/architecture/service-facts.js +88 -0
- package/dist/src/architecture/service-facts.js.map +1 -0
- package/dist/src/architecture/store.d.ts +50 -0
- package/dist/src/architecture/store.d.ts.map +1 -0
- package/dist/src/architecture/store.js +320 -0
- package/dist/src/architecture/store.js.map +1 -0
- package/dist/src/architecture/types.d.ts +400 -0
- package/dist/src/architecture/types.d.ts.map +1 -0
- package/dist/src/architecture/types.js +75 -0
- package/dist/src/architecture/types.js.map +1 -0
- package/dist/src/architecture/validator.d.ts +65 -0
- package/dist/src/architecture/validator.d.ts.map +1 -0
- package/dist/src/architecture/validator.js +1249 -0
- package/dist/src/architecture/validator.js.map +1 -0
- package/dist/src/code-graph/cochange.d.ts +40 -0
- package/dist/src/code-graph/cochange.d.ts.map +1 -1
- package/dist/src/code-graph/cochange.js +88 -3
- package/dist/src/code-graph/cochange.js.map +1 -1
- package/dist/src/code-graph/engine.d.ts +35 -1
- package/dist/src/code-graph/engine.d.ts.map +1 -1
- package/dist/src/code-graph/engine.js +300 -55
- package/dist/src/code-graph/engine.js.map +1 -1
- package/dist/src/code-graph/freshness.d.ts +39 -0
- package/dist/src/code-graph/freshness.d.ts.map +1 -0
- package/dist/src/code-graph/freshness.js +93 -0
- package/dist/src/code-graph/freshness.js.map +1 -0
- package/dist/src/code-graph/hooks/background.d.ts +18 -0
- package/dist/src/code-graph/hooks/background.d.ts.map +1 -0
- package/dist/src/code-graph/hooks/background.js +55 -0
- package/dist/src/code-graph/hooks/background.js.map +1 -0
- package/dist/src/code-graph/hooks/pointers.d.ts +66 -0
- package/dist/src/code-graph/hooks/pointers.d.ts.map +1 -0
- package/dist/src/code-graph/hooks/pointers.js +292 -0
- package/dist/src/code-graph/hooks/pointers.js.map +1 -0
- package/dist/src/code-graph/hooks/rank.d.ts +36 -0
- package/dist/src/code-graph/hooks/rank.d.ts.map +1 -0
- package/dist/src/code-graph/hooks/rank.js +212 -0
- package/dist/src/code-graph/hooks/rank.js.map +1 -0
- package/dist/src/code-graph/hooks/run.d.ts +37 -0
- package/dist/src/code-graph/hooks/run.d.ts.map +1 -0
- package/dist/src/code-graph/hooks/run.js +324 -0
- package/dist/src/code-graph/hooks/run.js.map +1 -0
- package/dist/src/code-graph/hooks/settings.d.ts +11 -0
- package/dist/src/code-graph/hooks/settings.d.ts.map +1 -0
- package/dist/src/code-graph/hooks/settings.js +25 -0
- package/dist/src/code-graph/hooks/settings.js.map +1 -0
- package/dist/src/code-graph/hooks/state.d.ts +20 -0
- package/dist/src/code-graph/hooks/state.d.ts.map +1 -0
- package/dist/src/code-graph/hooks/state.js +73 -0
- package/dist/src/code-graph/hooks/state.js.map +1 -0
- package/dist/src/code-graph/index.d.ts +6 -2
- package/dist/src/code-graph/index.d.ts.map +1 -1
- package/dist/src/code-graph/index.js +3 -1
- package/dist/src/code-graph/index.js.map +1 -1
- package/dist/src/code-graph/ko-text.d.ts +39 -0
- package/dist/src/code-graph/ko-text.d.ts.map +1 -0
- package/dist/src/code-graph/ko-text.js +223 -0
- package/dist/src/code-graph/ko-text.js.map +1 -0
- package/dist/src/code-graph/lock.d.ts +30 -0
- package/dist/src/code-graph/lock.d.ts.map +1 -0
- package/dist/src/code-graph/lock.js +140 -0
- package/dist/src/code-graph/lock.js.map +1 -0
- package/dist/src/code-graph/plugins/typescript-skeleton.d.ts +7 -0
- package/dist/src/code-graph/plugins/typescript-skeleton.d.ts.map +1 -0
- package/dist/src/code-graph/plugins/typescript-skeleton.js +157 -0
- package/dist/src/code-graph/plugins/typescript-skeleton.js.map +1 -0
- package/dist/src/code-graph/plugins/typescript.d.ts.map +1 -1
- package/dist/src/code-graph/plugins/typescript.js +58 -0
- package/dist/src/code-graph/plugins/typescript.js.map +1 -1
- package/dist/src/code-graph/storage.d.ts +85 -0
- package/dist/src/code-graph/storage.d.ts.map +1 -1
- package/dist/src/code-graph/storage.js +318 -3
- package/dist/src/code-graph/storage.js.map +1 -1
- package/dist/src/code-graph/types.d.ts +66 -0
- package/dist/src/code-graph/types.d.ts.map +1 -1
- package/dist/src/core/config.d.ts +33 -0
- package/dist/src/core/config.d.ts.map +1 -1
- package/dist/src/core/config.js +14 -0
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/errors.d.ts +4 -0
- package/dist/src/core/errors.d.ts.map +1 -1
- package/dist/src/core/errors.js +8 -0
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/core/hooks-env.d.ts +9 -0
- package/dist/src/core/hooks-env.d.ts.map +1 -0
- package/dist/src/core/hooks-env.js +16 -0
- package/dist/src/core/hooks-env.js.map +1 -0
- package/dist/src/mcp/schemas.d.ts +326 -3
- package/dist/src/mcp/schemas.d.ts.map +1 -1
- package/dist/src/mcp/schemas.js +170 -2
- package/dist/src/mcp/schemas.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +28 -4
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/architecture-passthrough.d.ts +9 -0
- package/dist/src/mcp/tools/architecture-passthrough.d.ts.map +1 -0
- package/dist/src/mcp/tools/architecture-passthrough.js +587 -0
- package/dist/src/mcp/tools/architecture-passthrough.js.map +1 -0
- package/dist/src/mcp/tools/code-graph-passthrough.d.ts +6 -1
- package/dist/src/mcp/tools/code-graph-passthrough.d.ts.map +1 -1
- package/dist/src/mcp/tools/code-graph-passthrough.js +95 -6
- package/dist/src/mcp/tools/code-graph-passthrough.js.map +1 -1
- package/dist/src/utils/claude-projects.d.ts +19 -0
- package/dist/src/utils/claude-projects.d.ts.map +1 -0
- package/dist/src/utils/claude-projects.js +157 -0
- package/dist/src/utils/claude-projects.js.map +1 -0
- package/dist/src/utils/read-only-tools.d.ts +19 -0
- package/dist/src/utils/read-only-tools.d.ts.map +1 -0
- package/dist/src/utils/read-only-tools.js +132 -0
- package/dist/src/utils/read-only-tools.js.map +1 -0
- package/package.json +5 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/skills/_shared/proactive-routing.md +1 -0
- package/plugin/skills/architecture/SKILL.md +913 -0
- package/plugin/skills/blast-radius/SKILL.md +11 -1
- package/plugin/skills/diff-radius/SKILL.md +11 -0
- package/schemas/architecture-ir.schema.json +596 -0
- package/schemas/gestalt.schema.json +19 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
/**
|
|
4
|
+
* mtime이 마지막 확인 시각에서 이만큼 안쪽이면 stat이 같아도 다시 읽는다.
|
|
5
|
+
* 확인 직후 같은 mtime 해상도 안에서 다시 쓰인 파일은 size까지 같으면
|
|
6
|
+
* stat만으로 구분이 안 된다 (git의 racy-clean과 같은 문제다).
|
|
7
|
+
* FAT 계열이 2초 해상도라 그 폭에 맞췄다.
|
|
8
|
+
*/
|
|
9
|
+
export const RACY_WINDOW_MS = 2000;
|
|
10
|
+
export function hashContent(content) {
|
|
11
|
+
return createHash('sha256').update(content).digest('hex');
|
|
12
|
+
}
|
|
13
|
+
export function hasStructuralDrift(d) {
|
|
14
|
+
return d.added.length > 0 || d.modified.length > 0 || d.removed.length > 0;
|
|
15
|
+
}
|
|
16
|
+
export function hasAnyDrift(d) {
|
|
17
|
+
return hasStructuralDrift(d) || d.touched.length > 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 디스크의 현재 파일 목록과 store를 맞대 바뀐 파일을 가린다. store에는 쓰지 않는다.
|
|
21
|
+
*
|
|
22
|
+
* - size와 mtime이 둘 다 같으면 파일을 읽지 않는다
|
|
23
|
+
* - 하나라도 다르면 읽어서 해시로 확정한다
|
|
24
|
+
* - stat 행이 없고 노드만 있는 파일은 stat 컬럼이 생기기 전에 빌드된 DB다.
|
|
25
|
+
* 노드의 file_hash로 한 번 확정하고 나면 다음부터는 stat으로 넘어간다
|
|
26
|
+
*/
|
|
27
|
+
export function detectDrift(store, currentFiles) {
|
|
28
|
+
const start = Date.now();
|
|
29
|
+
const stats = store.getAllFileStats();
|
|
30
|
+
const graphFiles = new Set(store.getGraphFilePaths());
|
|
31
|
+
const report = {
|
|
32
|
+
added: [],
|
|
33
|
+
modified: [],
|
|
34
|
+
removed: [],
|
|
35
|
+
touched: [],
|
|
36
|
+
unchanged: 0,
|
|
37
|
+
durationMs: 0,
|
|
38
|
+
};
|
|
39
|
+
const current = new Set(currentFiles);
|
|
40
|
+
for (const filePath of currentFiles) {
|
|
41
|
+
let size;
|
|
42
|
+
let mtimeMs;
|
|
43
|
+
try {
|
|
44
|
+
const st = statSync(filePath);
|
|
45
|
+
size = st.size;
|
|
46
|
+
mtimeMs = st.mtimeMs;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// 목록을 뽑은 뒤 지워진 파일이다. 다음 검사에서 removed로 잡힌다
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const stamp = { filePath, size, mtimeMs };
|
|
53
|
+
const row = stats.get(filePath);
|
|
54
|
+
if (row) {
|
|
55
|
+
const racy = row.mtimeMs >= row.checkedAt - RACY_WINDOW_MS;
|
|
56
|
+
if (row.size === size && row.mtimeMs === mtimeMs && !racy) {
|
|
57
|
+
report.unchanged++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
classifyByHash(report, stamp, row.fileHash);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (graphFiles.has(filePath)) {
|
|
64
|
+
classifyByHash(report, stamp, store.getFileHash(filePath));
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
report.added.push(stamp);
|
|
68
|
+
}
|
|
69
|
+
for (const filePath of new Set([...stats.keys(), ...graphFiles])) {
|
|
70
|
+
if (!current.has(filePath))
|
|
71
|
+
report.removed.push(filePath);
|
|
72
|
+
}
|
|
73
|
+
report.durationMs = Date.now() - start;
|
|
74
|
+
return report;
|
|
75
|
+
}
|
|
76
|
+
function classifyByHash(report, stamp, knownHash) {
|
|
77
|
+
let hash;
|
|
78
|
+
try {
|
|
79
|
+
hash = hashContent(readFileSync(stamp.filePath, 'utf-8'));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// 못 읽으면 바뀐 걸로 보고 빌드에 넘긴다. 빌드가 skippedFiles로 남긴다
|
|
83
|
+
report.modified.push(stamp);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (knownHash !== null && hash === knownHash) {
|
|
87
|
+
report.touched.push({ ...stamp, fileHash: hash, checkedAt: Date.now() });
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
report.modified.push(stamp);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=freshness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freshness.js","sourceRoot":"","sources":["../../../src/code-graph/freshness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type RefreshSpawner = (repoRoot: string) => void;
|
|
2
|
+
/**
|
|
3
|
+
* 훅 엔트리를 `refresh` 인자로 다시 띄운다. 부모는 기다리지 않는다.
|
|
4
|
+
* 엔진은 typescript 파서까지 불러와 기동만 200ms를 넘게 먹으니 훅 프로세스 안에서 돌리지 않는다.
|
|
5
|
+
*
|
|
6
|
+
* MCP 질의가 재색인을 넘길 때는 `reindex`로 띄운다. 그쪽은 훅이 꺼져 있어도 돌아야 한다.
|
|
7
|
+
* execArgv는 tsx로 띄운 개발 서버가 .ts 엔트리를 넘길 때 로더를 물려주는 자리다.
|
|
8
|
+
*/
|
|
9
|
+
export declare function detachedRefreshSpawner(entry: string, command?: 'refresh' | 'reindex', execArgv?: string[]): RefreshSpawner;
|
|
10
|
+
/**
|
|
11
|
+
* 직전 요청에서 minIntervalMs가 안 지났거나 다른 프로세스가 갱신 락을 쥐고 있으면 안 띄운다.
|
|
12
|
+
* 연달아 Edit 하는 동안 갱신 프로세스가 줄줄이 뜨는 걸 막는다. 막힌 변경은
|
|
13
|
+
* 턴 끝의 Stop 훅이 다시 요청해서 반영한다.
|
|
14
|
+
*
|
|
15
|
+
* 띄웠으면 true.
|
|
16
|
+
*/
|
|
17
|
+
export declare function requestRefresh(repoRoot: string, spawner: RefreshSpawner, minIntervalMs: number, now?: number): boolean;
|
|
18
|
+
//# sourceMappingURL=background.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../../../src/code-graph/hooks/background.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,SAAS,GAAG,SAAqB,EAC1C,QAAQ,GAAE,MAAM,EAAO,GACtB,cAAc,CAUhB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,MAAM,EACrB,GAAG,SAAa,GACf,OAAO,CAoBT"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { mkdirSync, statSync, utimesSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { LOCK_STALE_MS } from '../lock.js';
|
|
5
|
+
import { hooksDir } from './state.js';
|
|
6
|
+
/**
|
|
7
|
+
* 훅 엔트리를 `refresh` 인자로 다시 띄운다. 부모는 기다리지 않는다.
|
|
8
|
+
* 엔진은 typescript 파서까지 불러와 기동만 200ms를 넘게 먹으니 훅 프로세스 안에서 돌리지 않는다.
|
|
9
|
+
*
|
|
10
|
+
* MCP 질의가 재색인을 넘길 때는 `reindex`로 띄운다. 그쪽은 훅이 꺼져 있어도 돌아야 한다.
|
|
11
|
+
* execArgv는 tsx로 띄운 개발 서버가 .ts 엔트리를 넘길 때 로더를 물려주는 자리다.
|
|
12
|
+
*/
|
|
13
|
+
export function detachedRefreshSpawner(entry, command = 'refresh', execArgv = []) {
|
|
14
|
+
return (repoRoot) => {
|
|
15
|
+
const child = spawn(process.execPath, [...execArgv, entry, command, repoRoot], {
|
|
16
|
+
detached: true,
|
|
17
|
+
stdio: 'ignore',
|
|
18
|
+
env: process.env,
|
|
19
|
+
});
|
|
20
|
+
child.on('error', () => { });
|
|
21
|
+
child.unref();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 직전 요청에서 minIntervalMs가 안 지났거나 다른 프로세스가 갱신 락을 쥐고 있으면 안 띄운다.
|
|
26
|
+
* 연달아 Edit 하는 동안 갱신 프로세스가 줄줄이 뜨는 걸 막는다. 막힌 변경은
|
|
27
|
+
* 턴 끝의 Stop 훅이 다시 요청해서 반영한다.
|
|
28
|
+
*
|
|
29
|
+
* 띄웠으면 true.
|
|
30
|
+
*/
|
|
31
|
+
export function requestRefresh(repoRoot, spawner, minIntervalMs, now = Date.now()) {
|
|
32
|
+
const stamp = join(hooksDir(repoRoot), 'refresh.stamp');
|
|
33
|
+
try {
|
|
34
|
+
if (now - statSync(stamp).mtimeMs < minIntervalMs)
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// 처음 요청한다
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
// 죽은 프로세스가 남긴 락이면 갱신이 영영 안 뜬다. 판정은 엔진 락과 같은 상한을 쓴다
|
|
42
|
+
const lock = statSync(join(repoRoot, '.gestalt', 'code-graph.lock'));
|
|
43
|
+
if (now - lock.mtimeMs < LOCK_STALE_MS)
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// 락이 없다
|
|
48
|
+
}
|
|
49
|
+
mkdirSync(hooksDir(repoRoot), { recursive: true });
|
|
50
|
+
writeFileSync(stamp, '');
|
|
51
|
+
utimesSync(stamp, now / 1000, now / 1000);
|
|
52
|
+
spawner(repoRoot);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=background.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.js","sourceRoot":"","sources":["../../../../src/code-graph/hooks/background.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAa,EACb,UAAiC,SAAS,EAC1C,WAAqB,EAAE;IAEvB,OAAO,CAAC,QAAQ,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE;YAC7E,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;YACf,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5B,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,OAAuB,EACvB,aAAqB,EACrB,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,IAAI,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,aAAa;YAAE,OAAO,KAAK,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,UAAU;IACZ,CAAC;IACD,IAAI,CAAC;QACH,mDAAmD;QACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACrE,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,aAAa;YAAE,OAAO,KAAK,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ;IACV,CAAC;IAED,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzB,UAAU,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { CodeGraphStore } from '../storage.js';
|
|
2
|
+
import { type CodeGraphNode } from '../types.js';
|
|
3
|
+
import { type PromptTokens } from './rank.js';
|
|
4
|
+
/**
|
|
5
|
+
* 프롬프트 하나를 파일 포인터 몇 개로 바꾼다. 훅과 평가 스크립트가 이 함수 하나를 같이 쓴다.
|
|
6
|
+
*
|
|
7
|
+
* 신호는 셋이다. 영문 식별자(심볼 이름과 경로), 한국어 bigram(주석과 커밋 메시지),
|
|
8
|
+
* 티켓 키. 셋 다 파일 단위로 모아 점수를 더한다. 같은 파일을 가리키는 서로 다른 신호는
|
|
9
|
+
* 서로를 보강해야 해서, 노드 단위로 따로 줄 세우면 그게 안 된다.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 관련성 게이트. 1위 점수가 이보다 낮으면 아무것도 안 넣는다.
|
|
13
|
+
* 흔한 토큰 하나만 맞은 경우(idf 2~3)는 여기서 걸린다. 드문 토큰 하나나 흔한 토큰 둘은 넘는다.
|
|
14
|
+
* 값은 hooks 테스트의 관련, 무관 프롬프트 쌍과 평가 스크립트로 정했다.
|
|
15
|
+
*/
|
|
16
|
+
export declare const MIN_POINTER_SCORE = 4;
|
|
17
|
+
/**
|
|
18
|
+
* 한글 내용어가 둘 이상인 프롬프트의 포인터가 넘어야 하는 점수를 IDF 최댓값 ln(1+N)의 배수로 둔다.
|
|
19
|
+
* 고정값으로 두면 커밋 수에 따라 뜻이 달라진다. N은 색인한 커밋 수와 주석 노드 수 중 큰 쪽이다.
|
|
20
|
+
*
|
|
21
|
+
* 영문으로 걸린 포인터에도 건다. 한국어 프롬프트에 섞인 영문은 `API`, `A/B`, `flag`처럼
|
|
22
|
+
* 흔한 기술 용어가 대부분이라서다. 모노레포 평가에서 영문 신호만의 정밀도가 2%였다.
|
|
23
|
+
* 배수는 gestalt(N≈430)와 모노레포(N≈8천) 시점 분할 평가에서 두 레포 모두
|
|
24
|
+
* 정밀도가 오르고 후속 응답 잡음이 내려가는 쪽으로 골랐다
|
|
25
|
+
*/
|
|
26
|
+
export declare const TEXT_PROMPT_IDF_MULTIPLE = 3.5;
|
|
27
|
+
export interface Pointer {
|
|
28
|
+
node: CodeGraphNode;
|
|
29
|
+
relPath: string;
|
|
30
|
+
score: number;
|
|
31
|
+
/** 통째 일치 가산을 뺀 점수. 상대 컷은 이걸로 건다 */
|
|
32
|
+
baseScore: number;
|
|
33
|
+
/** 맞은 영문 토큰 */
|
|
34
|
+
matched: string[];
|
|
35
|
+
/** 맞은 한글 어절, 프롬프트에 적힌 그대로 (프롬프트 순서) */
|
|
36
|
+
koWords: string[];
|
|
37
|
+
koSource?: 'commit' | 'comment';
|
|
38
|
+
/** 이 파일을 건드린 커밋 중 프롬프트와 비슷했던 수 */
|
|
39
|
+
koCommits?: number;
|
|
40
|
+
ticket?: {
|
|
41
|
+
key: string;
|
|
42
|
+
count: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface PointerOptions {
|
|
46
|
+
/** 평가용. 끄면 영문 신호만 쓴다. 한국어와 티켓 키를 같이 끈다 */
|
|
47
|
+
korean?: boolean;
|
|
48
|
+
exists?: (filePath: string) => boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare function rankPointers(store: CodeGraphStore, repoRoot: string, tokens: PromptTokens, limit: number, opts?: PointerOptions): Pointer[];
|
|
51
|
+
/**
|
|
52
|
+
* 점수만으로는 못 거르는 경우를 막는 증거 조건. 포인터마다 따로 보고 하나는 맞아야 남는다.
|
|
53
|
+
*
|
|
54
|
+
* - 티켓 키가 맞았다
|
|
55
|
+
* - 그 포인터에서 서로 다른 영문 토큰과 한글 어절을 합쳐 둘 이상 맞았다.
|
|
56
|
+
* 한국어만으로 걸렸으면 서로 다른 어절 둘이 맞아야 한다는 뜻이다
|
|
57
|
+
* - 프롬프트에 조각 둘 이상짜리 식별자가 통째로 적혔고 그게 고른 심볼 이름이다
|
|
58
|
+
*
|
|
59
|
+
* 포인터 셋을 합쳐 세면 "점심"이 한 파일에, "먹을지"가 다른 파일에 맞아도 통과한다.
|
|
60
|
+
* `push`나 `summarize`처럼 짧은 함수 이름도 드물어서 idf가 높아, 토큰 하나로 들어가면
|
|
61
|
+
* "push는 하지 마" 같은 프롬프트에 엉뚱한 파일이 붙는다.
|
|
62
|
+
*/
|
|
63
|
+
export declare function hasEnoughEvidence(p: Pointer, tokens: PromptTokens): boolean;
|
|
64
|
+
/** 주입 문구에 붙이는 "어떤 단어로 걸렸는지". 에이전트가 포인터를 얼마나 믿을지 가늠하게 한다 */
|
|
65
|
+
export declare function evidenceLabel(p: Pointer): string;
|
|
66
|
+
//# sourceMappingURL=pointers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointers.d.ts","sourceRoot":"","sources":["../../../../src/code-graph/hooks/pointers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAA+B,KAAK,YAAY,EAAmB,MAAM,WAAW,CAAC;AAE5F;;;;;;GAMG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAe5C,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uCAAuC;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAyID,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,cAAmB,GACxB,OAAO,EAAE,CA8GX;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAI3E;AAWD,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAQhD"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { basename, sep } from 'node:path';
|
|
3
|
+
import { NodeKind } from '../types.js';
|
|
4
|
+
import { scoreNodes, splitIdentifier } from './rank.js';
|
|
5
|
+
/**
|
|
6
|
+
* 프롬프트 하나를 파일 포인터 몇 개로 바꾼다. 훅과 평가 스크립트가 이 함수 하나를 같이 쓴다.
|
|
7
|
+
*
|
|
8
|
+
* 신호는 셋이다. 영문 식별자(심볼 이름과 경로), 한국어 bigram(주석과 커밋 메시지),
|
|
9
|
+
* 티켓 키. 셋 다 파일 단위로 모아 점수를 더한다. 같은 파일을 가리키는 서로 다른 신호는
|
|
10
|
+
* 서로를 보강해야 해서, 노드 단위로 따로 줄 세우면 그게 안 된다.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* 관련성 게이트. 1위 점수가 이보다 낮으면 아무것도 안 넣는다.
|
|
14
|
+
* 흔한 토큰 하나만 맞은 경우(idf 2~3)는 여기서 걸린다. 드문 토큰 하나나 흔한 토큰 둘은 넘는다.
|
|
15
|
+
* 값은 hooks 테스트의 관련, 무관 프롬프트 쌍과 평가 스크립트로 정했다.
|
|
16
|
+
*/
|
|
17
|
+
export const MIN_POINTER_SCORE = 4;
|
|
18
|
+
/**
|
|
19
|
+
* 한글 내용어가 둘 이상인 프롬프트의 포인터가 넘어야 하는 점수를 IDF 최댓값 ln(1+N)의 배수로 둔다.
|
|
20
|
+
* 고정값으로 두면 커밋 수에 따라 뜻이 달라진다. N은 색인한 커밋 수와 주석 노드 수 중 큰 쪽이다.
|
|
21
|
+
*
|
|
22
|
+
* 영문으로 걸린 포인터에도 건다. 한국어 프롬프트에 섞인 영문은 `API`, `A/B`, `flag`처럼
|
|
23
|
+
* 흔한 기술 용어가 대부분이라서다. 모노레포 평가에서 영문 신호만의 정밀도가 2%였다.
|
|
24
|
+
* 배수는 gestalt(N≈430)와 모노레포(N≈8천) 시점 분할 평가에서 두 레포 모두
|
|
25
|
+
* 정밀도가 오르고 후속 응답 잡음이 내려가는 쪽으로 골랐다
|
|
26
|
+
*/
|
|
27
|
+
export const TEXT_PROMPT_IDF_MULTIPLE = 3.5;
|
|
28
|
+
/** 티켓 키가 맞으면 다른 신호 없이도 1위가 되게 준다 */
|
|
29
|
+
const TICKET_SCORE = 12;
|
|
30
|
+
/** 흔한 bigram 하나가 수만 행을 끌고 오지 않게 막는 조회 상한 */
|
|
31
|
+
const MAX_TERM_HITS = 20_000;
|
|
32
|
+
/** 한 어절의 bigram 중 이만큼은 맞아야 그 어절이 걸린 것으로 친다 */
|
|
33
|
+
const EOJEOL_COVERAGE = 0.5;
|
|
34
|
+
/** 커밋 메시지 길이 보정(BM25의 k1, b). 본문이 긴 커밋이 단어 수만으로 이기지 않게 */
|
|
35
|
+
const BM25_K1 = 1.2;
|
|
36
|
+
const BM25_B = 0.75;
|
|
37
|
+
/** 프롬프트와 비슷한 커밋을 이만큼만 본다 */
|
|
38
|
+
const TOP_COMMITS = 20;
|
|
39
|
+
/** 한 파일에 걸린 커밋 점수를 더할 때 2등부터 깎는 비율 */
|
|
40
|
+
const COMMIT_DECAY = 0.5;
|
|
41
|
+
function isTestPath(relPath) {
|
|
42
|
+
return /(^|\/)(tests?|__tests__)\//.test(relPath) || /\.(test|spec)\./.test(relPath);
|
|
43
|
+
}
|
|
44
|
+
function fileNode(filePath, relPath) {
|
|
45
|
+
return {
|
|
46
|
+
id: `file:${filePath}`,
|
|
47
|
+
kind: NodeKind.File,
|
|
48
|
+
name: basename(filePath),
|
|
49
|
+
filePath,
|
|
50
|
+
lineStart: 1,
|
|
51
|
+
isTest: isTestPath(relPath),
|
|
52
|
+
updatedAt: 0,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** 어절마다 bigram 절반 이상이 맞아야 걸린 것으로 치고 걸린 어절의 IDF 합을 더한다 */
|
|
56
|
+
function matchEojeols(tokens, has, idf) {
|
|
57
|
+
let score = 0;
|
|
58
|
+
const words = new Set();
|
|
59
|
+
tokens.ko.forEach((e, i) => {
|
|
60
|
+
const hits = e.terms.filter(has);
|
|
61
|
+
if (hits.length === 0 || hits.length / e.terms.length < EOJEOL_COVERAGE)
|
|
62
|
+
return;
|
|
63
|
+
words.add(i);
|
|
64
|
+
score += hits.reduce((sum, t) => sum + idf(t), 0) / Math.sqrt(e.terms.length);
|
|
65
|
+
});
|
|
66
|
+
return { score, words };
|
|
67
|
+
}
|
|
68
|
+
/** 조회 행을 문서(노드나 커밋)마다 맞은 term 집합으로 묶는다 */
|
|
69
|
+
function groupHits(rows, key) {
|
|
70
|
+
const out = new Map();
|
|
71
|
+
for (const r of rows) {
|
|
72
|
+
const k = key(r);
|
|
73
|
+
let set = out.get(k);
|
|
74
|
+
if (!set)
|
|
75
|
+
out.set(k, (set = new Set()));
|
|
76
|
+
set.add(r.term);
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 한국어 신호를 노드(주석)와 파일(커밋) 단위 점수로 바꾼다.
|
|
82
|
+
*
|
|
83
|
+
* 어절마다 bigram의 절반 이상이 맞아야 그 어절이 걸린 것으로 친다. "해상도"의 bigram
|
|
84
|
+
* 하나("상도")만 다른 낱말에서 맞는 우연을 거르려는 것이다. 걸린 어절의 점수는 맞은
|
|
85
|
+
* bigram의 IDF 합을 bigram 수의 제곱근으로 나눈 값이다 — 긴 낱말이 짧은 낱말을 bigram
|
|
86
|
+
* 개수만으로 이기지 않게 한다.
|
|
87
|
+
*
|
|
88
|
+
* 커밋은 커밋 하나가 문서 하나다. 어절 둘 이상이 한 커밋 메시지에서 같이 맞아야 그 커밋을
|
|
89
|
+
* 쓴다. 비슷한 커밋을 몇 개 고른 뒤 그 커밋들이 건드린 파일에 점수를 나눠준다. 많은 파일을
|
|
90
|
+
* 건드린 커밋일수록 파일 하나에 가는 몫이 작다.
|
|
91
|
+
*/
|
|
92
|
+
function scoreKorean(store, tokens) {
|
|
93
|
+
const byNode = new Map();
|
|
94
|
+
const byFile = new Map();
|
|
95
|
+
const allTerms = [...new Set(tokens.ko.flatMap((e) => e.terms))];
|
|
96
|
+
if (allTerms.length === 0)
|
|
97
|
+
return { byNode, byFile, minScore: 0 };
|
|
98
|
+
const st = store.getTextTermStats(allTerms);
|
|
99
|
+
const minScore = Math.max(MIN_POINTER_SCORE, TEXT_PROMPT_IDF_MULTIPLE * Math.log(1 + Math.max(st.commits, st.docs)));
|
|
100
|
+
const idf = (n, df) => Math.log(1 + n / (1 + (df ?? 0)));
|
|
101
|
+
const docIdf = (t) => idf(st.docs, st.docDf.get(t));
|
|
102
|
+
const byDoc = groupHits(store.getDocTermHits(allTerms, MAX_TERM_HITS), (r) => r.nodeId);
|
|
103
|
+
for (const [nodeId, terms] of byDoc) {
|
|
104
|
+
const m = matchEojeols(tokens, (t) => terms.has(t), docIdf);
|
|
105
|
+
if (m.words.size > 0)
|
|
106
|
+
byNode.set(nodeId, { ...m, commits: 0 });
|
|
107
|
+
}
|
|
108
|
+
const commitIdf = (t) => idf(st.commits, st.commitDf.get(t));
|
|
109
|
+
const bySha = groupHits(store.getCommitTermHits(allTerms, MAX_TERM_HITS), (r) => r.sha);
|
|
110
|
+
const matched = [];
|
|
111
|
+
for (const [sha, terms] of bySha) {
|
|
112
|
+
const m = matchEojeols(tokens, (t) => terms.has(t), commitIdf);
|
|
113
|
+
if (m.words.size >= 2)
|
|
114
|
+
matched.push({ sha, ...m });
|
|
115
|
+
}
|
|
116
|
+
matched.sort((a, b) => b.score - a.score);
|
|
117
|
+
const top = matched.slice(0, TOP_COMMITS);
|
|
118
|
+
const info = new Map(store.getTextCommits(top.map((c) => c.sha)).map((c) => [c.sha, c]));
|
|
119
|
+
const shares = new Map();
|
|
120
|
+
for (const c of top) {
|
|
121
|
+
const meta = info.get(c.sha);
|
|
122
|
+
if (!meta || meta.files.length === 0)
|
|
123
|
+
continue;
|
|
124
|
+
const lenNorm = (BM25_K1 + 1) / (1 + BM25_K1 * (1 - BM25_B + (BM25_B * meta.terms) / st.avgCommitTerms));
|
|
125
|
+
const share = (c.score * lenNorm) / (1 + Math.log2(meta.files.length));
|
|
126
|
+
for (const f of meta.files) {
|
|
127
|
+
let s = shares.get(f);
|
|
128
|
+
if (!s)
|
|
129
|
+
shares.set(f, (s = { scores: [], words: new Set() }));
|
|
130
|
+
s.scores.push(share);
|
|
131
|
+
for (const w of c.words)
|
|
132
|
+
s.words.add(w);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const [file, s] of shares) {
|
|
136
|
+
s.scores.sort((a, b) => b - a);
|
|
137
|
+
const score = s.scores.reduce((sum, v, i) => sum + v * COMMIT_DECAY ** i, 0);
|
|
138
|
+
byFile.set(file, { score, words: s.words, commits: s.scores.length });
|
|
139
|
+
}
|
|
140
|
+
return { byNode, byFile, minScore };
|
|
141
|
+
}
|
|
142
|
+
export function rankPointers(store, repoRoot, tokens, limit, opts = {}) {
|
|
143
|
+
const korean = opts.korean ?? true;
|
|
144
|
+
const exists = opts.exists ?? existsSync;
|
|
145
|
+
const rel = (f) => (f.startsWith(repoRoot + sep) ? f.slice(repoRoot.length + 1) : f);
|
|
146
|
+
// 영문: 노드 단위 점수
|
|
147
|
+
const nodeScores = new Map();
|
|
148
|
+
if (tokens.parts.length > 0) {
|
|
149
|
+
const candidates = store.searchNodesByTokens(repoRoot, tokens.parts, 5000);
|
|
150
|
+
if (candidates.length > 0) {
|
|
151
|
+
for (const r of scoreNodes(repoRoot, candidates, tokens, store.getStats('').totalNodes)) {
|
|
152
|
+
nodeScores.set(r.node.id, { node: r.node, english: r });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// 한국어: 주석은 노드에, 커밋은 파일에
|
|
157
|
+
let byFileKo = new Map();
|
|
158
|
+
let minText = 0;
|
|
159
|
+
if (korean && tokens.ko.length > 0) {
|
|
160
|
+
const { byNode, byFile, minScore } = scoreKorean(store, tokens);
|
|
161
|
+
byFileKo = byFile;
|
|
162
|
+
// 한글 내용어가 한 어절뿐이면 영문 프롬프트에 한국어 토씨가 붙은 꼴이다. 문턱을 걸지 않는다
|
|
163
|
+
if (tokens.ko.length >= 2)
|
|
164
|
+
minText = minScore;
|
|
165
|
+
const missing = [...byNode.keys()].filter((id) => !nodeScores.has(id));
|
|
166
|
+
for (const node of store.getNodesByIds(missing))
|
|
167
|
+
nodeScores.set(node.id, { node });
|
|
168
|
+
for (const [id, hit] of byNode) {
|
|
169
|
+
const entry = nodeScores.get(id);
|
|
170
|
+
if (entry)
|
|
171
|
+
entry.ko = hit;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const files = new Map();
|
|
175
|
+
const agg = (filePath) => {
|
|
176
|
+
let a = files.get(filePath);
|
|
177
|
+
if (!a) {
|
|
178
|
+
a = { filePath };
|
|
179
|
+
files.set(filePath, a);
|
|
180
|
+
}
|
|
181
|
+
return a;
|
|
182
|
+
};
|
|
183
|
+
for (const { node, english, ko } of nodeScores.values()) {
|
|
184
|
+
let base = (english?.baseScore ?? 0) + (ko?.score ?? 0);
|
|
185
|
+
if (ko && !english && node.isTest)
|
|
186
|
+
base *= 0.7;
|
|
187
|
+
const score = base + (english ? english.score - english.baseScore : 0);
|
|
188
|
+
const a = agg(node.filePath);
|
|
189
|
+
if (!a.best || score > a.best.score) {
|
|
190
|
+
a.best = {
|
|
191
|
+
node,
|
|
192
|
+
score,
|
|
193
|
+
base,
|
|
194
|
+
matched: english?.matched ?? [],
|
|
195
|
+
koWords: ko?.words ?? new Set(),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const [filePath, hit] of byFileKo)
|
|
200
|
+
agg(filePath).commit = hit;
|
|
201
|
+
if (korean && tokens.tickets.length > 0) {
|
|
202
|
+
// 그 티켓으로 가장 많이 고친 파일만 남긴다. 후속 PR은 앞 PR과 다른 파일을 고치는 일이 많아
|
|
203
|
+
// 한두 번 걸친 파일까지 넣으면 정밀도가 깎인다 (모노레포 롤링 평가 41% → 44%)
|
|
204
|
+
const rows = store.getTicketFiles(tokens.tickets);
|
|
205
|
+
const max = Math.max(0, ...rows.map((t) => t.count));
|
|
206
|
+
for (const t of rows) {
|
|
207
|
+
if (t.count < max)
|
|
208
|
+
continue;
|
|
209
|
+
const a = agg(t.filePath);
|
|
210
|
+
if (!a.ticket)
|
|
211
|
+
a.ticket = { key: t.ticket, count: t.count };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const ranked = [];
|
|
215
|
+
for (const a of files.values()) {
|
|
216
|
+
const relPath = rel(a.filePath);
|
|
217
|
+
const testMul = isTestPath(relPath) ? 0.7 : 1;
|
|
218
|
+
const commitScore = (a.commit?.score ?? 0) * testMul;
|
|
219
|
+
const ticketScore = a.ticket ? TICKET_SCORE + Math.log2(1 + a.ticket.count) : 0;
|
|
220
|
+
const base = (a.best?.base ?? 0) + commitScore + ticketScore;
|
|
221
|
+
const score = (a.best?.score ?? 0) + commitScore + ticketScore;
|
|
222
|
+
const words = new Set([...(a.best?.koWords ?? []), ...(a.commit?.words ?? [])]);
|
|
223
|
+
ranked.push({
|
|
224
|
+
node: a.best?.node ?? fileNode(a.filePath, relPath),
|
|
225
|
+
relPath,
|
|
226
|
+
score,
|
|
227
|
+
baseScore: base,
|
|
228
|
+
matched: a.best?.matched ?? [],
|
|
229
|
+
koWords: [...words].sort((x, y) => x - y).map((i) => tokens.ko[i].surface),
|
|
230
|
+
koSource: a.commit ? 'commit' : a.best?.koWords.size ? 'comment' : undefined,
|
|
231
|
+
koCommits: a.commit?.commits,
|
|
232
|
+
ticket: a.ticket,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
ranked.sort((x, y) => y.score - x.score || x.relPath.localeCompare(y.relPath));
|
|
236
|
+
// 한글 내용어가 둘 이상인 프롬프트면 포인터마다 문턱을 넘어야 한다. 티켓 키나 식별자를 통째로 적은 경우는
|
|
237
|
+
// 사람이 대상을 짚은 것이라 문턱과 상관없이 둔다. 그 밖에는 1위만 MIN_POINTER_SCORE를
|
|
238
|
+
// 넘으면 되고 나머지는 상대 컷으로만 거른다
|
|
239
|
+
const passes = (p) => hasEnoughEvidence(p, tokens) && (p.score >= minText || !!p.ticket || namedExactly(p, tokens));
|
|
240
|
+
const top = ranked[0];
|
|
241
|
+
if (!top || top.score < MIN_POINTER_SCORE)
|
|
242
|
+
return [];
|
|
243
|
+
// 1위의 절반에 못 미치는 건 버린다. 이력에만 남고 지워진 파일도 여기서 거른다
|
|
244
|
+
const picks = [];
|
|
245
|
+
for (const r of ranked) {
|
|
246
|
+
if (r.baseScore < top.baseScore * 0.5)
|
|
247
|
+
continue;
|
|
248
|
+
if (!passes(r) || !exists(r.node.filePath))
|
|
249
|
+
continue;
|
|
250
|
+
picks.push(r);
|
|
251
|
+
if (picks.length >= limit)
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
return picks;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* 점수만으로는 못 거르는 경우를 막는 증거 조건. 포인터마다 따로 보고 하나는 맞아야 남는다.
|
|
258
|
+
*
|
|
259
|
+
* - 티켓 키가 맞았다
|
|
260
|
+
* - 그 포인터에서 서로 다른 영문 토큰과 한글 어절을 합쳐 둘 이상 맞았다.
|
|
261
|
+
* 한국어만으로 걸렸으면 서로 다른 어절 둘이 맞아야 한다는 뜻이다
|
|
262
|
+
* - 프롬프트에 조각 둘 이상짜리 식별자가 통째로 적혔고 그게 고른 심볼 이름이다
|
|
263
|
+
*
|
|
264
|
+
* 포인터 셋을 합쳐 세면 "점심"이 한 파일에, "먹을지"가 다른 파일에 맞아도 통과한다.
|
|
265
|
+
* `push`나 `summarize`처럼 짧은 함수 이름도 드물어서 idf가 높아, 토큰 하나로 들어가면
|
|
266
|
+
* "push는 하지 마" 같은 프롬프트에 엉뚱한 파일이 붙는다.
|
|
267
|
+
*/
|
|
268
|
+
export function hasEnoughEvidence(p, tokens) {
|
|
269
|
+
if (p.ticket)
|
|
270
|
+
return true;
|
|
271
|
+
if (new Set(p.matched).size + p.koWords.length >= 2)
|
|
272
|
+
return true;
|
|
273
|
+
return namedExactly(p, tokens);
|
|
274
|
+
}
|
|
275
|
+
/** 프롬프트에 조각 둘 이상짜리 식별자가 통째로 적혔고 그게 이 포인터의 심볼 이름이다 */
|
|
276
|
+
function namedExactly(p, tokens) {
|
|
277
|
+
return (p.node.kind !== NodeKind.File &&
|
|
278
|
+
splitIdentifier(p.node.name).length >= 2 &&
|
|
279
|
+
tokens.wholeNames.has(p.node.name.toLowerCase()));
|
|
280
|
+
}
|
|
281
|
+
/** 주입 문구에 붙이는 "어떤 단어로 걸렸는지". 에이전트가 포인터를 얼마나 믿을지 가늠하게 한다 */
|
|
282
|
+
export function evidenceLabel(p) {
|
|
283
|
+
const parts = [];
|
|
284
|
+
if (p.ticket)
|
|
285
|
+
parts.push(`티켓 ${p.ticket.key} ${p.ticket.count}건`);
|
|
286
|
+
if (p.koWords.length > 0) {
|
|
287
|
+
const words = `"${p.koWords.slice(0, 3).join(' ')}"`;
|
|
288
|
+
parts.push(p.koSource === 'commit' ? `커밋 ${words} ${p.koCommits ?? 0}건` : `주석 ${words}`);
|
|
289
|
+
}
|
|
290
|
+
return parts.length > 0 ? ` (${parts.join(', ')})` : '';
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=pointers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointers.js","sourceRoot":"","sources":["../../../../src/code-graph/hooks/pointers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAsC,MAAM,WAAW,CAAC;AAE5F;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAC5C,oCAAoC;AACpC,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,4CAA4C;AAC5C,MAAM,aAAa,GAAG,MAAM,CAAC;AAC7B,8CAA8C;AAC9C,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,0DAA0D;AAC1D,MAAM,OAAO,GAAG,GAAG,CAAC;AACpB,MAAM,MAAM,GAAG,IAAI,CAAC;AACpB,4BAA4B;AAC5B,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,sCAAsC;AACtC,MAAM,YAAY,GAAG,GAAG,CAAC;AAwBzB,SAAS,UAAU,CAAC,OAAe;IACjC,OAAO,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB,EAAE,OAAe;IACjD,OAAO;QACL,EAAE,EAAE,QAAQ,QAAQ,EAAE;QACtB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC;QACxB,QAAQ;QACR,SAAS,EAAE,CAAC;QACZ,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC;QAC3B,SAAS,EAAE,CAAC;KACb,CAAC;AACJ,CAAC;AAQD,yDAAyD;AACzD,SAAS,YAAY,CACnB,MAAoB,EACpB,GAA8B,EAC9B,GAA6B;IAE7B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,eAAe;YAAE,OAAO;QAChF,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACb,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED,0CAA0C;AAC1C,SAAS,SAAS,CAChB,IAAS,EACT,GAAqB;IAErB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG;YAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QACxC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,WAAW,CAClB,KAAqB,EACrB,MAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAElE,MAAM,EAAE,GAAG,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACvB,iBAAiB,EACjB,wBAAwB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CACvE,CAAC;IACF,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAErF,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACxF,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxF,MAAM,OAAO,GAAyD,EAAE,CAAC;IACzE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoD,CAAC;IAC3E,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC/C,MAAM,OAAO,GACX,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YAC9D,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK;gBAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;QAC/B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,YAAY,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC;AAgBD,MAAM,UAAU,YAAY,CAC1B,KAAqB,EACrB,QAAgB,EAChB,MAAoB,EACpB,KAAa,EACb,OAAuB,EAAE;IAEzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC;IACzC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7F,eAAe;IACf,MAAM,UAAU,GAAG,IAAI,GAAG,EAAqE,CAAC;IAChG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxF,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,IAAI,QAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;IACxC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAChE,QAAQ,GAAG,MAAM,CAAC;QAClB,sDAAsD;QACtD,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,GAAG,QAAQ,CAAC;QAC9C,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,KAAK;gBAAE,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IACzC,MAAM,GAAG,GAAG,CAAC,QAAgB,EAAE,EAAE;QAC/B,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC;YACjB,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IAEF,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACxD,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;QACxD,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,IAAI,GAAG,CAAC;QAC/C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACpC,CAAC,CAAC,IAAI,GAAG;gBACP,IAAI;gBACJ,KAAK;gBACL,IAAI;gBACJ,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,IAAI,IAAI,GAAG,EAAE;aAChC,CAAC;QACJ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,QAAQ;QAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC;IACnE,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,yDAAyD;QACzD,mDAAmD;QACnD,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,CAAC,KAAK,GAAG,GAAG;gBAAE,SAAS;YAC5B,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC1B,IAAI,CAAC,CAAC,CAAC,MAAM;gBAAE,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC;QACrD,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,GAAG,WAAW,GAAG,WAAW,CAAC;QAC7D,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,WAAW,GAAG,WAAW,CAAC;QAC/D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC;YACnD,OAAO;YACP,KAAK;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE;YAC9B,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC;YAC3E,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC5E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO;YAC5B,MAAM,EAAE,CAAC,CAAC,MAAM;SACjB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAE/E,8DAA8D;IAC9D,2DAA2D;IAC3D,0BAA0B;IAC1B,MAAM,MAAM,GAAG,CAAC,CAAU,EAAE,EAAE,CAC5B,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAChG,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,GAAG,iBAAiB;QAAE,OAAO,EAAE,CAAC;IAErD,+CAA+C;IAC/C,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,GAAG,GAAG;YAAE,SAAS;QAChD,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,SAAS;QACrD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAU,EAAE,MAAoB;IAChE,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACjE,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,qDAAqD;AACrD,SAAS,YAAY,CAAC,CAAU,EAAE,MAAoB;IACpD,OAAO,CACL,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;QAC7B,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC;QACxC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CACjD,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAClE,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type CodeGraphNode } from '../types.js';
|
|
2
|
+
import { type KoEojeol } from '../ko-text.js';
|
|
3
|
+
/** camelCase, snake_case, kebab-case, 경로 구분자를 쪼개 소문자 조각으로 돌려준다 */
|
|
4
|
+
export declare function splitIdentifier(name: string): string[];
|
|
5
|
+
export interface PromptTokens {
|
|
6
|
+
/** 조각 단위 토큰 (stem 적용) */
|
|
7
|
+
parts: string[];
|
|
8
|
+
/** 프롬프트에 식별자 통째로 적힌 이름 (소문자, 4자 이상) */
|
|
9
|
+
wholeNames: Set<string>;
|
|
10
|
+
/** 한글 어절. 줄기와 bigram */
|
|
11
|
+
ko: KoEojeol[];
|
|
12
|
+
/** `CT-31408` 꼴 티켓 키 */
|
|
13
|
+
tickets: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function tokenizePrompt(prompt: string): PromptTokens;
|
|
16
|
+
export interface RankedNode {
|
|
17
|
+
node: CodeGraphNode;
|
|
18
|
+
relPath: string;
|
|
19
|
+
score: number;
|
|
20
|
+
/** 통째 일치 가산을 뺀 점수. 상대 컷은 이걸로 건다 */
|
|
21
|
+
baseScore: number;
|
|
22
|
+
matched: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 후보 노드마다 점수를 매긴다. 점수는 맞은 토큰의 IDF 합이다.
|
|
26
|
+
*
|
|
27
|
+
* - 이름에서 맞은 토큰은 그대로, 경로에서만 맞은 토큰은 절반만 친다. 경로 조각은 같은
|
|
28
|
+
* 디렉토리 파일 전부가 공유해서 그것만으로는 어느 파일인지 못 가린다
|
|
29
|
+
* - 이름 조각을 많이 덮을수록 더 준다. `refresh`는 `refresh`에 `refreshIndexCache`보다 가깝다
|
|
30
|
+
* - 프롬프트에 이름이 통째로 적혔으면 가산한다
|
|
31
|
+
* - 테스트 파일은 깎는다. 사용자가 고치려는 건 대개 구현 쪽이다
|
|
32
|
+
*
|
|
33
|
+
* idf의 N은 전체 노드 수다. 후보 수로 잡으면 후보가 적은 질의일수록 흔한 토큰이 귀해 보인다.
|
|
34
|
+
*/
|
|
35
|
+
export declare function scoreNodes(repoRoot: string, candidates: CodeGraphNode[], tokens: PromptTokens, totalNodes: number): RankedNode[];
|
|
36
|
+
//# sourceMappingURL=rank.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rank.d.ts","sourceRoot":"","sources":["../../../../src/code-graph/hooks/rank.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAiC,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAsH7E,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOtD;AAED,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uCAAuC;IACvC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,wBAAwB;IACxB,EAAE,EAAE,QAAQ,EAAE,CAAC;IACf,wBAAwB;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAqB3D;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,aAAa,EAAE,EAC3B,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,GACjB,UAAU,EAAE,CA0Cd"}
|