kiri-mcp-server 0.9.6 → 0.9.9
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 +94 -7
- package/dist/client/cli.js +68 -0
- package/dist/client/cli.js.map +1 -0
- package/dist/client/index.js +5 -0
- package/dist/client/index.js.map +1 -0
- package/dist/eval/metrics.js +47 -0
- package/dist/eval/metrics.js.map +1 -0
- package/dist/indexer/cli.js +362 -0
- package/dist/indexer/cli.js.map +1 -0
- package/dist/indexer/codeintel.js +182 -0
- package/dist/indexer/codeintel.js.map +1 -0
- package/dist/indexer/git.js +30 -0
- package/dist/indexer/git.js.map +1 -0
- package/dist/indexer/language.js +34 -0
- package/dist/indexer/language.js.map +1 -0
- package/dist/indexer/pipeline/filters/denylist.js +71 -0
- package/dist/indexer/pipeline/filters/denylist.js.map +1 -0
- package/dist/indexer/schema.js +101 -0
- package/dist/indexer/schema.js.map +1 -0
- package/dist/package.json +11 -1
- package/dist/server/bootstrap.js +19 -0
- package/dist/server/bootstrap.js.map +1 -0
- package/dist/server/context.js +1 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/fallbacks/degradeController.js +69 -0
- package/dist/server/fallbacks/degradeController.js.map +1 -0
- package/dist/server/handlers.js +1268 -0
- package/dist/server/handlers.js.map +1 -0
- package/dist/server/main.js +151 -0
- package/dist/server/main.js.map +1 -0
- package/dist/server/observability/metrics.js +56 -0
- package/dist/server/observability/metrics.js.map +1 -0
- package/dist/server/observability/tracing.js +58 -0
- package/dist/server/observability/tracing.js.map +1 -0
- package/dist/server/rpc.js +477 -0
- package/dist/server/rpc.js.map +1 -0
- package/dist/server/runtime.js +47 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/scoring.js +116 -0
- package/dist/server/scoring.js.map +1 -0
- package/dist/server/stdio.js +76 -0
- package/dist/server/stdio.js.map +1 -0
- package/dist/shared/duckdb.js +119 -0
- package/dist/shared/duckdb.js.map +1 -0
- package/dist/shared/embedding.js +98 -0
- package/dist/shared/embedding.js.map +1 -0
- package/dist/shared/index.js +9 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/security/config.js +64 -0
- package/dist/shared/security/config.js.map +1 -0
- package/dist/shared/security/masker.js +56 -0
- package/dist/shared/security/masker.js.map +1 -0
- package/dist/shared/tokenizer.js +4 -0
- package/dist/shared/tokenizer.js.map +1 -0
- package/dist/shared/utils/simpleYaml.js +89 -0
- package/dist/shared/utils/simpleYaml.js.map +1 -0
- package/dist/src/client/proxy.js +2 -1
- package/dist/src/client/proxy.js.map +1 -1
- package/dist/src/client/start-daemon.d.ts.map +1 -1
- package/dist/src/client/start-daemon.js +2 -1
- package/dist/src/client/start-daemon.js.map +1 -1
- package/dist/src/daemon/daemon.js +6 -4
- package/dist/src/daemon/daemon.js.map +1 -1
- package/dist/src/daemon/socket.d.ts +6 -4
- package/dist/src/daemon/socket.d.ts.map +1 -1
- package/dist/src/daemon/socket.js +62 -18
- package/dist/src/daemon/socket.js.map +1 -1
- package/dist/src/indexer/cli.d.ts +1 -0
- package/dist/src/indexer/cli.d.ts.map +1 -1
- package/dist/src/indexer/cli.js +503 -257
- package/dist/src/indexer/cli.js.map +1 -1
- package/dist/src/indexer/codeintel.d.ts +1 -1
- package/dist/src/indexer/codeintel.d.ts.map +1 -1
- package/dist/src/indexer/codeintel.js +296 -3
- package/dist/src/indexer/codeintel.js.map +1 -1
- package/dist/src/indexer/dart/analyze.d.ts +29 -0
- package/dist/src/indexer/dart/analyze.d.ts.map +1 -0
- package/dist/src/indexer/dart/analyze.js +452 -0
- package/dist/src/indexer/dart/analyze.js.map +1 -0
- package/dist/src/indexer/dart/client.d.ts +113 -0
- package/dist/src/indexer/dart/client.d.ts.map +1 -0
- package/dist/src/indexer/dart/client.js +444 -0
- package/dist/src/indexer/dart/client.js.map +1 -0
- package/dist/src/indexer/dart/config.d.ts +36 -0
- package/dist/src/indexer/dart/config.d.ts.map +1 -0
- package/dist/src/indexer/dart/config.js +62 -0
- package/dist/src/indexer/dart/config.js.map +1 -0
- package/dist/src/indexer/dart/dependencies.d.ts +17 -0
- package/dist/src/indexer/dart/dependencies.d.ts.map +1 -0
- package/dist/src/indexer/dart/dependencies.js +102 -0
- package/dist/src/indexer/dart/dependencies.js.map +1 -0
- package/dist/src/indexer/dart/pathKey.d.ts +40 -0
- package/dist/src/indexer/dart/pathKey.d.ts.map +1 -0
- package/dist/src/indexer/dart/pathKey.js +72 -0
- package/dist/src/indexer/dart/pathKey.js.map +1 -0
- package/dist/src/indexer/dart/poolGate.d.ts +57 -0
- package/dist/src/indexer/dart/poolGate.d.ts.map +1 -0
- package/dist/src/indexer/dart/poolGate.js +87 -0
- package/dist/src/indexer/dart/poolGate.js.map +1 -0
- package/dist/src/indexer/dart/sdk.d.ts +40 -0
- package/dist/src/indexer/dart/sdk.d.ts.map +1 -0
- package/dist/src/indexer/dart/sdk.js +167 -0
- package/dist/src/indexer/dart/sdk.js.map +1 -0
- package/dist/src/indexer/dart/transform.d.ts +17 -0
- package/dist/src/indexer/dart/transform.d.ts.map +1 -0
- package/dist/src/indexer/dart/transform.js +157 -0
- package/dist/src/indexer/dart/transform.js.map +1 -0
- package/dist/src/indexer/dart/types.d.ts +137 -0
- package/dist/src/indexer/dart/types.d.ts.map +1 -0
- package/dist/src/indexer/dart/types.js +5 -0
- package/dist/src/indexer/dart/types.js.map +1 -0
- package/dist/src/indexer/git.d.ts +1 -0
- package/dist/src/indexer/git.d.ts.map +1 -1
- package/dist/src/indexer/git.js +8 -0
- package/dist/src/indexer/git.js.map +1 -1
- package/dist/src/indexer/language.d.ts.map +1 -1
- package/dist/src/indexer/language.js +1 -0
- package/dist/src/indexer/language.js.map +1 -1
- package/dist/src/indexer/queue.d.ts +19 -0
- package/dist/src/indexer/queue.d.ts.map +1 -0
- package/dist/src/indexer/queue.js +50 -0
- package/dist/src/indexer/queue.js.map +1 -0
- package/dist/src/indexer/schema.d.ts +61 -1
- package/dist/src/indexer/schema.d.ts.map +1 -1
- package/dist/src/indexer/schema.js +253 -2
- package/dist/src/indexer/schema.js.map +1 -1
- package/dist/src/indexer/watch.d.ts +21 -0
- package/dist/src/indexer/watch.d.ts.map +1 -1
- package/dist/src/indexer/watch.js +189 -28
- package/dist/src/indexer/watch.js.map +1 -1
- package/dist/src/server/context.d.ts +7 -0
- package/dist/src/server/context.d.ts.map +1 -1
- package/dist/src/server/handlers.d.ts.map +1 -1
- package/dist/src/server/handlers.js +87 -4
- 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 +4 -1
- package/dist/src/server/indexBootstrap.js.map +1 -1
- package/dist/src/server/main.js +0 -0
- package/dist/src/server/runtime.d.ts.map +1 -1
- package/dist/src/server/runtime.js +45 -6
- package/dist/src/server/runtime.js.map +1 -1
- package/dist/src/shared/duckdb.d.ts.map +1 -1
- package/dist/src/shared/duckdb.js +9 -0
- package/dist/src/shared/duckdb.js.map +1 -1
- package/dist/src/shared/utils/path.d.ts +46 -0
- package/dist/src/shared/utils/path.d.ts.map +1 -0
- package/dist/src/shared/utils/path.js +94 -0
- package/dist/src/shared/utils/path.js.map +1 -0
- package/dist/src/shared/utils/socket.d.ts +61 -0
- package/dist/src/shared/utils/socket.d.ts.map +1 -0
- package/dist/src/shared/utils/socket.js +156 -0
- package/dist/src/shared/utils/socket.js.map +1 -0
- package/package.json +11 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dart依存関係解析(Phase 3)
|
|
3
|
+
*
|
|
4
|
+
* Analysis ServerのGetLibraryDependenciesResultからDependencyRecordを生成
|
|
5
|
+
*/
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
/**
|
|
9
|
+
* GetLibraryDependenciesResultからDependencyRecordを生成
|
|
10
|
+
*
|
|
11
|
+
* @param filePath - 解析対象ファイルのパス
|
|
12
|
+
* @param dependenciesResult - Analysis Serverの依存関係情報
|
|
13
|
+
* @param workspaceRoot - ワークスペースルート(相対パス解決用)
|
|
14
|
+
* @returns DependencyRecord配列
|
|
15
|
+
*/
|
|
16
|
+
export function extractDependencies(filePath, dependenciesResult, workspaceRoot) {
|
|
17
|
+
const dependencies = [];
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
// libraries配列から各ライブラリのURIを解析
|
|
20
|
+
for (const libraryPath of dependenciesResult.libraries) {
|
|
21
|
+
const dep = analyzeDependencyUri(libraryPath, filePath, workspaceRoot);
|
|
22
|
+
if (dep) {
|
|
23
|
+
const key = `${dep.dstKind}:${dep.dst}`;
|
|
24
|
+
if (!seen.has(key)) {
|
|
25
|
+
seen.add(key);
|
|
26
|
+
dependencies.push(dep);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return dependencies;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 依存関係URIを解析してDependencyRecordを生成
|
|
34
|
+
*
|
|
35
|
+
* Dartの依存関係は以下の形式:
|
|
36
|
+
* - dart:core, dart:async など(SDK)
|
|
37
|
+
* - package:flutter/material.dart など(パッケージ)
|
|
38
|
+
* - file:///path/to/file.dart など(相対パス)
|
|
39
|
+
*
|
|
40
|
+
* @param uri - 依存関係URI
|
|
41
|
+
* @param sourceFilePath - 依存元ファイルのパス
|
|
42
|
+
* @param workspaceRoot - ワークスペースルート
|
|
43
|
+
* @returns DependencyRecord または null
|
|
44
|
+
*/
|
|
45
|
+
function analyzeDependencyUri(uri, sourceFilePath, workspaceRoot) {
|
|
46
|
+
// dart: スキーム(SDK)
|
|
47
|
+
if (uri.startsWith("dart:")) {
|
|
48
|
+
return {
|
|
49
|
+
dstKind: "package",
|
|
50
|
+
dst: uri, // dart:core, dart:async など
|
|
51
|
+
rel: "import",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// package: スキーム(外部パッケージ)
|
|
55
|
+
if (uri.startsWith("package:")) {
|
|
56
|
+
return {
|
|
57
|
+
dstKind: "package",
|
|
58
|
+
dst: uri, // package:flutter/material.dart など
|
|
59
|
+
rel: "import",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// file: スキーム(ローカルファイル)
|
|
63
|
+
if (uri.startsWith("file:")) {
|
|
64
|
+
try {
|
|
65
|
+
// fileURLToPath を使用してクロスプラットフォーム対応
|
|
66
|
+
// Windows: file:///C:/repo/lib/foo.dart → C:\repo\lib\foo.dart
|
|
67
|
+
// Unix: file:///repo/lib/foo.dart → /repo/lib/foo.dart
|
|
68
|
+
const absolutePath = fileURLToPath(uri);
|
|
69
|
+
const relativePath = path.relative(workspaceRoot, absolutePath);
|
|
70
|
+
// ワークスペース外のファイルは無視(クロスプラットフォーム対応)
|
|
71
|
+
if (!relativePath.startsWith("..") && !path.isAbsolute(relativePath)) {
|
|
72
|
+
return {
|
|
73
|
+
dstKind: "path",
|
|
74
|
+
dst: relativePath,
|
|
75
|
+
rel: "import",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.warn(`[analyzeDependencyUri] Invalid file URI: ${uri}`, error);
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
// 相対パス(./lib/foo.dart など)
|
|
85
|
+
if (uri.startsWith("./") || uri.startsWith("../")) {
|
|
86
|
+
const sourceDir = path.dirname(sourceFilePath);
|
|
87
|
+
const absolutePath = path.normalize(path.join(sourceDir, uri));
|
|
88
|
+
const relativePath = path.relative(workspaceRoot, absolutePath);
|
|
89
|
+
// ワークスペース外のファイルは無視(Windows互換のため..を含むかチェック)
|
|
90
|
+
if (relativePath.startsWith("..")) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
dstKind: "path",
|
|
95
|
+
dst: relativePath,
|
|
96
|
+
rel: "import",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// その他のURIは無視
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../../src/indexer/dart/dependencies.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path normalization utilities for Windows case-insensitive filesystem support
|
|
3
|
+
*
|
|
4
|
+
* Fix #3 & #5: Normalize paths on Windows to prevent Map key collisions
|
|
5
|
+
* when same physical path is referenced with different casing (C:\repo vs c:\repo)
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Normalize workspace root path for use as Map key
|
|
9
|
+
*
|
|
10
|
+
* Windows: Resolves to real path, converts to forward slashes, lowercases
|
|
11
|
+
* Unix: Returns normalized absolute path
|
|
12
|
+
*
|
|
13
|
+
* @param workspaceRoot - Workspace root path (may be relative)
|
|
14
|
+
* @returns Normalized key suitable for Map/Set operations
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeWorkspaceKey(workspaceRoot: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Normalize file path for use as Map key
|
|
19
|
+
*
|
|
20
|
+
* Windows: Normalizes path, converts to forward slashes, lowercases
|
|
21
|
+
* Unix: Returns normalized absolute path
|
|
22
|
+
*
|
|
23
|
+
* Note: Does NOT resolve symlinks for files (unlike workspace roots)
|
|
24
|
+
* because overlay files may not exist on disk yet.
|
|
25
|
+
*
|
|
26
|
+
* @param filePath - File path (absolute or relative)
|
|
27
|
+
* @param workspaceRoot - Optional workspace root for resolving relative paths
|
|
28
|
+
* @returns Normalized key suitable for Map/Set operations
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizeFileKey(filePath: string, workspaceRoot?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Normalize any path for consistent comparison
|
|
33
|
+
*
|
|
34
|
+
* Generic version for edge cases where workspace vs file distinction doesn't matter
|
|
35
|
+
*
|
|
36
|
+
* @param inputPath - Any file system path
|
|
37
|
+
* @returns Normalized path
|
|
38
|
+
*/
|
|
39
|
+
export declare function normalizePath(inputPath: string): string;
|
|
40
|
+
//# sourceMappingURL=pathKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathKey.d.ts","sourceRoot":"","sources":["../../../../src/indexer/dart/pathKey.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAiBnE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAUjF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQvD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path normalization utilities for Windows case-insensitive filesystem support
|
|
3
|
+
*
|
|
4
|
+
* Fix #3 & #5: Normalize paths on Windows to prevent Map key collisions
|
|
5
|
+
* when same physical path is referenced with different casing (C:\repo vs c:\repo)
|
|
6
|
+
*/
|
|
7
|
+
import { realpathSync } from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
/**
|
|
10
|
+
* Normalize workspace root path for use as Map key
|
|
11
|
+
*
|
|
12
|
+
* Windows: Resolves to real path, converts to forward slashes, lowercases
|
|
13
|
+
* Unix: Returns normalized absolute path
|
|
14
|
+
*
|
|
15
|
+
* @param workspaceRoot - Workspace root path (may be relative)
|
|
16
|
+
* @returns Normalized key suitable for Map/Set operations
|
|
17
|
+
*/
|
|
18
|
+
export function normalizeWorkspaceKey(workspaceRoot) {
|
|
19
|
+
// Normalize to absolute path first
|
|
20
|
+
const normalized = path.resolve(workspaceRoot);
|
|
21
|
+
if (process.platform === "win32") {
|
|
22
|
+
try {
|
|
23
|
+
// Resolve symlinks/junctions to real path
|
|
24
|
+
const realPath = realpathSync.native(normalized);
|
|
25
|
+
// Convert backslashes to forward slashes and lowercase
|
|
26
|
+
return realPath.replace(/\\/g, "/").toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// If path doesn't exist yet, fall back to normalized path
|
|
30
|
+
return normalized.replace(/\\/g, "/").toLowerCase();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return normalized;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Normalize file path for use as Map key
|
|
37
|
+
*
|
|
38
|
+
* Windows: Normalizes path, converts to forward slashes, lowercases
|
|
39
|
+
* Unix: Returns normalized absolute path
|
|
40
|
+
*
|
|
41
|
+
* Note: Does NOT resolve symlinks for files (unlike workspace roots)
|
|
42
|
+
* because overlay files may not exist on disk yet.
|
|
43
|
+
*
|
|
44
|
+
* @param filePath - File path (absolute or relative)
|
|
45
|
+
* @param workspaceRoot - Optional workspace root for resolving relative paths
|
|
46
|
+
* @returns Normalized key suitable for Map/Set operations
|
|
47
|
+
*/
|
|
48
|
+
export function normalizeFileKey(filePath, workspaceRoot) {
|
|
49
|
+
// Resolve to absolute path
|
|
50
|
+
const normalized = workspaceRoot ? path.resolve(workspaceRoot, filePath) : path.resolve(filePath);
|
|
51
|
+
if (process.platform === "win32") {
|
|
52
|
+
// Normalize and lowercase for case-insensitive comparison
|
|
53
|
+
return path.normalize(normalized).replace(/\\/g, "/").toLowerCase();
|
|
54
|
+
}
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Normalize any path for consistent comparison
|
|
59
|
+
*
|
|
60
|
+
* Generic version for edge cases where workspace vs file distinction doesn't matter
|
|
61
|
+
*
|
|
62
|
+
* @param inputPath - Any file system path
|
|
63
|
+
* @returns Normalized path
|
|
64
|
+
*/
|
|
65
|
+
export function normalizePath(inputPath) {
|
|
66
|
+
const normalized = path.normalize(inputPath);
|
|
67
|
+
if (process.platform === "win32") {
|
|
68
|
+
return normalized.replace(/\\/g, "/").toLowerCase();
|
|
69
|
+
}
|
|
70
|
+
return normalized;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=pathKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathKey.js","sourceRoot":"","sources":["../../../../src/indexer/dart/pathKey.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,aAAqB;IACzD,mCAAmC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,0CAA0C;YAC1C,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACjD,uDAAuD;YACvD,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;YAC1D,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,aAAsB;IACvE,2BAA2B;IAC3B,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAElG,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,0DAA0D;QAC1D,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACtE,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool capacity limiting semaphore for DartAnalysisClient pool
|
|
3
|
+
*
|
|
4
|
+
* Fix #1: Enforce MAX_CLIENTS limit with FIFO waiting queue
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* DartPoolBusyError: Thrown when waiting for pool capacity times out
|
|
8
|
+
*/
|
|
9
|
+
export declare class DartPoolBusyError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Capacity limiter with FIFO queue
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```ts
|
|
17
|
+
* const limiter = createCapacityLimiter(8);
|
|
18
|
+
* await limiter.acquire({ timeoutMs: 10000 });
|
|
19
|
+
* try {
|
|
20
|
+
* // ... create and use client ...
|
|
21
|
+
* } finally {
|
|
22
|
+
* limiter.release();
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export interface CapacityLimiter {
|
|
27
|
+
/**
|
|
28
|
+
* Acquire a permit. Blocks until a permit is available or timeout occurs.
|
|
29
|
+
*
|
|
30
|
+
* @param options - Acquisition options
|
|
31
|
+
* @param options.timeoutMs - Timeout in milliseconds (0 = no timeout)
|
|
32
|
+
* @throws DartPoolBusyError if timeout occurs
|
|
33
|
+
*/
|
|
34
|
+
acquire(options?: {
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Release a permit. Must be called exactly once after each successful acquire().
|
|
39
|
+
*/
|
|
40
|
+
release(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get current pool statistics
|
|
43
|
+
*/
|
|
44
|
+
stats(): {
|
|
45
|
+
available: number;
|
|
46
|
+
queueDepth: number;
|
|
47
|
+
maxCapacity: number;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create a capacity limiter with specified maximum capacity
|
|
52
|
+
*
|
|
53
|
+
* @param maxCapacity - Maximum number of concurrent permits
|
|
54
|
+
* @returns CapacityLimiter instance
|
|
55
|
+
*/
|
|
56
|
+
export declare function createCapacityLimiter(maxCapacity: number): CapacityLimiter;
|
|
57
|
+
//# sourceMappingURL=poolGate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolGate.d.ts","sourceRoot":"","sources":["../../../../src/indexer/dart/poolGate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAQD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;IAEhB;;OAEG;IACH,KAAK,IAAI;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAkF1E"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool capacity limiting semaphore for DartAnalysisClient pool
|
|
3
|
+
*
|
|
4
|
+
* Fix #1: Enforce MAX_CLIENTS limit with FIFO waiting queue
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* DartPoolBusyError: Thrown when waiting for pool capacity times out
|
|
8
|
+
*/
|
|
9
|
+
export class DartPoolBusyError extends Error {
|
|
10
|
+
constructor(message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "DartPoolBusyError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a capacity limiter with specified maximum capacity
|
|
17
|
+
*
|
|
18
|
+
* @param maxCapacity - Maximum number of concurrent permits
|
|
19
|
+
* @returns CapacityLimiter instance
|
|
20
|
+
*/
|
|
21
|
+
export function createCapacityLimiter(maxCapacity) {
|
|
22
|
+
let availablePermits = maxCapacity;
|
|
23
|
+
const waitingQueue = [];
|
|
24
|
+
function acquire(options) {
|
|
25
|
+
const timeoutMs = options?.timeoutMs ?? 0;
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
// Fast path: permit available immediately
|
|
28
|
+
if (availablePermits > 0) {
|
|
29
|
+
availablePermits--;
|
|
30
|
+
resolve();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Slow path: wait in queue
|
|
34
|
+
const request = {
|
|
35
|
+
resolve: () => {
|
|
36
|
+
availablePermits--;
|
|
37
|
+
resolve();
|
|
38
|
+
},
|
|
39
|
+
reject,
|
|
40
|
+
timeout: null, // Will be set below
|
|
41
|
+
};
|
|
42
|
+
// Setup timeout if specified
|
|
43
|
+
if (timeoutMs > 0) {
|
|
44
|
+
request.timeout = setTimeout(() => {
|
|
45
|
+
// Remove from queue
|
|
46
|
+
const index = waitingQueue.indexOf(request);
|
|
47
|
+
if (index !== -1) {
|
|
48
|
+
waitingQueue.splice(index, 1);
|
|
49
|
+
}
|
|
50
|
+
reject(new DartPoolBusyError(`Dart Analysis Server pool busy: waited ${timeoutMs}ms for available slot (queue depth: ${waitingQueue.length})`));
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
// Fix #11 (Codex Critical Review): unref() to prevent blocking Node.js exit
|
|
53
|
+
// Consistent with idle timer pattern in analyze.ts
|
|
54
|
+
request.timeout.unref();
|
|
55
|
+
}
|
|
56
|
+
waitingQueue.push(request);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function release() {
|
|
60
|
+
// Fix #7 (Critical Review): Defensive check to prevent exceeding max capacity
|
|
61
|
+
if (availablePermits >= maxCapacity) {
|
|
62
|
+
console.warn(`[poolGate] release() called when pool is at full capacity (${maxCapacity}). ` +
|
|
63
|
+
`This indicates a permit accounting bug. Current stats: ${JSON.stringify(stats())}`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
availablePermits++;
|
|
67
|
+
// Process waiting queue (FIFO)
|
|
68
|
+
while (waitingQueue.length > 0 && availablePermits > 0) {
|
|
69
|
+
const request = waitingQueue.shift();
|
|
70
|
+
clearTimeout(request.timeout);
|
|
71
|
+
request.resolve();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function stats() {
|
|
75
|
+
return {
|
|
76
|
+
available: availablePermits,
|
|
77
|
+
queueDepth: waitingQueue.length,
|
|
78
|
+
maxCapacity,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
acquire,
|
|
83
|
+
release,
|
|
84
|
+
stats,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=poolGate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poolGate.js","sourceRoot":"","sources":["../../../../src/indexer/dart/poolGate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;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;AA+CD;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,IAAI,gBAAgB,GAAG,WAAW,CAAC;IACnC,MAAM,YAAY,GAAqB,EAAE,CAAC;IAE1C,SAAS,OAAO,CAAC,OAAgC;QAC/C,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC;QAE1C,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,0CAA0C;YAC1C,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;gBACzB,gBAAgB,EAAE,CAAC;gBACnB,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,2BAA2B;YAC3B,MAAM,OAAO,GAAmB;gBAC9B,OAAO,EAAE,GAAG,EAAE;oBACZ,gBAAgB,EAAE,CAAC;oBACnB,OAAO,EAAE,CAAC;gBACZ,CAAC;gBACD,MAAM;gBACN,OAAO,EAAE,IAAiC,EAAE,oBAAoB;aACjE,CAAC;YAEF,6BAA6B;YAC7B,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBAClB,OAAO,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;oBAChC,oBAAoB;oBACpB,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;oBAC5C,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;wBACjB,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;oBAChC,CAAC;oBACD,MAAM,CACJ,IAAI,iBAAiB,CACnB,0CAA0C,SAAS,uCAAuC,YAAY,CAAC,MAAM,GAAG,CACjH,CACF,CAAC;gBACJ,CAAC,EAAE,SAAS,CAAC,CAAC;gBAEd,4EAA4E;gBAC5E,mDAAmD;gBACnD,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1B,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,OAAO;QACd,8EAA8E;QAC9E,IAAI,gBAAgB,IAAI,WAAW,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CACV,8DAA8D,WAAW,KAAK;gBAC5E,0DAA0D,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CACtF,CAAC;YACF,OAAO;QACT,CAAC;QAED,gBAAgB,EAAE,CAAC;QAEnB,+BAA+B;QAC/B,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAG,CAAC;YACtC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,SAAS,KAAK;QACZ,OAAO;YACL,SAAS,EAAE,gBAAgB;YAC3B,UAAU,EAAE,YAAY,CAAC,MAAM;YAC/B,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO;QACP,OAAO;QACP,KAAK;KACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dart SDK detection and validation utilities
|
|
3
|
+
*/
|
|
4
|
+
export interface DartSdkInfo {
|
|
5
|
+
sdkPath: string;
|
|
6
|
+
version: string;
|
|
7
|
+
analysisServerPath: string;
|
|
8
|
+
dartExecutable: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* MissingToolError: Dart SDKが見つからない場合のエラー
|
|
12
|
+
*/
|
|
13
|
+
export declare class MissingToolError extends Error {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Dart SDKの検出と検証
|
|
18
|
+
*
|
|
19
|
+
* 検出順序:
|
|
20
|
+
* 1. DART_SDK 環境変数
|
|
21
|
+
* 2. PATH から dart コマンド検索
|
|
22
|
+
*
|
|
23
|
+
* @returns DartSdkInfo
|
|
24
|
+
* @throws MissingToolError - Dart SDKが見つからない場合
|
|
25
|
+
*/
|
|
26
|
+
export declare function detectDartSdk(): DartSdkInfo;
|
|
27
|
+
/**
|
|
28
|
+
* Dart SDK が利用可能かチェック(throws しない版)
|
|
29
|
+
*
|
|
30
|
+
* Fix #5: 結果をメモ化して複数回の子プロセス生成を防ぐ
|
|
31
|
+
* Fix #25: 失敗時は一定時間後に再検証を許可(一時的な環境問題からの回復を可能にする)
|
|
32
|
+
*
|
|
33
|
+
* @returns SDK が利用可能な場合 true
|
|
34
|
+
*/
|
|
35
|
+
export declare function isDartSdkAvailable(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* SDK検出キャッシュを無効化(テスト用)
|
|
38
|
+
*/
|
|
39
|
+
export declare function invalidateSdkCache(): void;
|
|
40
|
+
//# sourceMappingURL=sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../../src/indexer/dart/sdk.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI,WAAW,CA2F3C;AAyCD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAuB5C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dart SDK detection and validation utilities
|
|
3
|
+
*/
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
// Fix #6: SDK detection timeout (default: 5000ms)
|
|
8
|
+
const SDK_DETECT_TIMEOUT_MS = parseInt(process.env.DART_SDK_DETECT_TIMEOUT_MS ?? "5000", 10);
|
|
9
|
+
/**
|
|
10
|
+
* MissingToolError: Dart SDKが見つからない場合のエラー
|
|
11
|
+
*/
|
|
12
|
+
export class MissingToolError extends Error {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "MissingToolError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Dart SDKの検出と検証
|
|
20
|
+
*
|
|
21
|
+
* 検出順序:
|
|
22
|
+
* 1. DART_SDK 環境変数
|
|
23
|
+
* 2. PATH から dart コマンド検索
|
|
24
|
+
*
|
|
25
|
+
* @returns DartSdkInfo
|
|
26
|
+
* @throws MissingToolError - Dart SDKが見つからない場合
|
|
27
|
+
*/
|
|
28
|
+
export function detectDartSdk() {
|
|
29
|
+
// Windows判定
|
|
30
|
+
const isWindows = process.platform === "win32";
|
|
31
|
+
const dartExeName = isWindows ? "dart.exe" : "dart";
|
|
32
|
+
// 1. DART_SDK 環境変数をチェック
|
|
33
|
+
const dartSdkEnv = process.env.DART_SDK;
|
|
34
|
+
if (dartSdkEnv) {
|
|
35
|
+
const dartPath = path.join(dartSdkEnv, "bin", dartExeName);
|
|
36
|
+
const snapshotPath = path.join(dartSdkEnv, "bin", "snapshots", "analysis_server.dart.snapshot");
|
|
37
|
+
if (existsSync(snapshotPath) && existsSync(dartPath)) {
|
|
38
|
+
const version = getDartVersion(dartPath);
|
|
39
|
+
return {
|
|
40
|
+
sdkPath: dartSdkEnv,
|
|
41
|
+
version,
|
|
42
|
+
analysisServerPath: snapshotPath,
|
|
43
|
+
dartExecutable: dartPath,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// 2. PATH から dart コマンドを検索(プラットフォーム別)
|
|
48
|
+
// Fix #6: Use spawnSync with timeout to prevent hanging on network issues
|
|
49
|
+
try {
|
|
50
|
+
const whichCmd = isWindows ? "where" : "which";
|
|
51
|
+
const result = spawnSync(whichCmd, ["dart"], {
|
|
52
|
+
encoding: "utf-8",
|
|
53
|
+
timeout: SDK_DETECT_TIMEOUT_MS,
|
|
54
|
+
killSignal: isWindows ? "SIGTERM" : "SIGKILL",
|
|
55
|
+
});
|
|
56
|
+
if (result.error) {
|
|
57
|
+
throw result.error;
|
|
58
|
+
}
|
|
59
|
+
if (result.status !== 0) {
|
|
60
|
+
// Command failed (dart not found in PATH)
|
|
61
|
+
throw new Error(`${whichCmd} dart failed with status ${result.status}`);
|
|
62
|
+
}
|
|
63
|
+
const dartPathOutput = (result.stdout || "").trim();
|
|
64
|
+
// where は複数行返す可能性があるので最初の行を使用
|
|
65
|
+
const dartPath = dartPathOutput.split("\n")[0]?.trim();
|
|
66
|
+
if (dartPath && existsSync(dartPath)) {
|
|
67
|
+
const version = getDartVersion(dartPath);
|
|
68
|
+
// dart コマンドから SDK パスを推測
|
|
69
|
+
// 通常 /path/to/dart-sdk/bin/dart なので bin の親ディレクトリ
|
|
70
|
+
const sdkPath = path.dirname(path.dirname(dartPath));
|
|
71
|
+
// Fix #2: Flutter SDK support - try multiple snapshot locations
|
|
72
|
+
// Flutter wrapper: <flutter>/bin/dart → snapshot at <flutter>/bin/cache/dart-sdk/bin/snapshots/
|
|
73
|
+
// Standalone SDK: <dart-sdk>/bin/dart → snapshot at <dart-sdk>/bin/snapshots/
|
|
74
|
+
const snapshotCandidates = [
|
|
75
|
+
path.join(sdkPath, "bin", "snapshots", "analysis_server.dart.snapshot"),
|
|
76
|
+
path.join(sdkPath, "bin", "cache", "dart-sdk", "bin", "snapshots", "analysis_server.dart.snapshot"),
|
|
77
|
+
];
|
|
78
|
+
for (const snapshotPath of snapshotCandidates) {
|
|
79
|
+
if (existsSync(snapshotPath)) {
|
|
80
|
+
// Flutter SDKの場合はactual SDK pathを調整
|
|
81
|
+
const actualSdkPath = snapshotPath.includes(path.join("cache", "dart-sdk"))
|
|
82
|
+
? path.join(sdkPath, "bin", "cache", "dart-sdk")
|
|
83
|
+
: sdkPath;
|
|
84
|
+
return {
|
|
85
|
+
sdkPath: actualSdkPath,
|
|
86
|
+
version,
|
|
87
|
+
analysisServerPath: snapshotPath,
|
|
88
|
+
dartExecutable: dartPath,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// which/where dart が失敗した場合は次へ
|
|
96
|
+
}
|
|
97
|
+
// Dart SDK が見つからない
|
|
98
|
+
throw new MissingToolError("Dart SDK not found. Please install Dart SDK and ensure 'dart' is in PATH, or set DART_SDK environment variable. Visit https://dart.dev/get-dart for installation instructions.");
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* dart --version の実行結果からバージョン文字列を取得
|
|
102
|
+
*
|
|
103
|
+
* @param dartExecutable - dart 実行ファイルのパス
|
|
104
|
+
* @returns バージョン文字列(例: "3.2.0")
|
|
105
|
+
*/
|
|
106
|
+
function getDartVersion(dartExecutable) {
|
|
107
|
+
// Fix #6: Use spawnSync with timeout to prevent hanging
|
|
108
|
+
const isWindows = process.platform === "win32";
|
|
109
|
+
const result = spawnSync(dartExecutable, ["--version"], {
|
|
110
|
+
encoding: "utf-8",
|
|
111
|
+
timeout: SDK_DETECT_TIMEOUT_MS,
|
|
112
|
+
killSignal: isWindows ? "SIGTERM" : "SIGKILL",
|
|
113
|
+
});
|
|
114
|
+
// Check stdout first, then stderr (dart --version outputs to stderr)
|
|
115
|
+
const output = result.stdout || result.stderr || "";
|
|
116
|
+
const match = output.match(/Dart SDK version:\s+(\S+)/);
|
|
117
|
+
if (match?.[1]) {
|
|
118
|
+
return match[1];
|
|
119
|
+
}
|
|
120
|
+
// If timeout or other error occurred, log it
|
|
121
|
+
if (result.error || result.signal) {
|
|
122
|
+
console.warn(`[getDartVersion] Failed to get version: error=${result.error?.message}, signal=${result.signal}`);
|
|
123
|
+
}
|
|
124
|
+
return "unknown";
|
|
125
|
+
}
|
|
126
|
+
// Fix #5: SDK検出結果をメモ化(大量ファイル処理時の性能改善)
|
|
127
|
+
// Fix #25 (Codex Critical Review Round 4): Don't cache failures permanently - allow retries
|
|
128
|
+
let cachedSdkAvailable = null;
|
|
129
|
+
let cacheTimestamp = 0;
|
|
130
|
+
const CACHE_FAILURE_TTL_MS = 60000; // Re-check failed detection after 60 seconds
|
|
131
|
+
/**
|
|
132
|
+
* Dart SDK が利用可能かチェック(throws しない版)
|
|
133
|
+
*
|
|
134
|
+
* Fix #5: 結果をメモ化して複数回の子プロセス生成を防ぐ
|
|
135
|
+
* Fix #25: 失敗時は一定時間後に再検証を許可(一時的な環境問題からの回復を可能にする)
|
|
136
|
+
*
|
|
137
|
+
* @returns SDK が利用可能な場合 true
|
|
138
|
+
*/
|
|
139
|
+
export function isDartSdkAvailable() {
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
// Success cache is永続的(環境が変わらない限り有効)
|
|
142
|
+
if (cachedSdkAvailable === true) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
// Failure cache has TTL - retry after expiration
|
|
146
|
+
if (cachedSdkAvailable === false && now - cacheTimestamp < CACHE_FAILURE_TTL_MS) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
detectDartSdk();
|
|
151
|
+
cachedSdkAvailable = true;
|
|
152
|
+
cacheTimestamp = now;
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
cachedSdkAvailable = false;
|
|
157
|
+
cacheTimestamp = now;
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* SDK検出キャッシュを無効化(テスト用)
|
|
163
|
+
*/
|
|
164
|
+
export function invalidateSdkCache() {
|
|
165
|
+
cachedSdkAvailable = null;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../../../src/indexer/dart/sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dart Analysis Server の Outline から KIRI の SymbolRecord への変換
|
|
3
|
+
*/
|
|
4
|
+
import type { SymbolRecord, SnippetRecord } from "../codeintel.js";
|
|
5
|
+
import type { Outline } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Outline を SymbolRecord と SnippetRecord に変換
|
|
8
|
+
*
|
|
9
|
+
* @param outline - Analysis Server の Outline
|
|
10
|
+
* @param content - ファイルの内容(行番号計算用)
|
|
11
|
+
* @returns { symbols, snippets }
|
|
12
|
+
*/
|
|
13
|
+
export declare function outlineToSymbols(outline: Outline, content: string): {
|
|
14
|
+
symbols: SymbolRecord[];
|
|
15
|
+
snippets: SnippetRecord[];
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../src/indexer/dart/transform.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,YAAY,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GACd;IAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,CAyCxD"}
|