kiri-mcp-server 0.9.9 → 0.11.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/README.md +60 -7
- package/config/scoring-profiles.yml +82 -35
- package/dist/config/scoring-profiles.yml +82 -35
- package/dist/package.json +12 -1
- package/dist/src/client/proxy.js +81 -12
- package/dist/src/client/proxy.js.map +1 -1
- package/dist/src/daemon/daemon.js +91 -14
- package/dist/src/daemon/daemon.js.map +1 -1
- package/dist/src/indexer/cli.d.ts.map +1 -1
- package/dist/src/indexer/cli.js +712 -98
- package/dist/src/indexer/cli.js.map +1 -1
- package/dist/src/indexer/git.d.ts.map +1 -1
- package/dist/src/indexer/git.js +41 -3
- package/dist/src/indexer/git.js.map +1 -1
- package/dist/src/indexer/migrations/repo-merger.d.ts +33 -0
- package/dist/src/indexer/migrations/repo-merger.d.ts.map +1 -0
- package/dist/src/indexer/migrations/repo-merger.js +67 -0
- package/dist/src/indexer/migrations/repo-merger.js.map +1 -0
- package/dist/src/indexer/schema.d.ts +66 -0
- package/dist/src/indexer/schema.d.ts.map +1 -1
- package/dist/src/indexer/schema.js +337 -0
- package/dist/src/indexer/schema.js.map +1 -1
- package/dist/src/server/abbreviations.d.ts +47 -0
- package/dist/src/server/abbreviations.d.ts.map +1 -0
- package/dist/src/server/abbreviations.js +71 -0
- package/dist/src/server/abbreviations.js.map +1 -0
- package/dist/src/server/boost-profiles.d.ts +63 -0
- package/dist/src/server/boost-profiles.d.ts.map +1 -0
- package/dist/src/server/boost-profiles.js +202 -0
- package/dist/src/server/boost-profiles.js.map +1 -0
- package/dist/src/server/config.d.ts +45 -0
- package/dist/src/server/config.d.ts.map +1 -0
- package/dist/src/server/config.js +146 -0
- package/dist/src/server/config.js.map +1 -0
- package/dist/src/server/context.d.ts +29 -0
- package/dist/src/server/context.d.ts.map +1 -1
- package/dist/src/server/context.js +26 -1
- package/dist/src/server/context.js.map +1 -1
- package/dist/src/server/handlers/snippets-get.d.ts +36 -0
- package/dist/src/server/handlers/snippets-get.d.ts.map +1 -0
- package/dist/src/server/handlers/snippets-get.js +120 -0
- package/dist/src/server/handlers/snippets-get.js.map +1 -0
- package/dist/src/server/handlers.d.ts +35 -22
- package/dist/src/server/handlers.d.ts.map +1 -1
- package/dist/src/server/handlers.js +1993 -414
- package/dist/src/server/handlers.js.map +1 -1
- package/dist/src/server/indexBootstrap.d.ts.map +1 -1
- package/dist/src/server/indexBootstrap.js +49 -2
- package/dist/src/server/indexBootstrap.js.map +1 -1
- package/dist/src/server/main.d.ts.map +1 -1
- package/dist/src/server/main.js +119 -30
- package/dist/src/server/main.js.map +1 -1
- package/dist/src/server/profile-selector.d.ts +33 -0
- package/dist/src/server/profile-selector.d.ts.map +1 -0
- package/dist/src/server/profile-selector.js +291 -0
- package/dist/src/server/profile-selector.js.map +1 -0
- package/dist/src/server/rpc.d.ts.map +1 -1
- package/dist/src/server/rpc.js +61 -12
- package/dist/src/server/rpc.js.map +1 -1
- package/dist/src/server/rrf.d.ts +86 -0
- package/dist/src/server/rrf.d.ts.map +1 -0
- package/dist/src/server/rrf.js +108 -0
- package/dist/src/server/rrf.js.map +1 -0
- package/dist/src/server/runtime.d.ts.map +1 -1
- package/dist/src/server/runtime.js +14 -4
- package/dist/src/server/runtime.js.map +1 -1
- package/dist/src/server/scoring.d.ts +7 -1
- package/dist/src/server/scoring.d.ts.map +1 -1
- package/dist/src/server/scoring.js +121 -2
- package/dist/src/server/scoring.js.map +1 -1
- package/dist/src/server/services/index.d.ts +24 -0
- package/dist/src/server/services/index.d.ts.map +1 -0
- package/dist/src/server/services/index.js +20 -0
- package/dist/src/server/services/index.js.map +1 -0
- package/dist/src/server/services/repo-repository.d.ts +61 -0
- package/dist/src/server/services/repo-repository.d.ts.map +1 -0
- package/dist/src/server/services/repo-repository.js +93 -0
- package/dist/src/server/services/repo-repository.js.map +1 -0
- package/dist/src/server/services/repo-resolver.d.ts +28 -0
- package/dist/src/server/services/repo-resolver.d.ts.map +1 -0
- package/dist/src/server/services/repo-resolver.js +62 -0
- package/dist/src/server/services/repo-resolver.js.map +1 -0
- package/dist/src/shared/cli/args.d.ts +70 -0
- package/dist/src/shared/cli/args.d.ts.map +1 -0
- package/dist/src/shared/cli/args.js +84 -0
- package/dist/src/shared/cli/args.js.map +1 -0
- package/dist/src/shared/duckdb.d.ts.map +1 -1
- package/dist/src/shared/duckdb.js +21 -1
- package/dist/src/shared/duckdb.js.map +1 -1
- package/dist/src/shared/embedding/engine.d.ts +38 -0
- package/dist/src/shared/embedding/engine.d.ts.map +1 -0
- package/dist/src/shared/embedding/engine.js +6 -0
- package/dist/src/shared/embedding/engine.js.map +1 -0
- package/dist/src/shared/embedding/lsh-engine.d.ts +11 -0
- package/dist/src/shared/embedding/lsh-engine.d.ts.map +1 -0
- package/dist/src/shared/embedding/lsh-engine.js +14 -0
- package/dist/src/shared/embedding/lsh-engine.js.map +1 -0
- package/dist/src/shared/embedding/registry.d.ts +25 -0
- package/dist/src/shared/embedding/registry.d.ts.map +1 -0
- package/dist/src/shared/embedding/registry.js +50 -0
- package/dist/src/shared/embedding/registry.js.map +1 -0
- package/dist/src/shared/embedding/semantic-engine.d.ts +14 -0
- package/dist/src/shared/embedding/semantic-engine.d.ts.map +1 -0
- package/dist/src/shared/embedding/semantic-engine.js +50 -0
- package/dist/src/shared/embedding/semantic-engine.js.map +1 -0
- package/dist/src/shared/fs/safePath.d.ts +7 -0
- package/dist/src/shared/fs/safePath.d.ts.map +1 -0
- package/dist/src/shared/fs/safePath.js +23 -0
- package/dist/src/shared/fs/safePath.js.map +1 -0
- package/dist/src/shared/models/model-manager.d.ts +38 -0
- package/dist/src/shared/models/model-manager.d.ts.map +1 -0
- package/dist/src/shared/models/model-manager.js +116 -0
- package/dist/src/shared/models/model-manager.js.map +1 -0
- package/dist/src/shared/models/model-manifest.d.ts +22 -0
- package/dist/src/shared/models/model-manifest.d.ts.map +1 -0
- package/dist/src/shared/models/model-manifest.js +24 -0
- package/dist/src/shared/models/model-manifest.js.map +1 -0
- package/dist/src/shared/utils/glob.d.ts +5 -0
- package/dist/src/shared/utils/glob.d.ts.map +1 -0
- package/dist/src/shared/utils/glob.js +22 -0
- package/dist/src/shared/utils/glob.js.map +1 -0
- package/dist/src/shared/utils/retry.d.ts +8 -0
- package/dist/src/shared/utils/retry.d.ts.map +1 -0
- package/dist/src/shared/utils/retry.js +20 -0
- package/dist/src/shared/utils/retry.js.map +1 -0
- package/dist/src/shared/utils/validation.d.ts +14 -0
- package/dist/src/shared/utils/validation.d.ts.map +1 -0
- package/dist/src/shared/utils/validation.js +22 -0
- package/dist/src/shared/utils/validation.js.map +1 -0
- package/package.json +29 -20
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { parseSimpleYaml } from "../shared/utils/simpleYaml.js";
|
|
@@ -22,16 +22,75 @@ function validateWeights(weights, profileName) {
|
|
|
22
22
|
"docPenaltyMultiplier",
|
|
23
23
|
"configPenaltyMultiplier",
|
|
24
24
|
"implBoostMultiplier",
|
|
25
|
+
"blacklistPenaltyMultiplier",
|
|
26
|
+
"testPenaltyMultiplier",
|
|
27
|
+
"lockPenaltyMultiplier",
|
|
25
28
|
];
|
|
26
29
|
const obj = weights;
|
|
30
|
+
// v1.0.0: Provide default values for new fields (backward compatibility)
|
|
31
|
+
if (obj.blacklistPenaltyMultiplier === undefined) {
|
|
32
|
+
console.warn(`[KIRI] Profile '${profileName}' missing blacklistPenaltyMultiplier, using default 0.01`);
|
|
33
|
+
obj.blacklistPenaltyMultiplier = 0.01;
|
|
34
|
+
}
|
|
35
|
+
if (obj.testPenaltyMultiplier === undefined) {
|
|
36
|
+
console.warn(`[KIRI] Profile '${profileName}' missing testPenaltyMultiplier, using default 0.02`);
|
|
37
|
+
obj.testPenaltyMultiplier = 0.02;
|
|
38
|
+
}
|
|
39
|
+
if (obj.lockPenaltyMultiplier === undefined) {
|
|
40
|
+
console.warn(`[KIRI] Profile '${profileName}' missing lockPenaltyMultiplier, using default 0.01`);
|
|
41
|
+
obj.lockPenaltyMultiplier = 0.01;
|
|
42
|
+
}
|
|
27
43
|
for (const key of required) {
|
|
28
44
|
const value = obj[key];
|
|
29
45
|
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
30
46
|
throw new Error(`Profile '${profileName}' has invalid ${key}: ${String(value)}. Must be a non-negative finite number.`);
|
|
31
47
|
}
|
|
32
48
|
}
|
|
49
|
+
if (obj.docPenaltyMultiplier > 1) {
|
|
50
|
+
throw new Error(`Profile '${profileName}' has docPenaltyMultiplier > 1 (${obj.docPenaltyMultiplier}). Penalties must be ≤ 1.`);
|
|
51
|
+
}
|
|
52
|
+
if (obj.configPenaltyMultiplier > 1) {
|
|
53
|
+
throw new Error(`Profile '${profileName}' has configPenaltyMultiplier > 1 (${obj.configPenaltyMultiplier}). Penalties must be ≤ 1.`);
|
|
54
|
+
}
|
|
55
|
+
if (obj.implBoostMultiplier < 1) {
|
|
56
|
+
throw new Error(`Profile '${profileName}' has implBoostMultiplier < 1 (${obj.implBoostMultiplier}). Boost multipliers must be ≥ 1.`);
|
|
57
|
+
}
|
|
58
|
+
if (obj.blacklistPenaltyMultiplier > 1) {
|
|
59
|
+
throw new Error(`Profile '${profileName}' has blacklistPenaltyMultiplier > 1 (${obj.blacklistPenaltyMultiplier}). Penalties must be ≤ 1.`);
|
|
60
|
+
}
|
|
61
|
+
if (obj.testPenaltyMultiplier > 1) {
|
|
62
|
+
throw new Error(`Profile '${profileName}' has testPenaltyMultiplier > 1 (${obj.testPenaltyMultiplier}). Penalties must be ≤ 1.`);
|
|
63
|
+
}
|
|
64
|
+
if (obj.lockPenaltyMultiplier > 1) {
|
|
65
|
+
throw new Error(`Profile '${profileName}' has lockPenaltyMultiplier > 1 (${obj.lockPenaltyMultiplier}). Penalties must be ≤ 1.`);
|
|
66
|
+
}
|
|
67
|
+
const totalWeight = obj.textMatch +
|
|
68
|
+
obj.pathMatch +
|
|
69
|
+
obj.editingPath +
|
|
70
|
+
obj.dependency +
|
|
71
|
+
obj.proximity +
|
|
72
|
+
obj.structural;
|
|
73
|
+
if (totalWeight < 2 || totalWeight > 15) {
|
|
74
|
+
console.warn(`Profile '${profileName}' has unusual aggregate weight ${totalWeight.toFixed(2)}. Review weight balance if this was unintentional.`);
|
|
75
|
+
}
|
|
33
76
|
return weights;
|
|
34
77
|
}
|
|
78
|
+
function resolveScoringConfigPath(currentDir) {
|
|
79
|
+
const envPath = process.env.KIRI_SCORING_CONFIG;
|
|
80
|
+
const candidates = [
|
|
81
|
+
envPath,
|
|
82
|
+
join(process.cwd(), "config/scoring-profiles.yml"),
|
|
83
|
+
join(currentDir, "../../../config/scoring-profiles.yml"),
|
|
84
|
+
join(currentDir, "../../../../config/scoring-profiles.yml"),
|
|
85
|
+
].filter((candidate) => Boolean(candidate));
|
|
86
|
+
for (const candidate of candidates) {
|
|
87
|
+
if (existsSync(candidate)) {
|
|
88
|
+
return candidate;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`Scoring profiles config not found. Checked paths: ${candidates.join(", ")}. ` +
|
|
92
|
+
"Set KIRI_SCORING_CONFIG or place config/scoring-profiles.yml in the repo root.");
|
|
93
|
+
}
|
|
35
94
|
function loadProfilesFromConfig() {
|
|
36
95
|
if (profilesCache) {
|
|
37
96
|
return profilesCache;
|
|
@@ -40,7 +99,7 @@ function loadProfilesFromConfig() {
|
|
|
40
99
|
// 環境変数でカスタムパスを指定可能
|
|
41
100
|
// 開発環境(src/)と本番環境(dist/src/)の両方で動作するようにdirname(__filename)から相対パス解決
|
|
42
101
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
43
|
-
const configPath =
|
|
102
|
+
const configPath = resolveScoringConfigPath(__dirname);
|
|
44
103
|
const configContent = readFileSync(configPath, "utf-8");
|
|
45
104
|
const parsed = parseSimpleYaml(configContent);
|
|
46
105
|
// 必須プロファイルの検証とウェイトのバリデーション
|
|
@@ -50,6 +109,9 @@ function loadProfilesFromConfig() {
|
|
|
50
109
|
"testfail",
|
|
51
110
|
"typeerror",
|
|
52
111
|
"feature",
|
|
112
|
+
"debug",
|
|
113
|
+
"api",
|
|
114
|
+
"editor",
|
|
53
115
|
];
|
|
54
116
|
const validated = {};
|
|
55
117
|
for (const profile of requiredProfiles) {
|
|
@@ -75,6 +137,51 @@ function loadProfilesFromConfig() {
|
|
|
75
137
|
docPenaltyMultiplier: 0.5,
|
|
76
138
|
configPenaltyMultiplier: 0.05,
|
|
77
139
|
implBoostMultiplier: 1.3,
|
|
140
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
141
|
+
testPenaltyMultiplier: 0.02,
|
|
142
|
+
lockPenaltyMultiplier: 0.01,
|
|
143
|
+
},
|
|
144
|
+
debug: {
|
|
145
|
+
textMatch: 1.0,
|
|
146
|
+
pathMatch: 1.3,
|
|
147
|
+
editingPath: 1.7,
|
|
148
|
+
dependency: 1.2,
|
|
149
|
+
proximity: 0.35,
|
|
150
|
+
structural: 0.9,
|
|
151
|
+
docPenaltyMultiplier: 0.5,
|
|
152
|
+
configPenaltyMultiplier: 0.05,
|
|
153
|
+
implBoostMultiplier: 1.45,
|
|
154
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
155
|
+
testPenaltyMultiplier: 0.02,
|
|
156
|
+
lockPenaltyMultiplier: 0.01,
|
|
157
|
+
},
|
|
158
|
+
api: {
|
|
159
|
+
textMatch: 1.0,
|
|
160
|
+
pathMatch: 1.5,
|
|
161
|
+
editingPath: 1.8,
|
|
162
|
+
dependency: 1.0,
|
|
163
|
+
proximity: 0.3,
|
|
164
|
+
structural: 0.95,
|
|
165
|
+
docPenaltyMultiplier: 0.55,
|
|
166
|
+
configPenaltyMultiplier: 0.05,
|
|
167
|
+
implBoostMultiplier: 1.4,
|
|
168
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
169
|
+
testPenaltyMultiplier: 0.02,
|
|
170
|
+
lockPenaltyMultiplier: 0.01,
|
|
171
|
+
},
|
|
172
|
+
editor: {
|
|
173
|
+
textMatch: 1.0,
|
|
174
|
+
pathMatch: 1.4,
|
|
175
|
+
editingPath: 1.9,
|
|
176
|
+
dependency: 1.0,
|
|
177
|
+
proximity: 0.4,
|
|
178
|
+
structural: 0.9,
|
|
179
|
+
docPenaltyMultiplier: 0.6,
|
|
180
|
+
configPenaltyMultiplier: 0.05,
|
|
181
|
+
implBoostMultiplier: 1.4,
|
|
182
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
183
|
+
testPenaltyMultiplier: 0.02,
|
|
184
|
+
lockPenaltyMultiplier: 0.01,
|
|
78
185
|
},
|
|
79
186
|
bugfix: {
|
|
80
187
|
textMatch: 1.0,
|
|
@@ -86,6 +193,9 @@ function loadProfilesFromConfig() {
|
|
|
86
193
|
docPenaltyMultiplier: 0.5,
|
|
87
194
|
configPenaltyMultiplier: 0.05,
|
|
88
195
|
implBoostMultiplier: 1.3,
|
|
196
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
197
|
+
testPenaltyMultiplier: 0.02,
|
|
198
|
+
lockPenaltyMultiplier: 0.01,
|
|
89
199
|
},
|
|
90
200
|
testfail: {
|
|
91
201
|
textMatch: 1.0,
|
|
@@ -97,6 +207,9 @@ function loadProfilesFromConfig() {
|
|
|
97
207
|
docPenaltyMultiplier: 0.5,
|
|
98
208
|
configPenaltyMultiplier: 0.05,
|
|
99
209
|
implBoostMultiplier: 1.3,
|
|
210
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
211
|
+
testPenaltyMultiplier: 0.2,
|
|
212
|
+
lockPenaltyMultiplier: 0.01,
|
|
100
213
|
},
|
|
101
214
|
typeerror: {
|
|
102
215
|
textMatch: 1.0,
|
|
@@ -108,6 +221,9 @@ function loadProfilesFromConfig() {
|
|
|
108
221
|
docPenaltyMultiplier: 0.5,
|
|
109
222
|
configPenaltyMultiplier: 0.05,
|
|
110
223
|
implBoostMultiplier: 1.3,
|
|
224
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
225
|
+
testPenaltyMultiplier: 0.02,
|
|
226
|
+
lockPenaltyMultiplier: 0.01,
|
|
111
227
|
},
|
|
112
228
|
feature: {
|
|
113
229
|
textMatch: 1.0,
|
|
@@ -119,6 +235,9 @@ function loadProfilesFromConfig() {
|
|
|
119
235
|
docPenaltyMultiplier: 0.5,
|
|
120
236
|
configPenaltyMultiplier: 0.05,
|
|
121
237
|
implBoostMultiplier: 1.3,
|
|
238
|
+
blacklistPenaltyMultiplier: 0.01,
|
|
239
|
+
testPenaltyMultiplier: 0.02,
|
|
240
|
+
lockPenaltyMultiplier: 0.01,
|
|
122
241
|
},
|
|
123
242
|
};
|
|
124
243
|
return profilesCache;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../../src/server/scoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../../src/server/scoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DuckDBClient } from "../../shared/duckdb.js";
|
|
2
|
+
import { RepoRepository } from "./repo-repository.js";
|
|
3
|
+
import { RepoResolver } from "./repo-resolver.js";
|
|
4
|
+
/**
|
|
5
|
+
* ServerServices
|
|
6
|
+
*
|
|
7
|
+
* サーバー全体で共有されるサービスの集合。
|
|
8
|
+
* リクエスト間で共有され、単一のインスタンスを持つ。
|
|
9
|
+
*/
|
|
10
|
+
export interface ServerServices {
|
|
11
|
+
repoRepository: RepoRepository;
|
|
12
|
+
repoResolver: RepoResolver;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* createServerServices
|
|
16
|
+
*
|
|
17
|
+
* サーバーサービスを初期化して返す。
|
|
18
|
+
* サーバー起動時に一度だけ呼び出される。
|
|
19
|
+
*
|
|
20
|
+
* @param db - DuckDBクライアント
|
|
21
|
+
* @returns 初期化されたサービス群
|
|
22
|
+
*/
|
|
23
|
+
export declare function createServerServices(db: DuckDBClient): ServerServices;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,cAAc,CAQrE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RepoRepository } from "./repo-repository.js";
|
|
2
|
+
import { RepoResolver } from "./repo-resolver.js";
|
|
3
|
+
/**
|
|
4
|
+
* createServerServices
|
|
5
|
+
*
|
|
6
|
+
* サーバーサービスを初期化して返す。
|
|
7
|
+
* サーバー起動時に一度だけ呼び出される。
|
|
8
|
+
*
|
|
9
|
+
* @param db - DuckDBクライアント
|
|
10
|
+
* @returns 初期化されたサービス群
|
|
11
|
+
*/
|
|
12
|
+
export function createServerServices(db) {
|
|
13
|
+
const repoRepository = new RepoRepository(db);
|
|
14
|
+
const repoResolver = new RepoResolver(repoRepository);
|
|
15
|
+
return {
|
|
16
|
+
repoRepository,
|
|
17
|
+
repoResolver,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/services/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAalD;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAgB;IACnD,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,cAAc,CAAC,CAAC;IAEtD,OAAO;QACL,cAAc;QACd,YAAY;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DuckDBClient } from "../../shared/duckdb.js";
|
|
2
|
+
/**
|
|
3
|
+
* RepoRecord
|
|
4
|
+
*
|
|
5
|
+
* リポジトリレコードのデータ構造
|
|
6
|
+
*/
|
|
7
|
+
export interface RepoRecord {
|
|
8
|
+
id: number;
|
|
9
|
+
root: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* RepoRepository
|
|
13
|
+
*
|
|
14
|
+
* リポジトリテーブルへのデータアクセスを担当するクラス。
|
|
15
|
+
* DB I/O のみを行い、ビジネスロジックは持たない。
|
|
16
|
+
*/
|
|
17
|
+
export declare class RepoRepository {
|
|
18
|
+
private db;
|
|
19
|
+
constructor(db: DuckDBClient);
|
|
20
|
+
/**
|
|
21
|
+
* normalized_root 列が存在するかチェックする。
|
|
22
|
+
* 後方互換性のため、カラム存在チェックを行う。
|
|
23
|
+
*
|
|
24
|
+
* @returns カラムが存在する場合は true
|
|
25
|
+
*/
|
|
26
|
+
private hasNormalizedRootColumn;
|
|
27
|
+
/**
|
|
28
|
+
* 指定されたパス候補のいずれかに一致するリポジトリを検索する。
|
|
29
|
+
* Phase 1: normalized_root列を使用した高速検索をサポート。
|
|
30
|
+
*
|
|
31
|
+
* @param candidates - 検索するパス候補の配列
|
|
32
|
+
* @returns 最初に見つかったリポジトリレコード、見つからない場合はnull
|
|
33
|
+
*/
|
|
34
|
+
findByPaths(candidates: string[]): Promise<RepoRecord | null>;
|
|
35
|
+
/**
|
|
36
|
+
* 正規化されたパスに一致するリポジトリを検索する(レガシーフォールバック)。
|
|
37
|
+
* Phase 1: normalized_root 列が存在する場合、このメソッドは使用されなくなります。
|
|
38
|
+
* マイグレーション期間中の安全性のため保持されています。
|
|
39
|
+
*
|
|
40
|
+
* NOTE: この処理は O(n) である。normalized_root カラム + インデックスが存在すれば不要。
|
|
41
|
+
*
|
|
42
|
+
* @param normalized - 正規化されたパス
|
|
43
|
+
* @param normalizeFn - パスを正規化する関数
|
|
44
|
+
* @returns 見つかったリポジトリレコード、見つからない場合はnull
|
|
45
|
+
*/
|
|
46
|
+
findByNormalizedPath(normalized: string, normalizeFn: (path: string) => string): Promise<RepoRecord | null>;
|
|
47
|
+
/**
|
|
48
|
+
* リポジトリのrootパスを更新する。
|
|
49
|
+
*
|
|
50
|
+
* @param id - リポジトリID
|
|
51
|
+
* @param newRoot - 新しいrootパス
|
|
52
|
+
*/
|
|
53
|
+
updateRoot(id: number, newRoot: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* repoテーブルが存在するかチェックする。
|
|
56
|
+
*
|
|
57
|
+
* @returns テーブルが存在する場合はtrue
|
|
58
|
+
*/
|
|
59
|
+
tableExists(): Promise<boolean>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=repo-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-repository.d.ts","sourceRoot":"","sources":["../../../../src/server/services/repo-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAEpC;;;;;OAKG;YACW,uBAAuB;IAQrC;;;;;;OAMG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAgCnE;;;;;;;;;;OAUG;IACG,oBAAoB,CACxB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACpC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAK7B;;;;;OAKG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5D;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAWtC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { normalizeRepoPath } from "../../shared/utils/path.js";
|
|
2
|
+
/**
|
|
3
|
+
* RepoRepository
|
|
4
|
+
*
|
|
5
|
+
* リポジトリテーブルへのデータアクセスを担当するクラス。
|
|
6
|
+
* DB I/O のみを行い、ビジネスロジックは持たない。
|
|
7
|
+
*/
|
|
8
|
+
export class RepoRepository {
|
|
9
|
+
db;
|
|
10
|
+
constructor(db) {
|
|
11
|
+
this.db = db;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* normalized_root 列が存在するかチェックする。
|
|
15
|
+
* 後方互換性のため、カラム存在チェックを行う。
|
|
16
|
+
*
|
|
17
|
+
* @returns カラムが存在する場合は true
|
|
18
|
+
*/
|
|
19
|
+
async hasNormalizedRootColumn() {
|
|
20
|
+
const cols = await this.db.all(`SELECT column_name FROM duckdb_columns()
|
|
21
|
+
WHERE table_name = 'repo' AND column_name = 'normalized_root'`);
|
|
22
|
+
return cols.length > 0;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 指定されたパス候補のいずれかに一致するリポジトリを検索する。
|
|
26
|
+
* Phase 1: normalized_root列を使用した高速検索をサポート。
|
|
27
|
+
*
|
|
28
|
+
* @param candidates - 検索するパス候補の配列
|
|
29
|
+
* @returns 最初に見つかったリポジトリレコード、見つからない場合はnull
|
|
30
|
+
*/
|
|
31
|
+
async findByPaths(candidates) {
|
|
32
|
+
if (candidates.length === 0) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
// Step 1: Try direct root lookup first (legacy compatibility)
|
|
36
|
+
const rootPlaceholders = candidates.map(() => "?").join(", ");
|
|
37
|
+
let rows = await this.db.all(`SELECT id, root FROM repo WHERE root IN (${rootPlaceholders}) LIMIT 1`, candidates);
|
|
38
|
+
if (rows.length > 0) {
|
|
39
|
+
return rows[0] ?? null; // exactOptionalPropertyTypes 対応: undefined を null に変換
|
|
40
|
+
}
|
|
41
|
+
// Step 2: Try normalized_root lookup (fast path with index) if column exists
|
|
42
|
+
const hasNormalizedRoot = await this.hasNormalizedRootColumn();
|
|
43
|
+
if (hasNormalizedRoot) {
|
|
44
|
+
const normalizedCandidates = candidates.map((c) => normalizeRepoPath(c));
|
|
45
|
+
const normalizedPlaceholders = normalizedCandidates.map(() => "?").join(", ");
|
|
46
|
+
rows = await this.db.all(`SELECT id, root FROM repo WHERE normalized_root IN (${normalizedPlaceholders}) LIMIT 1`, normalizedCandidates);
|
|
47
|
+
return rows[0] ?? null; // exactOptionalPropertyTypes 対応: undefined を null に変換
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 正規化されたパスに一致するリポジトリを検索する(レガシーフォールバック)。
|
|
53
|
+
* Phase 1: normalized_root 列が存在する場合、このメソッドは使用されなくなります。
|
|
54
|
+
* マイグレーション期間中の安全性のため保持されています。
|
|
55
|
+
*
|
|
56
|
+
* NOTE: この処理は O(n) である。normalized_root カラム + インデックスが存在すれば不要。
|
|
57
|
+
*
|
|
58
|
+
* @param normalized - 正規化されたパス
|
|
59
|
+
* @param normalizeFn - パスを正規化する関数
|
|
60
|
+
* @returns 見つかったリポジトリレコード、見つからない場合はnull
|
|
61
|
+
*/
|
|
62
|
+
async findByNormalizedPath(normalized, normalizeFn) {
|
|
63
|
+
const allRepos = await this.db.all("SELECT id, root FROM repo");
|
|
64
|
+
return allRepos.find((repo) => normalizeFn(repo.root) === normalized) || null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* リポジトリのrootパスを更新する。
|
|
68
|
+
*
|
|
69
|
+
* @param id - リポジトリID
|
|
70
|
+
* @param newRoot - 新しいrootパス
|
|
71
|
+
*/
|
|
72
|
+
async updateRoot(id, newRoot) {
|
|
73
|
+
await this.db.run("UPDATE repo SET root = ? WHERE id = ?", [newRoot, id]);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* repoテーブルが存在するかチェックする。
|
|
77
|
+
*
|
|
78
|
+
* @returns テーブルが存在する場合はtrue
|
|
79
|
+
*/
|
|
80
|
+
async tableExists() {
|
|
81
|
+
try {
|
|
82
|
+
await this.db.all("SELECT 1 FROM repo LIMIT 1");
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error instanceof Error && error.message.includes("Table with name repo")) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
throw new Error("Repo metadata check failed. Verify DuckDB permissions before retrying.");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=repo-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-repository.js","sourceRoot":"","sources":["../../../../src/server/services/repo-repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAY/D;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IACL;IAApB,YAAoB,EAAgB;QAAhB,OAAE,GAAF,EAAE,CAAc;IAAG,CAAC;IAExC;;;;;OAKG;IACK,KAAK,CAAC,uBAAuB;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAC5B;qEAC+D,CAChE,CAAC;QACF,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,UAAoB;QACpC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8DAA8D;QAC9D,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAC1B,4CAA4C,gBAAgB,WAAW,EACvE,UAAU,CACX,CAAC;QAEF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,sDAAsD;QAChF,CAAC;QAED,6EAA6E;QAC7E,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC/D,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,oBAAoB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;YACzE,MAAM,sBAAsB,GAAG,oBAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9E,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACtB,uDAAuD,sBAAsB,WAAW,EACxF,oBAAoB,CACrB,CAAC;YAEF,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,sDAAsD;QAChF,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,oBAAoB,CACxB,UAAkB,EAClB,WAAqC;QAErC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAa,2BAA2B,CAAC,CAAC;QAC5E,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC;IAChF,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,OAAe;QAC1C,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,uCAAuC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAChD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;gBAC7E,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { RepoRepository } from "./repo-repository.js";
|
|
2
|
+
/**
|
|
3
|
+
* RepoNotFoundError
|
|
4
|
+
*
|
|
5
|
+
* リポジトリが見つからなかった場合のエラー
|
|
6
|
+
*/
|
|
7
|
+
export declare class RepoNotFoundError extends Error {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* RepoResolver
|
|
12
|
+
*
|
|
13
|
+
* リポジトリパスをデータベースIDに解決する責務を持つクラス。
|
|
14
|
+
* パス正規化とDB検索を組み合わせ、エラー処理も担当する。
|
|
15
|
+
*/
|
|
16
|
+
export declare class RepoResolver {
|
|
17
|
+
private repository;
|
|
18
|
+
constructor(repository: RepoRepository);
|
|
19
|
+
/**
|
|
20
|
+
* リポジトリのrootパスをデータベースIDに解決する。
|
|
21
|
+
*
|
|
22
|
+
* @param repoRoot - リポジトリのrootパス
|
|
23
|
+
* @returns リポジトリID
|
|
24
|
+
* @throws RepoNotFoundError リポジトリがインデックスされていない場合
|
|
25
|
+
*/
|
|
26
|
+
resolveId(repoRoot: string): Promise<number>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=repo-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-resolver.d.ts","sourceRoot":"","sources":["../../../../src/server/services/repo-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,cAAc;IAE9C;;;;;;OAMG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA4CnD"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getRepoPathCandidates, normalizeRepoPath } from "../../shared/utils/path.js";
|
|
2
|
+
/**
|
|
3
|
+
* RepoNotFoundError
|
|
4
|
+
*
|
|
5
|
+
* リポジトリが見つからなかった場合のエラー
|
|
6
|
+
*/
|
|
7
|
+
export class RepoNotFoundError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "RepoNotFoundError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* RepoResolver
|
|
15
|
+
*
|
|
16
|
+
* リポジトリパスをデータベースIDに解決する責務を持つクラス。
|
|
17
|
+
* パス正規化とDB検索を組み合わせ、エラー処理も担当する。
|
|
18
|
+
*/
|
|
19
|
+
export class RepoResolver {
|
|
20
|
+
repository;
|
|
21
|
+
constructor(repository) {
|
|
22
|
+
this.repository = repository;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* リポジトリのrootパスをデータベースIDに解決する。
|
|
26
|
+
*
|
|
27
|
+
* @param repoRoot - リポジトリのrootパス
|
|
28
|
+
* @returns リポジトリID
|
|
29
|
+
* @throws RepoNotFoundError リポジトリがインデックスされていない場合
|
|
30
|
+
*/
|
|
31
|
+
async resolveId(repoRoot) {
|
|
32
|
+
// repoテーブルの存在確認
|
|
33
|
+
const tableExists = await this.repository.tableExists();
|
|
34
|
+
if (!tableExists) {
|
|
35
|
+
throw new RepoNotFoundError(`Repository ${repoRoot} was not indexed. Run the indexer before starting the server.`);
|
|
36
|
+
}
|
|
37
|
+
// パス候補と正規化パスを取得
|
|
38
|
+
const candidates = getRepoPathCandidates(repoRoot);
|
|
39
|
+
const normalized = candidates[0];
|
|
40
|
+
// exactOptionalPropertyTypes 対応: candidates[0] が undefined の場合はエラー
|
|
41
|
+
if (!normalized) {
|
|
42
|
+
throw new RepoNotFoundError(`Repository ${repoRoot} path normalization failed. Check path validity.`);
|
|
43
|
+
}
|
|
44
|
+
// 高速パス: 直接検索を試みる
|
|
45
|
+
let repo = await this.repository.findByPaths(candidates);
|
|
46
|
+
// 低速パス: 正規化フォールバックを試みる
|
|
47
|
+
if (!repo) {
|
|
48
|
+
repo = await this.repository.findByNormalizedPath(normalized, normalizeRepoPath);
|
|
49
|
+
if (!repo) {
|
|
50
|
+
throw new RepoNotFoundError(`Repository ${repoRoot} was not indexed. Run the indexer before starting the server.`);
|
|
51
|
+
}
|
|
52
|
+
// 次回の高速検索のために正規化パスに更新
|
|
53
|
+
await this.repository.updateRoot(repo.id, normalized);
|
|
54
|
+
}
|
|
55
|
+
// パスが正規化されていない場合は更新
|
|
56
|
+
if (repo.root !== normalized) {
|
|
57
|
+
await this.repository.updateRoot(repo.id, normalized);
|
|
58
|
+
}
|
|
59
|
+
return repo.id;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=repo-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-resolver.js","sourceRoot":"","sources":["../../../../src/server/services/repo-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAItF;;;;GAIG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IACH;IAApB,YAAoB,UAA0B;QAA1B,eAAU,GAAV,UAAU,CAAgB;IAAG,CAAC;IAElD;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC9B,gBAAgB;QAChB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QACxD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,iBAAiB,CACzB,cAAc,QAAQ,+DAA+D,CACtF,CAAC;QACJ,CAAC;QAED,gBAAgB;QAChB,MAAM,UAAU,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAEjC,mEAAmE;QACnE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,iBAAiB,CACzB,cAAc,QAAQ,kDAAkD,CACzE,CAAC;QACJ,CAAC;QAED,iBAAiB;QACjB,IAAI,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAEzD,uBAAuB;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;YAEjF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,iBAAiB,CACzB,cAAc,QAAQ,+DAA+D,CACtF,CAAC;YACJ,CAAC;YAED,sBAAsB;YACtB,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACxD,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI Argument Parsing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent --help and --version handling across all kiri commands.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* CLI option specification
|
|
8
|
+
*/
|
|
9
|
+
export interface CliOption {
|
|
10
|
+
/** Option flag name (without --) */
|
|
11
|
+
flag: string;
|
|
12
|
+
/** Short flag (single character, optional) */
|
|
13
|
+
short?: string;
|
|
14
|
+
/** Option type */
|
|
15
|
+
type: "string" | "boolean";
|
|
16
|
+
/** Default value */
|
|
17
|
+
default?: string | boolean;
|
|
18
|
+
/** Description for help text */
|
|
19
|
+
description: string;
|
|
20
|
+
/** Placeholder for help text (e.g., "<path>", "<port>") */
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Help section for grouping related options
|
|
25
|
+
*/
|
|
26
|
+
export interface HelpSection {
|
|
27
|
+
/** Section title */
|
|
28
|
+
title: string;
|
|
29
|
+
/** Options in this section */
|
|
30
|
+
options: CliOption[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Complete CLI specification
|
|
34
|
+
*/
|
|
35
|
+
export interface CliSpec {
|
|
36
|
+
/** Command name (e.g., "kiri", "kiri-server") */
|
|
37
|
+
commandName: string;
|
|
38
|
+
/** Command description */
|
|
39
|
+
description: string;
|
|
40
|
+
/** Package version */
|
|
41
|
+
version: string;
|
|
42
|
+
/** Usage line (e.g., "kiri [options]") */
|
|
43
|
+
usage: string;
|
|
44
|
+
/** Help sections grouping related options */
|
|
45
|
+
sections: HelpSection[];
|
|
46
|
+
/** Optional examples */
|
|
47
|
+
examples?: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parsed CLI arguments result
|
|
51
|
+
*/
|
|
52
|
+
export interface ParsedArgs {
|
|
53
|
+
values: Record<string, string | boolean | undefined>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Render help message to stdout
|
|
57
|
+
*/
|
|
58
|
+
export declare function renderHelp(spec: CliSpec): void;
|
|
59
|
+
/**
|
|
60
|
+
* Render version information to stdout
|
|
61
|
+
*/
|
|
62
|
+
export declare function renderVersion(commandName: string, version: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Define CLI with automatic --help and --version handling
|
|
65
|
+
*
|
|
66
|
+
* @param spec CLI specification
|
|
67
|
+
* @returns Parsed arguments (if not exited via --help or --version)
|
|
68
|
+
*/
|
|
69
|
+
export declare function defineCli(spec: CliSpec): ParsedArgs;
|
|
70
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../../src/shared/cli/args.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CACtD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAoC9C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAsCnD"}
|