aicodeman 0.2.8
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/LICENSE +21 -0
- package/README.md +403 -0
- package/dist/ai-checker-base.d.ts +175 -0
- package/dist/ai-checker-base.d.ts.map +1 -0
- package/dist/ai-checker-base.js +424 -0
- package/dist/ai-checker-base.js.map +1 -0
- package/dist/ai-idle-checker.d.ts +53 -0
- package/dist/ai-idle-checker.d.ts.map +1 -0
- package/dist/ai-idle-checker.js +141 -0
- package/dist/ai-idle-checker.js.map +1 -0
- package/dist/ai-plan-checker.d.ts +52 -0
- package/dist/ai-plan-checker.d.ts.map +1 -0
- package/dist/ai-plan-checker.js +103 -0
- package/dist/ai-plan-checker.js.map +1 -0
- package/dist/bash-tool-parser.d.ts +191 -0
- package/dist/bash-tool-parser.d.ts.map +1 -0
- package/dist/bash-tool-parser.js +598 -0
- package/dist/bash-tool-parser.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +460 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/buffer-limits.d.ts +59 -0
- package/dist/config/buffer-limits.d.ts.map +1 -0
- package/dist/config/buffer-limits.js +74 -0
- package/dist/config/buffer-limits.js.map +1 -0
- package/dist/config/map-limits.d.ts +40 -0
- package/dist/config/map-limits.d.ts.map +1 -0
- package/dist/config/map-limits.js +52 -0
- package/dist/config/map-limits.js.map +1 -0
- package/dist/file-stream-manager.d.ts +148 -0
- package/dist/file-stream-manager.d.ts.map +1 -0
- package/dist/file-stream-manager.js +351 -0
- package/dist/file-stream-manager.js.map +1 -0
- package/dist/hooks-config.d.ts +31 -0
- package/dist/hooks-config.d.ts.map +1 -0
- package/dist/hooks-config.js +115 -0
- package/dist/hooks-config.js.map +1 -0
- package/dist/image-watcher.d.ts +86 -0
- package/dist/image-watcher.d.ts.map +1 -0
- package/dist/image-watcher.js +275 -0
- package/dist/image-watcher.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/mux-factory.d.ts +13 -0
- package/dist/mux-factory.d.ts.map +1 -0
- package/dist/mux-factory.js +19 -0
- package/dist/mux-factory.js.map +1 -0
- package/dist/mux-interface.d.ts +145 -0
- package/dist/mux-interface.d.ts.map +1 -0
- package/dist/mux-interface.js +9 -0
- package/dist/mux-interface.js.map +1 -0
- package/dist/plan-orchestrator.d.ts +123 -0
- package/dist/plan-orchestrator.d.ts.map +1 -0
- package/dist/plan-orchestrator.js +500 -0
- package/dist/plan-orchestrator.js.map +1 -0
- package/dist/prompts/index.d.ts +9 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +9 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/planner.d.ts +14 -0
- package/dist/prompts/planner.d.ts.map +1 -0
- package/dist/prompts/planner.js +83 -0
- package/dist/prompts/planner.js.map +1 -0
- package/dist/prompts/research-agent.d.ts +10 -0
- package/dist/prompts/research-agent.d.ts.map +1 -0
- package/dist/prompts/research-agent.js +143 -0
- package/dist/prompts/research-agent.js.map +1 -0
- package/dist/push-store.d.ts +41 -0
- package/dist/push-store.d.ts.map +1 -0
- package/dist/push-store.js +168 -0
- package/dist/push-store.js.map +1 -0
- package/dist/ralph-config.d.ts +67 -0
- package/dist/ralph-config.d.ts.map +1 -0
- package/dist/ralph-config.js +134 -0
- package/dist/ralph-config.js.map +1 -0
- package/dist/ralph-loop.d.ts +124 -0
- package/dist/ralph-loop.d.ts.map +1 -0
- package/dist/ralph-loop.js +418 -0
- package/dist/ralph-loop.js.map +1 -0
- package/dist/ralph-tracker.d.ts +1081 -0
- package/dist/ralph-tracker.d.ts.map +1 -0
- package/dist/ralph-tracker.js +3343 -0
- package/dist/ralph-tracker.js.map +1 -0
- package/dist/respawn-controller.d.ts +1182 -0
- package/dist/respawn-controller.d.ts.map +1 -0
- package/dist/respawn-controller.js +2754 -0
- package/dist/respawn-controller.js.map +1 -0
- package/dist/run-summary.d.ts +123 -0
- package/dist/run-summary.d.ts.map +1 -0
- package/dist/run-summary.js +325 -0
- package/dist/run-summary.js.map +1 -0
- package/dist/session-lifecycle-log.d.ts +36 -0
- package/dist/session-lifecycle-log.d.ts.map +1 -0
- package/dist/session-lifecycle-log.js +101 -0
- package/dist/session-lifecycle-log.js.map +1 -0
- package/dist/session-manager.d.ts +97 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +224 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/session.d.ts +686 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +2025 -0
- package/dist/session.js.map +1 -0
- package/dist/state-store.d.ts +189 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +730 -0
- package/dist/state-store.js.map +1 -0
- package/dist/subagent-watcher.d.ts +345 -0
- package/dist/subagent-watcher.d.ts.map +1 -0
- package/dist/subagent-watcher.js +1469 -0
- package/dist/subagent-watcher.js.map +1 -0
- package/dist/task-queue.d.ts +108 -0
- package/dist/task-queue.d.ts.map +1 -0
- package/dist/task-queue.js +235 -0
- package/dist/task-queue.js.map +1 -0
- package/dist/task-tracker.d.ts +306 -0
- package/dist/task-tracker.d.ts.map +1 -0
- package/dist/task-tracker.js +488 -0
- package/dist/task-tracker.js.map +1 -0
- package/dist/task.d.ts +73 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +177 -0
- package/dist/task.js.map +1 -0
- package/dist/team-watcher.d.ts +53 -0
- package/dist/team-watcher.d.ts.map +1 -0
- package/dist/team-watcher.js +313 -0
- package/dist/team-watcher.js.map +1 -0
- package/dist/templates/case-template.md +461 -0
- package/dist/templates/claude-md.d.ts +26 -0
- package/dist/templates/claude-md.d.ts.map +1 -0
- package/dist/templates/claude-md.js +74 -0
- package/dist/templates/claude-md.js.map +1 -0
- package/dist/tmux-manager.d.ts +181 -0
- package/dist/tmux-manager.d.ts.map +1 -0
- package/dist/tmux-manager.js +1405 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/transcript-watcher.d.ts +110 -0
- package/dist/transcript-watcher.d.ts.map +1 -0
- package/dist/transcript-watcher.js +338 -0
- package/dist/transcript-watcher.js.map +1 -0
- package/dist/tunnel-manager.d.ts +54 -0
- package/dist/tunnel-manager.d.ts.map +1 -0
- package/dist/tunnel-manager.js +251 -0
- package/dist/tunnel-manager.js.map +1 -0
- package/dist/types.d.ts +1139 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +215 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/buffer-accumulator.d.ts +111 -0
- package/dist/utils/buffer-accumulator.d.ts.map +1 -0
- package/dist/utils/buffer-accumulator.js +172 -0
- package/dist/utils/buffer-accumulator.js.map +1 -0
- package/dist/utils/claude-cli-resolver.d.ts +26 -0
- package/dist/utils/claude-cli-resolver.d.ts.map +1 -0
- package/dist/utils/claude-cli-resolver.js +78 -0
- package/dist/utils/claude-cli-resolver.js.map +1 -0
- package/dist/utils/cleanup-manager.d.ts +165 -0
- package/dist/utils/cleanup-manager.d.ts.map +1 -0
- package/dist/utils/cleanup-manager.js +274 -0
- package/dist/utils/cleanup-manager.js.map +1 -0
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/lru-map.d.ts +140 -0
- package/dist/utils/lru-map.d.ts.map +1 -0
- package/dist/utils/lru-map.js +234 -0
- package/dist/utils/lru-map.js.map +1 -0
- package/dist/utils/nice-wrapper.d.ts +13 -0
- package/dist/utils/nice-wrapper.d.ts.map +1 -0
- package/dist/utils/nice-wrapper.js +17 -0
- package/dist/utils/nice-wrapper.js.map +1 -0
- package/dist/utils/opencode-cli-resolver.d.ts +21 -0
- package/dist/utils/opencode-cli-resolver.d.ts.map +1 -0
- package/dist/utils/opencode-cli-resolver.js +67 -0
- package/dist/utils/opencode-cli-resolver.js.map +1 -0
- package/dist/utils/regex-patterns.d.ts +64 -0
- package/dist/utils/regex-patterns.d.ts.map +1 -0
- package/dist/utils/regex-patterns.js +74 -0
- package/dist/utils/regex-patterns.js.map +1 -0
- package/dist/utils/stale-expiration-map.d.ts +159 -0
- package/dist/utils/stale-expiration-map.d.ts.map +1 -0
- package/dist/utils/stale-expiration-map.js +277 -0
- package/dist/utils/stale-expiration-map.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +108 -0
- package/dist/utils/string-similarity.d.ts.map +1 -0
- package/dist/utils/string-similarity.js +189 -0
- package/dist/utils/string-similarity.js.map +1 -0
- package/dist/utils/token-validation.d.ts +39 -0
- package/dist/utils/token-validation.d.ts.map +1 -0
- package/dist/utils/token-validation.js +59 -0
- package/dist/utils/token-validation.js.map +1 -0
- package/dist/utils/type-safety.d.ts +33 -0
- package/dist/utils/type-safety.d.ts.map +1 -0
- package/dist/utils/type-safety.js +35 -0
- package/dist/utils/type-safety.js.map +1 -0
- package/dist/web/public/app.js +491 -0
- package/dist/web/public/app.js.br +0 -0
- package/dist/web/public/app.js.gz +0 -0
- package/dist/web/public/index.html +1675 -0
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/manifest.json +8 -0
- package/dist/web/public/mobile.css +1 -0
- package/dist/web/public/mobile.css.br +0 -0
- package/dist/web/public/mobile.css.gz +0 -0
- package/dist/web/public/ralph-wizard.js +1037 -0
- package/dist/web/public/ralph-wizard.js.br +0 -0
- package/dist/web/public/ralph-wizard.js.gz +0 -0
- package/dist/web/public/styles.css +1 -0
- package/dist/web/public/styles.css.br +0 -0
- package/dist/web/public/styles.css.gz +0 -0
- package/dist/web/public/sw.js +67 -0
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/upload.html +155 -0
- package/dist/web/public/upload.html.br +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js +1 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js +1 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js +2 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css +209 -0
- package/dist/web/public/vendor/xterm.css.br +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js +9 -0
- package/dist/web/public/vendor/xterm.min.js.br +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/schemas.d.ts +479 -0
- package/dist/web/schemas.d.ts.map +1 -0
- package/dist/web/schemas.js +448 -0
- package/dist/web/schemas.js.map +1 -0
- package/dist/web/server.d.ts +207 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +5784 -0
- package/dist/web/server.js.map +1 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +390 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Centralized Map size limits for memory management.
|
|
3
|
+
*
|
|
4
|
+
* These constants define maximum sizes for Maps that track ephemeral data.
|
|
5
|
+
* Without limits, long-running sessions can accumulate unbounded entries
|
|
6
|
+
* leading to memory leaks.
|
|
7
|
+
*
|
|
8
|
+
* Memory Budget Rationale:
|
|
9
|
+
* - Assuming average entry size of ~1KB
|
|
10
|
+
* - MAX_TRACKED_AGENTS=500 × 1KB = ~500KB for agent tracking
|
|
11
|
+
* - Activity/results per agent × agents = bounded by these limits
|
|
12
|
+
* - Total Map overhead: <50MB even under heavy load
|
|
13
|
+
*
|
|
14
|
+
* @module config/map-limits
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Maximum concurrent sessions allowed.
|
|
18
|
+
* Each session consumes significant resources (PTY, buffers, watchers).
|
|
19
|
+
*/
|
|
20
|
+
export declare const MAX_CONCURRENT_SESSIONS = 50;
|
|
21
|
+
/**
|
|
22
|
+
* Maximum concurrent SSE client connections.
|
|
23
|
+
* Each connection holds an open HTTP response and receives all broadcast events.
|
|
24
|
+
*/
|
|
25
|
+
export declare const MAX_SSE_CLIENTS = 100;
|
|
26
|
+
/**
|
|
27
|
+
* Maximum todo items to track per session.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MAX_TODOS_PER_SESSION = 500;
|
|
30
|
+
/**
|
|
31
|
+
* Maximum pending tool calls to track per subagent.
|
|
32
|
+
* Entries should be cleaned up on tool_result, but this prevents leaks.
|
|
33
|
+
*/
|
|
34
|
+
export declare const MAX_PENDING_TOOL_CALLS = 100;
|
|
35
|
+
/**
|
|
36
|
+
* TTL for orphaned pending tool calls (5 minutes).
|
|
37
|
+
* If no tool_result received, entry is cleaned up.
|
|
38
|
+
*/
|
|
39
|
+
export declare const PENDING_TOOL_CALL_TTL_MS: number;
|
|
40
|
+
//# sourceMappingURL=map-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-limits.d.ts","sourceRoot":"","sources":["../../src/config/map-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAM1C;;;GAGG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AAMnC;;GAEG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAMzC;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,wBAAwB,QAAgB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Centralized Map size limits for memory management.
|
|
3
|
+
*
|
|
4
|
+
* These constants define maximum sizes for Maps that track ephemeral data.
|
|
5
|
+
* Without limits, long-running sessions can accumulate unbounded entries
|
|
6
|
+
* leading to memory leaks.
|
|
7
|
+
*
|
|
8
|
+
* Memory Budget Rationale:
|
|
9
|
+
* - Assuming average entry size of ~1KB
|
|
10
|
+
* - MAX_TRACKED_AGENTS=500 × 1KB = ~500KB for agent tracking
|
|
11
|
+
* - Activity/results per agent × agents = bounded by these limits
|
|
12
|
+
* - Total Map overhead: <50MB even under heavy load
|
|
13
|
+
*
|
|
14
|
+
* @module config/map-limits
|
|
15
|
+
*/
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Session Tracking Limits
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Maximum concurrent sessions allowed.
|
|
21
|
+
* Each session consumes significant resources (PTY, buffers, watchers).
|
|
22
|
+
*/
|
|
23
|
+
export const MAX_CONCURRENT_SESSIONS = 50;
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// SSE Client Limits
|
|
26
|
+
// ============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Maximum concurrent SSE client connections.
|
|
29
|
+
* Each connection holds an open HTTP response and receives all broadcast events.
|
|
30
|
+
*/
|
|
31
|
+
export const MAX_SSE_CLIENTS = 100;
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Todo Item Limits (Ralph Tracker)
|
|
34
|
+
// ============================================================================
|
|
35
|
+
/**
|
|
36
|
+
* Maximum todo items to track per session.
|
|
37
|
+
*/
|
|
38
|
+
export const MAX_TODOS_PER_SESSION = 500;
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Pending Tool Calls Limits
|
|
41
|
+
// ============================================================================
|
|
42
|
+
/**
|
|
43
|
+
* Maximum pending tool calls to track per subagent.
|
|
44
|
+
* Entries should be cleaned up on tool_result, but this prevents leaks.
|
|
45
|
+
*/
|
|
46
|
+
export const MAX_PENDING_TOOL_CALLS = 100;
|
|
47
|
+
/**
|
|
48
|
+
* TTL for orphaned pending tool calls (5 minutes).
|
|
49
|
+
* If no tool_result received, entry is cleaned up.
|
|
50
|
+
*/
|
|
51
|
+
export const PENDING_TOOL_CALL_TTL_MS = 5 * 60 * 1000;
|
|
52
|
+
//# sourceMappingURL=map-limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-limits.js","sourceRoot":"","sources":["../../src/config/map-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC,+EAA+E;AAC/E,mCAAmC;AACnC,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAEzC,+EAA+E;AAC/E,4BAA4B;AAC5B,+EAA+E;AAE/E;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview File Stream Manager - Manages tail -f processes for live log viewing
|
|
3
|
+
*
|
|
4
|
+
* This module spawns and manages `tail -f` processes for streaming live file
|
|
5
|
+
* content to the frontend. It handles:
|
|
6
|
+
* - Spawning tail processes with initial history
|
|
7
|
+
* - Streaming output via callbacks
|
|
8
|
+
* - Cleanup when streams are closed
|
|
9
|
+
* - Security validation (path within working directory)
|
|
10
|
+
*
|
|
11
|
+
* @module file-stream-manager
|
|
12
|
+
*/
|
|
13
|
+
import { ChildProcess } from 'node:child_process';
|
|
14
|
+
import { EventEmitter } from 'node:events';
|
|
15
|
+
/**
|
|
16
|
+
* Represents an active file stream.
|
|
17
|
+
*/
|
|
18
|
+
export interface FileStream {
|
|
19
|
+
/** Unique stream identifier */
|
|
20
|
+
id: string;
|
|
21
|
+
/** Session this stream belongs to */
|
|
22
|
+
sessionId: string;
|
|
23
|
+
/** Absolute path to the file being streamed */
|
|
24
|
+
filePath: string;
|
|
25
|
+
/** Tail process handle */
|
|
26
|
+
process: ChildProcess;
|
|
27
|
+
/** Timestamp when stream was created */
|
|
28
|
+
createdAt: number;
|
|
29
|
+
/** Timestamp of last data received */
|
|
30
|
+
lastDataAt: number;
|
|
31
|
+
/** Whether the stream is still active */
|
|
32
|
+
active: boolean;
|
|
33
|
+
/** Callback for sending data to client */
|
|
34
|
+
onData: (data: string) => void;
|
|
35
|
+
/** Callback for stream end */
|
|
36
|
+
onEnd: () => void;
|
|
37
|
+
/** Callback for errors */
|
|
38
|
+
onError: (error: string) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Options for creating a file stream.
|
|
42
|
+
*/
|
|
43
|
+
export interface CreateStreamOptions {
|
|
44
|
+
/** Session ID requesting the stream */
|
|
45
|
+
sessionId: string;
|
|
46
|
+
/** Path to the file to stream */
|
|
47
|
+
filePath: string;
|
|
48
|
+
/** Working directory for path validation */
|
|
49
|
+
workingDir: string;
|
|
50
|
+
/** Number of historical lines to show (default: 50) */
|
|
51
|
+
lines?: number;
|
|
52
|
+
/** Callback for data */
|
|
53
|
+
onData: (data: string) => void;
|
|
54
|
+
/** Callback for stream end */
|
|
55
|
+
onEnd: () => void;
|
|
56
|
+
/** Callback for errors */
|
|
57
|
+
onError: (error: string) => void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Result of creating a stream.
|
|
61
|
+
*/
|
|
62
|
+
export interface CreateStreamResult {
|
|
63
|
+
success: boolean;
|
|
64
|
+
streamId?: string;
|
|
65
|
+
error?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Manages file streaming via tail -f processes.
|
|
69
|
+
* Ensures security by validating paths and limiting concurrent streams.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const manager = new FileStreamManager();
|
|
74
|
+
*
|
|
75
|
+
* const result = await manager.createStream({
|
|
76
|
+
* sessionId: 'session-123',
|
|
77
|
+
* filePath: '/var/log/app.log',
|
|
78
|
+
* workingDir: '/var/log',
|
|
79
|
+
* onData: (data) => sseClient.write(data),
|
|
80
|
+
* onEnd: () => sseClient.close(),
|
|
81
|
+
* onError: (err) => console.error(err),
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* // Later, to stop:
|
|
85
|
+
* manager.closeStream(result.streamId);
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare class FileStreamManager extends EventEmitter {
|
|
89
|
+
private streams;
|
|
90
|
+
private sessionStreamCounts;
|
|
91
|
+
private cleanupTimer;
|
|
92
|
+
constructor();
|
|
93
|
+
/**
|
|
94
|
+
* Create a new file stream.
|
|
95
|
+
*
|
|
96
|
+
* @param options - Stream configuration
|
|
97
|
+
* @returns Result with stream ID on success, error on failure
|
|
98
|
+
*/
|
|
99
|
+
createStream(options: CreateStreamOptions): Promise<CreateStreamResult>;
|
|
100
|
+
/**
|
|
101
|
+
* Close a file stream.
|
|
102
|
+
*
|
|
103
|
+
* @param streamId - ID of the stream to close
|
|
104
|
+
* @returns true if stream was closed, false if not found
|
|
105
|
+
*/
|
|
106
|
+
closeStream(streamId: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Close all streams for a session.
|
|
109
|
+
*
|
|
110
|
+
* @param sessionId - Session ID whose streams to close
|
|
111
|
+
* @returns Number of streams closed
|
|
112
|
+
*/
|
|
113
|
+
closeSessionStreams(sessionId: string): number;
|
|
114
|
+
/**
|
|
115
|
+
* Get all active streams for a session.
|
|
116
|
+
*
|
|
117
|
+
* @param sessionId - Session ID to query
|
|
118
|
+
* @returns Array of stream info
|
|
119
|
+
*/
|
|
120
|
+
getSessionStreams(sessionId: string): Array<{
|
|
121
|
+
id: string;
|
|
122
|
+
filePath: string;
|
|
123
|
+
createdAt: number;
|
|
124
|
+
}>;
|
|
125
|
+
/**
|
|
126
|
+
* Get count of active streams.
|
|
127
|
+
*/
|
|
128
|
+
get activeStreamCount(): number;
|
|
129
|
+
/**
|
|
130
|
+
* Clean up and destroy the manager.
|
|
131
|
+
*/
|
|
132
|
+
destroy(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Validate that a file path is safe to access.
|
|
135
|
+
* Must be within the working directory (no path traversal).
|
|
136
|
+
*/
|
|
137
|
+
private validatePath;
|
|
138
|
+
/**
|
|
139
|
+
* Remove a stream from tracking.
|
|
140
|
+
*/
|
|
141
|
+
private removeStream;
|
|
142
|
+
/**
|
|
143
|
+
* Clean up streams that have been inactive for too long.
|
|
144
|
+
*/
|
|
145
|
+
private cleanupInactiveStreams;
|
|
146
|
+
}
|
|
147
|
+
export declare const fileStreamManager: FileStreamManager;
|
|
148
|
+
//# sourceMappingURL=file-stream-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-stream-manager.d.ts","sourceRoot":"","sources":["../src/file-stream-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAS,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA4B3C;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,0BAA0B;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,0BAA0B;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,mBAAmB,CAAkC;IAC7D,OAAO,CAAC,YAAY,CAA+C;;IAUnE;;;;;OAKG;IACG,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuH7E;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAoCtC;;;;;OAKG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAW9C;;;;;OAKG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAchG;;OAEG;IACH,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;OAEG;IACH,OAAO,IAAI,IAAI;IAmBf;;;OAGG;IACH,OAAO,CAAC,YAAY;IAoDpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAcpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;CAS/B;AAGD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview File Stream Manager - Manages tail -f processes for live log viewing
|
|
3
|
+
*
|
|
4
|
+
* This module spawns and manages `tail -f` processes for streaming live file
|
|
5
|
+
* content to the frontend. It handles:
|
|
6
|
+
* - Spawning tail processes with initial history
|
|
7
|
+
* - Streaming output via callbacks
|
|
8
|
+
* - Cleanup when streams are closed
|
|
9
|
+
* - Security validation (path within working directory)
|
|
10
|
+
*
|
|
11
|
+
* @module file-stream-manager
|
|
12
|
+
*/
|
|
13
|
+
import { spawn } from 'node:child_process';
|
|
14
|
+
import { existsSync, statSync, realpathSync } from 'node:fs';
|
|
15
|
+
import { resolve, relative, isAbsolute } from 'node:path';
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
import { EventEmitter } from 'node:events';
|
|
18
|
+
// ========== Configuration Constants ==========
|
|
19
|
+
/**
|
|
20
|
+
* Default number of historical lines to show when opening a file.
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_TAIL_LINES = 50;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum file size to stream (100MB).
|
|
25
|
+
* Skip files larger than this to prevent memory issues.
|
|
26
|
+
*/
|
|
27
|
+
const MAX_FILE_SIZE = 100 * 1024 * 1024;
|
|
28
|
+
/**
|
|
29
|
+
* Maximum concurrent streams per session.
|
|
30
|
+
*/
|
|
31
|
+
const MAX_STREAMS_PER_SESSION = 5;
|
|
32
|
+
/**
|
|
33
|
+
* Inactivity timeout for streams (5 minutes).
|
|
34
|
+
* Streams with no data for this long will be auto-closed.
|
|
35
|
+
*/
|
|
36
|
+
const STREAM_INACTIVITY_TIMEOUT_MS = 5 * 60 * 1000;
|
|
37
|
+
// ========== FileStreamManager Class ==========
|
|
38
|
+
/**
|
|
39
|
+
* Manages file streaming via tail -f processes.
|
|
40
|
+
* Ensures security by validating paths and limiting concurrent streams.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const manager = new FileStreamManager();
|
|
45
|
+
*
|
|
46
|
+
* const result = await manager.createStream({
|
|
47
|
+
* sessionId: 'session-123',
|
|
48
|
+
* filePath: '/var/log/app.log',
|
|
49
|
+
* workingDir: '/var/log',
|
|
50
|
+
* onData: (data) => sseClient.write(data),
|
|
51
|
+
* onEnd: () => sseClient.close(),
|
|
52
|
+
* onError: (err) => console.error(err),
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* // Later, to stop:
|
|
56
|
+
* manager.closeStream(result.streamId);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export class FileStreamManager extends EventEmitter {
|
|
60
|
+
streams = new Map();
|
|
61
|
+
sessionStreamCounts = new Map();
|
|
62
|
+
cleanupTimer = null;
|
|
63
|
+
constructor() {
|
|
64
|
+
super();
|
|
65
|
+
// Start cleanup timer for inactive streams
|
|
66
|
+
this.cleanupTimer = setInterval(() => this.cleanupInactiveStreams(), 60 * 1000);
|
|
67
|
+
}
|
|
68
|
+
// ========== Public Methods ==========
|
|
69
|
+
/**
|
|
70
|
+
* Create a new file stream.
|
|
71
|
+
*
|
|
72
|
+
* @param options - Stream configuration
|
|
73
|
+
* @returns Result with stream ID on success, error on failure
|
|
74
|
+
*/
|
|
75
|
+
async createStream(options) {
|
|
76
|
+
const { sessionId, filePath, workingDir, lines = DEFAULT_TAIL_LINES, onData, onEnd, onError } = options;
|
|
77
|
+
// Check concurrent stream limit for this session
|
|
78
|
+
const currentCount = this.sessionStreamCounts.get(sessionId) || 0;
|
|
79
|
+
if (currentCount >= MAX_STREAMS_PER_SESSION) {
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
error: `Maximum ${MAX_STREAMS_PER_SESSION} concurrent streams per session`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Resolve and validate path
|
|
86
|
+
const validationResult = this.validatePath(filePath, workingDir);
|
|
87
|
+
if (!validationResult.valid) {
|
|
88
|
+
return { success: false, error: validationResult.error };
|
|
89
|
+
}
|
|
90
|
+
let absolutePath = validationResult.absolutePath;
|
|
91
|
+
// Check file exists and size
|
|
92
|
+
try {
|
|
93
|
+
const stats = statSync(absolutePath);
|
|
94
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
95
|
+
return {
|
|
96
|
+
success: false,
|
|
97
|
+
error: `File too large (${Math.round(stats.size / 1024 / 1024)}MB > ${MAX_FILE_SIZE / 1024 / 1024}MB limit)`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
const errorCode = err instanceof Error && 'code' in err ? err.code : 'UNKNOWN';
|
|
103
|
+
console.warn(`[FileStreamManager] Failed to stat file "${absolutePath}" (${errorCode}):`, err instanceof Error ? err.message : String(err));
|
|
104
|
+
return { success: false, error: 'File not found or not accessible' };
|
|
105
|
+
}
|
|
106
|
+
// Re-resolve symlinks right before spawn to minimize TOCTOU window.
|
|
107
|
+
// A symlink could have been swapped between validatePath() and here.
|
|
108
|
+
try {
|
|
109
|
+
const resolvedPath = realpathSync(absolutePath);
|
|
110
|
+
if (resolvedPath !== absolutePath) {
|
|
111
|
+
// Symlink target changed — re-validate against allowed paths
|
|
112
|
+
const recheck = this.validatePath(resolvedPath, workingDir);
|
|
113
|
+
if (!recheck.valid) {
|
|
114
|
+
return { success: false, error: recheck.error };
|
|
115
|
+
}
|
|
116
|
+
absolutePath = resolvedPath;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return { success: false, error: 'File not found or not accessible' };
|
|
121
|
+
}
|
|
122
|
+
// Generate stream ID
|
|
123
|
+
const streamId = `${sessionId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
124
|
+
// Spawn tail process
|
|
125
|
+
const tailProcess = spawn('tail', ['-f', '-n', String(lines), absolutePath], {
|
|
126
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
127
|
+
});
|
|
128
|
+
if (!tailProcess.pid) {
|
|
129
|
+
return { success: false, error: 'Failed to spawn tail process' };
|
|
130
|
+
}
|
|
131
|
+
const stream = {
|
|
132
|
+
id: streamId,
|
|
133
|
+
sessionId,
|
|
134
|
+
filePath: absolutePath,
|
|
135
|
+
process: tailProcess,
|
|
136
|
+
createdAt: Date.now(),
|
|
137
|
+
lastDataAt: Date.now(),
|
|
138
|
+
active: true,
|
|
139
|
+
onData,
|
|
140
|
+
onEnd,
|
|
141
|
+
onError,
|
|
142
|
+
};
|
|
143
|
+
// Handle stdout
|
|
144
|
+
tailProcess.stdout?.on('data', (data) => {
|
|
145
|
+
if (stream.active) {
|
|
146
|
+
stream.lastDataAt = Date.now();
|
|
147
|
+
onData(data.toString());
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
// Handle stderr
|
|
151
|
+
tailProcess.stderr?.on('data', (data) => {
|
|
152
|
+
if (stream.active) {
|
|
153
|
+
onError(data.toString());
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
// Handle process exit
|
|
157
|
+
tailProcess.on('exit', (_code) => {
|
|
158
|
+
if (stream.active) {
|
|
159
|
+
stream.active = false;
|
|
160
|
+
onEnd();
|
|
161
|
+
this.removeStream(streamId);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
// Handle errors
|
|
165
|
+
tailProcess.on('error', (err) => {
|
|
166
|
+
if (stream.active) {
|
|
167
|
+
stream.active = false;
|
|
168
|
+
onError(err.message);
|
|
169
|
+
this.removeStream(streamId);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
// Store stream
|
|
173
|
+
this.streams.set(streamId, stream);
|
|
174
|
+
this.sessionStreamCounts.set(sessionId, currentCount + 1);
|
|
175
|
+
return { success: true, streamId };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Close a file stream.
|
|
179
|
+
*
|
|
180
|
+
* @param streamId - ID of the stream to close
|
|
181
|
+
* @returns true if stream was closed, false if not found
|
|
182
|
+
*/
|
|
183
|
+
closeStream(streamId) {
|
|
184
|
+
const stream = this.streams.get(streamId);
|
|
185
|
+
if (!stream)
|
|
186
|
+
return false;
|
|
187
|
+
stream.active = false;
|
|
188
|
+
// Remove all event listeners to prevent memory leaks (closures hold references)
|
|
189
|
+
stream.process.stdout?.removeAllListeners();
|
|
190
|
+
stream.process.stderr?.removeAllListeners();
|
|
191
|
+
stream.process.removeAllListeners();
|
|
192
|
+
// Kill the tail process
|
|
193
|
+
try {
|
|
194
|
+
stream.process.kill('SIGTERM');
|
|
195
|
+
// Force kill after 1 second if still running
|
|
196
|
+
const forceKillTimer = setTimeout(() => {
|
|
197
|
+
try {
|
|
198
|
+
stream.process.kill('SIGKILL');
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// Already dead
|
|
202
|
+
}
|
|
203
|
+
}, 1000);
|
|
204
|
+
// Clear the force kill timer if process exits naturally
|
|
205
|
+
stream.process.once('exit', () => {
|
|
206
|
+
clearTimeout(forceKillTimer);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Process may have already exited
|
|
211
|
+
}
|
|
212
|
+
stream.onEnd();
|
|
213
|
+
this.removeStream(streamId);
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Close all streams for a session.
|
|
218
|
+
*
|
|
219
|
+
* @param sessionId - Session ID whose streams to close
|
|
220
|
+
* @returns Number of streams closed
|
|
221
|
+
*/
|
|
222
|
+
closeSessionStreams(sessionId) {
|
|
223
|
+
let closed = 0;
|
|
224
|
+
for (const [streamId, stream] of this.streams) {
|
|
225
|
+
if (stream.sessionId === sessionId) {
|
|
226
|
+
this.closeStream(streamId);
|
|
227
|
+
closed++;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return closed;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Get all active streams for a session.
|
|
234
|
+
*
|
|
235
|
+
* @param sessionId - Session ID to query
|
|
236
|
+
* @returns Array of stream info
|
|
237
|
+
*/
|
|
238
|
+
getSessionStreams(sessionId) {
|
|
239
|
+
const result = [];
|
|
240
|
+
for (const [, stream] of this.streams) {
|
|
241
|
+
if (stream.sessionId === sessionId && stream.active) {
|
|
242
|
+
result.push({
|
|
243
|
+
id: stream.id,
|
|
244
|
+
filePath: stream.filePath,
|
|
245
|
+
createdAt: stream.createdAt,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Get count of active streams.
|
|
253
|
+
*/
|
|
254
|
+
get activeStreamCount() {
|
|
255
|
+
return this.streams.size;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Clean up and destroy the manager.
|
|
259
|
+
*/
|
|
260
|
+
destroy() {
|
|
261
|
+
// Stop cleanup timer
|
|
262
|
+
if (this.cleanupTimer) {
|
|
263
|
+
clearInterval(this.cleanupTimer);
|
|
264
|
+
this.cleanupTimer = null;
|
|
265
|
+
}
|
|
266
|
+
// Close all streams
|
|
267
|
+
for (const streamId of this.streams.keys()) {
|
|
268
|
+
this.closeStream(streamId);
|
|
269
|
+
}
|
|
270
|
+
// Clear Maps to release references
|
|
271
|
+
this.streams.clear();
|
|
272
|
+
this.sessionStreamCounts.clear();
|
|
273
|
+
}
|
|
274
|
+
// ========== Private Methods ==========
|
|
275
|
+
/**
|
|
276
|
+
* Validate that a file path is safe to access.
|
|
277
|
+
* Must be within the working directory (no path traversal).
|
|
278
|
+
*/
|
|
279
|
+
validatePath(filePath, workingDir) {
|
|
280
|
+
// Expand ~ to home directory
|
|
281
|
+
let expandedPath = filePath;
|
|
282
|
+
if (expandedPath.startsWith('~')) {
|
|
283
|
+
expandedPath = expandedPath.replace(/^~/, homedir());
|
|
284
|
+
}
|
|
285
|
+
// Resolve to absolute path
|
|
286
|
+
let absolutePath = isAbsolute(expandedPath) ? resolve(expandedPath) : resolve(workingDir, expandedPath);
|
|
287
|
+
// Resolve symlinks to prevent symlink attacks — validate the real target,
|
|
288
|
+
// not the symlink itself. Fall back to resolved path if file doesn't exist yet.
|
|
289
|
+
try {
|
|
290
|
+
absolutePath = realpathSync(absolutePath);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// File may not exist yet (tail -f can wait); keep the resolved path
|
|
294
|
+
// which will be caught by the existsSync check below
|
|
295
|
+
}
|
|
296
|
+
// Normalize the working directory
|
|
297
|
+
const normalizedWorkingDir = resolve(workingDir);
|
|
298
|
+
// Check if the resolved path is within the working directory
|
|
299
|
+
// or common log directories (/tmp intentionally excluded — world-writable)
|
|
300
|
+
const allowedPaths = [normalizedWorkingDir, '/var/log', resolve(homedir(), 'logs')];
|
|
301
|
+
const isAllowed = allowedPaths.some((allowed) => {
|
|
302
|
+
const rel = relative(allowed, absolutePath);
|
|
303
|
+
return rel && !rel.startsWith('..') && !isAbsolute(rel);
|
|
304
|
+
});
|
|
305
|
+
if (!isAllowed) {
|
|
306
|
+
return {
|
|
307
|
+
valid: false,
|
|
308
|
+
error: `Path must be within working directory or allowed log directories`,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
// Note: No need to check for '..' — resolve() already normalizes the path,
|
|
312
|
+
// and realpathSync() resolves symlinks. Both eliminate traversal sequences.
|
|
313
|
+
// Check file exists
|
|
314
|
+
if (!existsSync(absolutePath)) {
|
|
315
|
+
return { valid: false, error: 'File does not exist' };
|
|
316
|
+
}
|
|
317
|
+
return { valid: true, absolutePath };
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Remove a stream from tracking.
|
|
321
|
+
*/
|
|
322
|
+
removeStream(streamId) {
|
|
323
|
+
const stream = this.streams.get(streamId);
|
|
324
|
+
if (stream) {
|
|
325
|
+
// Decrement session count
|
|
326
|
+
const count = this.sessionStreamCounts.get(stream.sessionId) || 0;
|
|
327
|
+
if (count <= 1) {
|
|
328
|
+
this.sessionStreamCounts.delete(stream.sessionId);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
this.sessionStreamCounts.set(stream.sessionId, count - 1);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
this.streams.delete(streamId);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Clean up streams that have been inactive for too long.
|
|
338
|
+
*/
|
|
339
|
+
cleanupInactiveStreams() {
|
|
340
|
+
const now = Date.now();
|
|
341
|
+
for (const [streamId, stream] of this.streams) {
|
|
342
|
+
if (now - stream.lastDataAt > STREAM_INACTIVITY_TIMEOUT_MS) {
|
|
343
|
+
console.log(`[FileStreamManager] Closing inactive stream: ${streamId}`);
|
|
344
|
+
this.closeStream(streamId);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Export singleton instance
|
|
350
|
+
export const fileStreamManager = new FileStreamManager();
|
|
351
|
+
//# sourceMappingURL=file-stream-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-stream-manager.js","sourceRoot":"","sources":["../src/file-stream-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAgB,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,gDAAgD;AAEhD;;GAEG;AACH,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B;;;GAGG;AACH,MAAM,aAAa,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC;;GAEG;AACH,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAElC;;;GAGG;AACH,MAAM,4BAA4B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AA2DnD,gDAAgD;AAEhD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACzC,OAAO,GAA4B,IAAI,GAAG,EAAE,CAAC;IAC7C,mBAAmB,GAAwB,IAAI,GAAG,EAAE,CAAC;IACrD,YAAY,GAA0C,IAAI,CAAC;IAEnE;QACE,KAAK,EAAE,CAAC;QACR,2CAA2C;QAC3C,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAClF,CAAC;IAED,uCAAuC;IAEvC;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,OAA4B;QAC7C,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,GAAG,kBAAkB,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAExG,iDAAiD;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAClE,IAAI,YAAY,IAAI,uBAAuB,EAAE,CAAC;YAC5C,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,WAAW,uBAAuB,iCAAiC;aAC3E,CAAC;QACJ,CAAC;QAED,4BAA4B;QAC5B,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACjE,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;YAC5B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC3D,CAAC;QAED,IAAI,YAAY,GAAG,gBAAgB,CAAC,YAAa,CAAC;QAElD,6BAA6B;QAC7B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;YACrC,IAAI,KAAK,CAAC,IAAI,GAAG,aAAa,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,mBAAmB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,QAAQ,aAAa,GAAG,IAAI,GAAG,IAAI,WAAW;iBAC7G,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,GAAG,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,CAAE,GAA6B,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1G,OAAO,CAAC,IAAI,CACV,4CAA4C,YAAY,MAAM,SAAS,IAAI,EAC3E,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;QACvE,CAAC;QAED,oEAAoE;QACpE,qEAAqE;QACrE,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;YAChD,IAAI,YAAY,KAAK,YAAY,EAAE,CAAC;gBAClC,6DAA6D;gBAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;gBAC5D,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;oBACnB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClD,CAAC;gBACD,YAAY,GAAG,YAAY,CAAC;YAC9B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;QACvE,CAAC;QAED,qBAAqB;QACrB,MAAM,QAAQ,GAAG,GAAG,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAExF,qBAAqB;QACrB,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,EAAE;YAC3E,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;YACrB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC;QACnE,CAAC;QAED,MAAM,MAAM,GAAe;YACzB,EAAE,EAAE,QAAQ;YACZ,SAAS;YACT,QAAQ,EAAE,YAAY;YACtB,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;YACtB,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,KAAK;YACL,OAAO;SACR,CAAC;QAEF,gBAAgB;QAChB,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC9C,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,gBAAgB;QAChB,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC9C,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,sBAAsB;QACtB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;gBACtB,KAAK,EAAE,CAAC;gBACR,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,gBAAgB;QAChB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC9B,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACrB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,eAAe;QACf,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;QAE1D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,QAAgB;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAE1B,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;QAEtB,gFAAgF;QAChF,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAEpC,wBAAwB;QACxB,IAAI,CAAC;YACH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC/B,6CAA6C;YAC7C,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;gBACrC,IAAI,CAAC;oBACH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACjC,CAAC;gBAAC,MAAM,CAAC;oBACP,eAAe;gBACjB,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,wDAAwD;YACxD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC/B,YAAY,CAAC,cAAc,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,SAAiB;QACnC,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC9C,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACnC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;gBAC3B,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,SAAiB;QACjC,MAAM,MAAM,GAA+D,EAAE,CAAC;QAC9E,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACpD,MAAM,CAAC,IAAI,CAAC;oBACV,EAAE,EAAE,MAAM,CAAC,EAAE;oBACb,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,SAAS,EAAE,MAAM,CAAC,SAAS;iBAC5B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,OAAO;QACL,qBAAqB;QACrB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QAED,oBAAoB;QACpB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;IACnC,CAAC;IAED,wCAAwC;IAExC;;;OAGG;IACK,YAAY,CAClB,QAAgB,EAChB,UAAkB;QAElB,6BAA6B;QAC7B,IAAI,YAAY,GAAG,QAAQ,CAAC;QAC5B,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;QAED,2BAA2B;QAC3B,IAAI,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAExG,0EAA0E;QAC1E,gFAAgF;QAChF,IAAI,CAAC;YACH,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;YACpE,qDAAqD;QACvD,CAAC;QAED,kCAAkC;QAClC,MAAM,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAEjD,6DAA6D;QAC7D,2EAA2E;QAC3E,MAAM,YAAY,GAAG,CAAC,oBAAoB,EAAE,UAAU,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QAEpF,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAC5C,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,kEAAkE;aAC1E,CAAC;QACJ,CAAC;QAED,2EAA2E;QAC3E,4EAA4E;QAE5E,oBAAoB;QACpB,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QACxD,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,QAAgB;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,MAAM,EAAE,CAAC;YACX,0BAA0B;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAClE,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACf,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,sBAAsB;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC9C,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,GAAG,4BAA4B,EAAE,CAAC;gBAC3D,OAAO,CAAC,GAAG,CAAC,gDAAgD,QAAQ,EAAE,CAAC,CAAC;gBACxE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,4BAA4B;AAC5B,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Claude Code hooks configuration generator
|
|
3
|
+
*
|
|
4
|
+
* Generates .claude/settings.local.json with hook definitions that POST
|
|
5
|
+
* to Codeman's /api/hook-event endpoint when Claude Code fires
|
|
6
|
+
* notification or stop hooks. Uses $CODEMAN_API_URL and
|
|
7
|
+
* $CODEMAN_SESSION_ID env vars (set on every managed session) so the
|
|
8
|
+
* config is static per case directory.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Generates the hooks section for .claude/settings.local.json
|
|
12
|
+
*
|
|
13
|
+
* The hook commands read stdin JSON from Claude Code (contains tool_name,
|
|
14
|
+
* tool_input, etc.) and forward it as the `data` field to Codeman's API.
|
|
15
|
+
* Env vars are resolved at runtime by the shell, so the config is static
|
|
16
|
+
* per case directory.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateHooksConfig(): {
|
|
19
|
+
hooks: Record<string, unknown[]>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Updates env vars in .claude/settings.local.json for the given case path.
|
|
23
|
+
* Merges with existing env field; removes vars set to empty string.
|
|
24
|
+
*/
|
|
25
|
+
export declare function updateCaseEnvVars(casePath: string, envVars: Record<string, string>): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Writes hooks config to .claude/settings.local.json in the given case path.
|
|
28
|
+
* Merges with existing file content, only touching the `hooks` key.
|
|
29
|
+
*/
|
|
30
|
+
export declare function writeHooksConfig(casePath: string): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=hooks-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-config.d.ts","sourceRoot":"","sources":["../src/hooks-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CA4C1E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BxG;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBtE"}
|