mcp-test-timebox 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +192 -0
  3. package/dist/executor/index.d.ts +8 -0
  4. package/dist/executor/index.d.ts.map +1 -0
  5. package/dist/executor/index.js +8 -0
  6. package/dist/executor/index.js.map +1 -0
  7. package/dist/executor/process-executor.d.ts +93 -0
  8. package/dist/executor/process-executor.d.ts.map +1 -0
  9. package/dist/executor/process-executor.js +161 -0
  10. package/dist/executor/process-executor.js.map +1 -0
  11. package/dist/executor/timebox-controller.d.ts +109 -0
  12. package/dist/executor/timebox-controller.d.ts.map +1 -0
  13. package/dist/executor/timebox-controller.js +140 -0
  14. package/dist/executor/timebox-controller.js.map +1 -0
  15. package/dist/report/index.d.ts +8 -0
  16. package/dist/report/index.d.ts.map +1 -0
  17. package/dist/report/index.js +12 -0
  18. package/dist/report/index.js.map +1 -0
  19. package/dist/report/log-extractor.d.ts +125 -0
  20. package/dist/report/log-extractor.d.ts.map +1 -0
  21. package/dist/report/log-extractor.js +213 -0
  22. package/dist/report/log-extractor.js.map +1 -0
  23. package/dist/report/report-generator.d.ts +148 -0
  24. package/dist/report/report-generator.d.ts.map +1 -0
  25. package/dist/report/report-generator.js +261 -0
  26. package/dist/report/report-generator.js.map +1 -0
  27. package/dist/server.d.ts +27 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +150 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/tools/index.d.ts +7 -0
  32. package/dist/tools/index.d.ts.map +1 -0
  33. package/dist/tools/index.js +7 -0
  34. package/dist/tools/index.js.map +1 -0
  35. package/dist/tools/run-test.d.ts +80 -0
  36. package/dist/tools/run-test.d.ts.map +1 -0
  37. package/dist/tools/run-test.js +178 -0
  38. package/dist/tools/run-test.js.map +1 -0
  39. package/dist/utils/path-validator.d.ts +52 -0
  40. package/dist/utils/path-validator.d.ts.map +1 -0
  41. package/dist/utils/path-validator.js +128 -0
  42. package/dist/utils/path-validator.js.map +1 -0
  43. package/dist/validation/command-builder.d.ts +52 -0
  44. package/dist/validation/command-builder.d.ts.map +1 -0
  45. package/dist/validation/command-builder.js +143 -0
  46. package/dist/validation/command-builder.js.map +1 -0
  47. package/dist/validation/index.d.ts +8 -0
  48. package/dist/validation/index.d.ts.map +1 -0
  49. package/dist/validation/index.js +12 -0
  50. package/dist/validation/index.js.map +1 -0
  51. package/dist/validation/input-schema.d.ts +85 -0
  52. package/dist/validation/input-schema.d.ts.map +1 -0
  53. package/dist/validation/input-schema.js +113 -0
  54. package/dist/validation/input-schema.js.map +1 -0
  55. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 K.Kawanishi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # mcp-test-timebox
2
+
3
+ テスト実行の「終わらない/戻ってこない」問題を防ぐ、タイムボックス付きテスト専用MCPサーバ。
4
+
5
+ ## 概要
6
+
7
+ - **必ず結果を返す**: ハードタイムアウト・無出力タイムアウトにより、ハングしても必ずレスポンスを返却
8
+ - **安全な実行**: 任意コマンド実行を禁止し、固定テンプレート(`flutter test`等)のみ許可
9
+ - **成果物の保存**: 実行ごとに `raw.log` / `summary.md` / `summary.json` を生成
10
+
11
+ ## インストール
12
+
13
+ ### 前提条件
14
+
15
+ - Node.js 18.0.0 以上
16
+ - npm または yarn
17
+
18
+ ### インストール手順
19
+
20
+ ```bash
21
+ # リポジトリをクローン
22
+ git clone <repository-url>
23
+ cd mcp-test-timebox
24
+
25
+ # 依存関係をインストール
26
+ npm install
27
+
28
+ # ビルド
29
+ npm run build
30
+ ```
31
+
32
+ ## 使用方法
33
+
34
+ ### MCPサーバとして起動
35
+
36
+ ```bash
37
+ # stdio経由でMCPサーバを起動
38
+ npm run start
39
+
40
+ # または直接実行
41
+ node dist/server.js
42
+ ```
43
+
44
+ ### run_test ツールのパラメータ
45
+
46
+ | パラメータ | 型 | 必須 | 説明 |
47
+ |-----------|-----|------|------|
48
+ | `runner` | string | ✓ | テストランナー(現在は `flutter` のみ) |
49
+ | `scope` | string | ✓ | 実行スコープ: `all`, `file`, `pattern` |
50
+ | `target` | string | △ | `scope` が `file` または `pattern` の場合に必須 |
51
+ | `timeout_ms` | number | ✓ | ハードタイムアウト(ミリ秒) |
52
+ | `no_output_timeout_ms` | number | ✓ | 無出力タイムアウト(ミリ秒) |
53
+ | `max_output_bytes` | number | ✓ | 要約対象の末尾バイト数 |
54
+ | `report_dir` | string | - | レポート出力先(省略時は自動生成) |
55
+
56
+ ### 実行例
57
+
58
+ ```json
59
+ {
60
+ "runner": "flutter",
61
+ "scope": "all",
62
+ "timeout_ms": 300000,
63
+ "no_output_timeout_ms": 60000,
64
+ "max_output_bytes": 102400
65
+ }
66
+ ```
67
+
68
+ ```json
69
+ {
70
+ "runner": "flutter",
71
+ "scope": "file",
72
+ "target": "test/widget_test.dart",
73
+ "timeout_ms": 300000,
74
+ "no_output_timeout_ms": 60000,
75
+ "max_output_bytes": 102400
76
+ }
77
+ ```
78
+
79
+ ### レスポンス
80
+
81
+ ```json
82
+ {
83
+ "status": "pass",
84
+ "exit_code": 0,
85
+ "duration_ms": 12345,
86
+ "report_dir": ".cache/mcp-test-timebox/reports/20260113-123456",
87
+ "artifacts": {
88
+ "raw_log": ".cache/mcp-test-timebox/reports/20260113-123456/raw.log",
89
+ "summary_md": ".cache/mcp-test-timebox/reports/20260113-123456/summary.md",
90
+ "summary_json": ".cache/mcp-test-timebox/reports/20260113-123456/summary.json"
91
+ },
92
+ "excerpt": "..."
93
+ }
94
+ ```
95
+
96
+ ### ステータス一覧
97
+
98
+ | ステータス | 説明 |
99
+ |-----------|------|
100
+ | `pass` | テスト成功(exit code 0) |
101
+ | `fail` | テスト失敗(exit code ≠ 0) |
102
+ | `timeout` | ハードタイムアウト超過 |
103
+ | `no_output` | 無出力タイムアウト超過 |
104
+ | `error` | バリデーションエラー等 |
105
+
106
+ ## MCP設定例
107
+
108
+ ### Kiro での設定
109
+
110
+ `.kiro/settings/mcp.json`:
111
+
112
+ ```json
113
+ {
114
+ "mcpServers": {
115
+ "mcp-test-timebox": {
116
+ "command": "node",
117
+ "args": ["/path/to/mcp-test-timebox/dist/server.js"],
118
+ "disabled": false,
119
+ "autoApprove": []
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Claude Desktop での設定
126
+
127
+ `claude_desktop_config.json`:
128
+
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "mcp-test-timebox": {
133
+ "command": "node",
134
+ "args": ["/path/to/mcp-test-timebox/dist/server.js"]
135
+ }
136
+ }
137
+ }
138
+ ```
139
+
140
+ ## 開発
141
+
142
+ ### ビルド
143
+
144
+ ```bash
145
+ npm run build
146
+ ```
147
+
148
+ ### テスト実行
149
+
150
+ ```bash
151
+ # 全テスト実行
152
+ npm run test
153
+
154
+ # ウォッチモード
155
+ npm run test:watch
156
+
157
+ # カバレッジ付き
158
+ npm run test:coverage
159
+ ```
160
+
161
+ ### 開発モード(ウォッチビルド)
162
+
163
+ ```bash
164
+ npm run dev
165
+ ```
166
+
167
+ ## 成果物
168
+
169
+ テスト実行ごとに以下のファイルが生成されます:
170
+
171
+ ```
172
+ .cache/mcp-test-timebox/reports/<timestamp>/
173
+ ├── raw.log # stdout/stderrの完全ログ(出力元を区別)
174
+ ├── summary.md # 人間が読みやすい要約
175
+ └── summary.json # 機械処理用の構造化データ
176
+ ```
177
+
178
+ ### raw.log フォーマット
179
+
180
+ ```
181
+ [2026-01-13T12:34:56.789Z] [stdout] Running "flutter test"...
182
+ [2026-01-13T12:34:57.123Z] [stderr] Warning: some warning
183
+ [2026-01-13T12:34:58.456Z] [stdout] ✓ Test passed
184
+ ```
185
+
186
+ ## ドキュメント
187
+
188
+ - [MVP要件](docs/MVP.md) - プロジェクトのMVP仕様
189
+
190
+ ## ライセンス
191
+
192
+ MIT License - 詳細は [LICENSE](LICENSE) を参照
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Executor モジュール
3
+ *
4
+ * プロセス実行とタイムアウト監視に関するコンポーネントをエクスポート
5
+ */
6
+ export { TimeboxController, createTimeboxController, type ITimeboxController, type TimeoutType, type TimeoutCallback, } from './timebox-controller.js';
7
+ export { ProcessExecutor, createProcessExecutor, type IProcessExecutor, type ProcessExecutorOptions, type ProcessResult, type ProcessStatus, type LogEntry, } from './process-executor.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/executor/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Executor モジュール
3
+ *
4
+ * プロセス実行とタイムアウト監視に関するコンポーネントをエクスポート
5
+ */
6
+ export { TimeboxController, createTimeboxController, } from './timebox-controller.js';
7
+ export { ProcessExecutor, createProcessExecutor, } from './process-executor.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/executor/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GAIxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,qBAAqB,GAMtB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * ProcessExecutor - プロセス実行とタイムアウト監視コンポーネント
3
+ *
4
+ * 子プロセスを生成し、タイムアウト監視を行う。
5
+ * - stdinを即座に閉じる
6
+ * - tree-killでプロセスツリーごと終了
7
+ * - stdout/stderrをLogEntryとして収集
8
+ *
9
+ * Requirements:
10
+ * - 3.1: プロセス起動時にstdinを即座に閉じる
11
+ * - 3.2: timeout_ms で指定された時間が経過したらプロセスを強制終了
12
+ * - 3.3: no_output_timeout_ms で指定された時間、出力がなければ強制終了
13
+ * - 3.4: プロセスツリーごと終了する
14
+ * - 3.5: exit code 0 で pass、それ以外で fail を返す
15
+ */
16
+ /**
17
+ * ログエントリ - stdout/stderrの出力を記録
18
+ */
19
+ export interface LogEntry {
20
+ /** Unix timestamp (ms) */
21
+ timestamp: number;
22
+ /** 出力元ストリーム */
23
+ stream: 'stdout' | 'stderr';
24
+ /** 出力データ */
25
+ data: string;
26
+ }
27
+ /**
28
+ * プロセス実行結果のステータス
29
+ */
30
+ export type ProcessStatus = 'pass' | 'fail' | 'timeout' | 'no_output' | 'error';
31
+ /**
32
+ * プロセス実行結果
33
+ */
34
+ export interface ProcessResult {
35
+ /** 実行ステータス */
36
+ status: ProcessStatus;
37
+ /** 終了コード(タイムアウト時はnull) */
38
+ exitCode: number | null;
39
+ /** 実行時間(ミリ秒) */
40
+ durationMs: number;
41
+ /** ログエントリ(stdout/stderr) */
42
+ logs: LogEntry[];
43
+ /** タイムアウトしたかどうか */
44
+ timedOut: boolean;
45
+ /** 無出力タイムアウトしたかどうか */
46
+ noOutput: boolean;
47
+ }
48
+ /**
49
+ * プロセス実行オプション
50
+ */
51
+ export interface ProcessExecutorOptions {
52
+ /** 作業ディレクトリ */
53
+ cwd: string;
54
+ /** ハードタイムアウト(ミリ秒) */
55
+ timeoutMs: number;
56
+ /** 無出力タイムアウト(ミリ秒) */
57
+ noOutputTimeoutMs: number;
58
+ }
59
+ /**
60
+ * ProcessExecutorインターフェース
61
+ */
62
+ export interface IProcessExecutor {
63
+ /**
64
+ * プロセスを実行し、タイムアウト監視を行う
65
+ *
66
+ * @param command - 実行するコマンド
67
+ * @param args - コマンド引数
68
+ * @param options - 実行オプション
69
+ * @returns プロセス実行結果
70
+ */
71
+ execute(command: string, args: string[], options: ProcessExecutorOptions): Promise<ProcessResult>;
72
+ }
73
+ /**
74
+ * ProcessExecutor - プロセス実行の実装
75
+ */
76
+ export declare class ProcessExecutor implements IProcessExecutor {
77
+ /**
78
+ * プロセスを実行し、タイムアウト監視を行う
79
+ *
80
+ * @param command - 実行するコマンド
81
+ * @param args - コマンド引数
82
+ * @param options - 実行オプション
83
+ * @returns プロセス実行結果
84
+ */
85
+ execute(command: string, args: string[], options: ProcessExecutorOptions): Promise<ProcessResult>;
86
+ }
87
+ /**
88
+ * ProcessExecutorのファクトリ関数
89
+ *
90
+ * @returns 新しいProcessExecutorインスタンス
91
+ */
92
+ export declare function createProcessExecutor(): IProcessExecutor;
93
+ //# sourceMappingURL=process-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-executor.d.ts","sourceRoot":"","sources":["../../src/executor/process-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,cAAc;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,gBAAgB;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,mBAAmB;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,sBAAsB;IACtB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,eAAe;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAGD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;OAOG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,aAAa,CAAC,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD;;;;;;;OAOG;IACG,OAAO,CACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,aAAa,CAAC;CAwI1B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAExD"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * ProcessExecutor - プロセス実行とタイムアウト監視コンポーネント
3
+ *
4
+ * 子プロセスを生成し、タイムアウト監視を行う。
5
+ * - stdinを即座に閉じる
6
+ * - tree-killでプロセスツリーごと終了
7
+ * - stdout/stderrをLogEntryとして収集
8
+ *
9
+ * Requirements:
10
+ * - 3.1: プロセス起動時にstdinを即座に閉じる
11
+ * - 3.2: timeout_ms で指定された時間が経過したらプロセスを強制終了
12
+ * - 3.3: no_output_timeout_ms で指定された時間、出力がなければ強制終了
13
+ * - 3.4: プロセスツリーごと終了する
14
+ * - 3.5: exit code 0 で pass、それ以外で fail を返す
15
+ */
16
+ import { spawn } from 'node:child_process';
17
+ import treeKill from 'tree-kill';
18
+ import { createTimeboxController } from './timebox-controller.js';
19
+ /**
20
+ * ProcessExecutor - プロセス実行の実装
21
+ */
22
+ export class ProcessExecutor {
23
+ /**
24
+ * プロセスを実行し、タイムアウト監視を行う
25
+ *
26
+ * @param command - 実行するコマンド
27
+ * @param args - コマンド引数
28
+ * @param options - 実行オプション
29
+ * @returns プロセス実行結果
30
+ */
31
+ async execute(command, args, options) {
32
+ const startTime = Date.now();
33
+ const logs = [];
34
+ const timebox = createTimeboxController();
35
+ return new Promise((resolve) => {
36
+ let childProcess = null;
37
+ let resolved = false;
38
+ /**
39
+ * 結果を返す(一度だけ)
40
+ */
41
+ const finalize = (result) => {
42
+ if (resolved)
43
+ return;
44
+ resolved = true;
45
+ timebox.clear();
46
+ resolve(result);
47
+ };
48
+ /**
49
+ * プロセスを強制終了する
50
+ */
51
+ const killProcess = (timeoutType) => {
52
+ if (childProcess && childProcess.pid) {
53
+ // tree-killでプロセスツリーごと終了(Requirements 3.4)
54
+ treeKill(childProcess.pid, 'SIGKILL', (err) => {
55
+ if (err) {
56
+ // エラーが発生してもログに記録するのみ
57
+ console.error(`[ProcessExecutor] tree-kill error: ${err.message}`);
58
+ }
59
+ });
60
+ }
61
+ const durationMs = Date.now() - startTime;
62
+ const isNoOutput = timeoutType === 'no_output';
63
+ finalize({
64
+ status: isNoOutput ? 'no_output' : 'timeout',
65
+ exitCode: null,
66
+ durationMs,
67
+ logs,
68
+ timedOut: !isNoOutput,
69
+ noOutput: isNoOutput,
70
+ });
71
+ };
72
+ try {
73
+ // プロセスを起動
74
+ childProcess = spawn(command, args, {
75
+ cwd: options.cwd,
76
+ stdio: ['pipe', 'pipe', 'pipe'],
77
+ // Windowsでは shell: true が必要な場合がある
78
+ shell: process.platform === 'win32',
79
+ });
80
+ // stdinを即座に閉じる(Requirements 3.1)
81
+ if (childProcess.stdin) {
82
+ childProcess.stdin.end();
83
+ }
84
+ // タイムアウト設定(Requirements 3.2, 3.3)
85
+ timebox.setHardTimeout(options.timeoutMs, killProcess);
86
+ timebox.setNoOutputTimeout(options.noOutputTimeoutMs, killProcess);
87
+ // stdout監視
88
+ if (childProcess.stdout) {
89
+ childProcess.stdout.on('data', (data) => {
90
+ const entry = {
91
+ timestamp: Date.now(),
92
+ stream: 'stdout',
93
+ data: data.toString(),
94
+ };
95
+ logs.push(entry);
96
+ timebox.notifyOutput();
97
+ });
98
+ }
99
+ // stderr監視
100
+ if (childProcess.stderr) {
101
+ childProcess.stderr.on('data', (data) => {
102
+ const entry = {
103
+ timestamp: Date.now(),
104
+ stream: 'stderr',
105
+ data: data.toString(),
106
+ };
107
+ logs.push(entry);
108
+ timebox.notifyOutput();
109
+ });
110
+ }
111
+ // プロセス終了時
112
+ childProcess.on('close', (code) => {
113
+ const durationMs = Date.now() - startTime;
114
+ // exit code に基づいてステータスを決定(Requirements 3.5)
115
+ const status = code === 0 ? 'pass' : 'fail';
116
+ finalize({
117
+ status,
118
+ exitCode: code,
119
+ durationMs,
120
+ logs,
121
+ timedOut: false,
122
+ noOutput: false,
123
+ });
124
+ });
125
+ // プロセスエラー時
126
+ childProcess.on('error', (err) => {
127
+ const durationMs = Date.now() - startTime;
128
+ finalize({
129
+ status: 'error',
130
+ exitCode: null,
131
+ durationMs,
132
+ logs,
133
+ timedOut: false,
134
+ noOutput: false,
135
+ });
136
+ });
137
+ }
138
+ catch (err) {
139
+ // spawn自体が失敗した場合
140
+ const durationMs = Date.now() - startTime;
141
+ finalize({
142
+ status: 'error',
143
+ exitCode: null,
144
+ durationMs,
145
+ logs,
146
+ timedOut: false,
147
+ noOutput: false,
148
+ });
149
+ }
150
+ });
151
+ }
152
+ }
153
+ /**
154
+ * ProcessExecutorのファクトリ関数
155
+ *
156
+ * @returns 新しいProcessExecutorインスタンス
157
+ */
158
+ export function createProcessExecutor() {
159
+ return new ProcessExecutor();
160
+ }
161
+ //# sourceMappingURL=process-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-executor.js","sourceRoot":"","sources":["../../src/executor/process-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * TimeboxController - タイムアウト監視コンポーネント
3
+ *
4
+ * プロセス実行のタイムアウトを管理する。
5
+ * - ハードタイムアウト: 指定時間経過で強制終了
6
+ * - 無出力タイムアウト: 出力がない状態が続くと強制終了
7
+ *
8
+ * Requirements:
9
+ * - 3.2: timeout_ms で指定された時間が経過したらプロセスを強制終了
10
+ * - 3.3: no_output_timeout_ms で指定された時間、出力がなければ強制終了
11
+ */
12
+ /**
13
+ * タイムアウトの種類
14
+ */
15
+ export type TimeoutType = 'hard' | 'no_output';
16
+ /**
17
+ * タイムアウト発生時のコールバック
18
+ */
19
+ export type TimeoutCallback = (type: TimeoutType) => void;
20
+ /**
21
+ * TimeboxControllerインターフェース
22
+ */
23
+ export interface ITimeboxController {
24
+ /** ハードタイムアウトを設定 */
25
+ setHardTimeout(ms: number, onTimeout: TimeoutCallback): void;
26
+ /** 無出力タイムアウトを設定 */
27
+ setNoOutputTimeout(ms: number, onTimeout: TimeoutCallback): void;
28
+ /** 出力があったことを通知(無出力タイマーをリセット) */
29
+ notifyOutput(): void;
30
+ /** すべてのタイマーをクリア */
31
+ clear(): void;
32
+ /** タイムアウトが発生したかどうか */
33
+ isTimedOut(): boolean;
34
+ /** タイムアウトの種類を取得 */
35
+ getTimeoutType(): TimeoutType | null;
36
+ }
37
+ /**
38
+ * TimeboxController - タイムアウト監視の実装
39
+ *
40
+ * 2種類のタイムアウトを管理:
41
+ * 1. ハードタイムアウト: 設定後、指定時間で必ず発火
42
+ * 2. 無出力タイムアウト: 出力があるたびにリセットされる
43
+ */
44
+ export declare class TimeboxController implements ITimeboxController {
45
+ /** ハードタイムアウトのタイマーID */
46
+ private hardTimeoutId;
47
+ /** 無出力タイムアウトのタイマーID */
48
+ private noOutputTimeoutId;
49
+ /** 無出力タイムアウトの設定値(リセット用) */
50
+ private noOutputTimeoutMs;
51
+ /** 無出力タイムアウトのコールバック(リセット用) */
52
+ private noOutputCallback;
53
+ /** タイムアウトが発生したかどうか */
54
+ private timedOut;
55
+ /** 発生したタイムアウトの種類 */
56
+ private timeoutType;
57
+ /**
58
+ * ハードタイムアウトを設定する
59
+ *
60
+ * 指定時間経過後、コールバックを呼び出す。
61
+ * 一度設定すると、clear()が呼ばれるまでリセットされない。
62
+ *
63
+ * @param ms - タイムアウト時間(ミリ秒)
64
+ * @param onTimeout - タイムアウト時のコールバック
65
+ */
66
+ setHardTimeout(ms: number, onTimeout: TimeoutCallback): void;
67
+ /**
68
+ * 無出力タイムアウトを設定する
69
+ *
70
+ * 指定時間、stdout/stderrに出力がない場合にコールバックを呼び出す。
71
+ * notifyOutput()が呼ばれるとタイマーがリセットされる。
72
+ *
73
+ * @param ms - タイムアウト時間(ミリ秒)
74
+ * @param onTimeout - タイムアウト時のコールバック
75
+ */
76
+ setNoOutputTimeout(ms: number, onTimeout: TimeoutCallback): void;
77
+ /**
78
+ * 出力があったことを通知する
79
+ *
80
+ * 無出力タイマーをリセットする。
81
+ * ハードタイムアウトには影響しない。
82
+ */
83
+ notifyOutput(): void;
84
+ /**
85
+ * すべてのタイマーをクリアする
86
+ *
87
+ * プロセス終了時や、タイムアウト発生時に呼び出す。
88
+ */
89
+ clear(): void;
90
+ /**
91
+ * タイムアウトが発生したかどうかを返す
92
+ */
93
+ isTimedOut(): boolean;
94
+ /**
95
+ * 発生したタイムアウトの種類を返す
96
+ */
97
+ getTimeoutType(): TimeoutType | null;
98
+ /**
99
+ * 無出力タイマーをリセットする(内部メソッド)
100
+ */
101
+ private resetNoOutputTimer;
102
+ }
103
+ /**
104
+ * TimeboxControllerのファクトリ関数
105
+ *
106
+ * @returns 新しいTimeboxControllerインスタンス
107
+ */
108
+ export declare function createTimeboxController(): ITimeboxController;
109
+ //# sourceMappingURL=timebox-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timebox-controller.d.ts","sourceRoot":"","sources":["../../src/executor/timebox-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7D,mBAAmB;IACnB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IACjE,gCAAgC;IAChC,YAAY,IAAI,IAAI,CAAC;IACrB,mBAAmB;IACnB,KAAK,IAAI,IAAI,CAAC;IACd,sBAAsB;IACtB,UAAU,IAAI,OAAO,CAAC;IACtB,mBAAmB;IACnB,cAAc,IAAI,WAAW,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;GAMG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;IAC1D,uBAAuB;IACvB,OAAO,CAAC,aAAa,CAA8C;IAEnE,uBAAuB;IACvB,OAAO,CAAC,iBAAiB,CAA8C;IAEvE,2BAA2B;IAC3B,OAAO,CAAC,iBAAiB,CAAuB;IAEhD,8BAA8B;IAC9B,OAAO,CAAC,gBAAgB,CAAgC;IAExD,sBAAsB;IACtB,OAAO,CAAC,QAAQ,CAAS;IAEzB,oBAAoB;IACpB,OAAO,CAAC,WAAW,CAA4B;IAE/C;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI;IAe5D;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,IAAI;IAShE;;;;;OAKG;IACH,YAAY,IAAI,IAAI;IAOpB;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAgBb;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAiB3B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,kBAAkB,CAE5D"}