@two7722/sentinel-guard 1.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 (88) hide show
  1. package/dist/__tests__/rules-engine.test.d.ts +1 -0
  2. package/dist/__tests__/rules-engine.test.js +69 -0
  3. package/dist/__tests__/rules-engine.test.js.map +1 -0
  4. package/dist/__tests__/transport-encryption.test.d.ts +1 -0
  5. package/dist/__tests__/transport-encryption.test.js +95 -0
  6. package/dist/__tests__/transport-encryption.test.js.map +1 -0
  7. package/dist/api/client.d.ts +27 -0
  8. package/dist/api/client.js +91 -0
  9. package/dist/api/client.js.map +1 -0
  10. package/dist/cli/bootstrap.d.ts +12 -0
  11. package/dist/cli/bootstrap.js +132 -0
  12. package/dist/cli/bootstrap.js.map +1 -0
  13. package/dist/cli/index.d.ts +2 -0
  14. package/dist/cli/index.js +534 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/crypto/keys.d.ts +40 -0
  17. package/dist/crypto/keys.js +125 -0
  18. package/dist/crypto/keys.js.map +1 -0
  19. package/dist/crypto/transport-encryption.d.ts +13 -0
  20. package/dist/crypto/transport-encryption.js +62 -0
  21. package/dist/crypto/transport-encryption.js.map +1 -0
  22. package/dist/install/setup.d.ts +2 -0
  23. package/dist/install/setup.js +80 -0
  24. package/dist/install/setup.js.map +1 -0
  25. package/dist/lib/budget.d.ts +14 -0
  26. package/dist/lib/budget.js +93 -0
  27. package/dist/lib/budget.js.map +1 -0
  28. package/dist/lib/claude-process.d.ts +16 -0
  29. package/dist/lib/claude-process.js +98 -0
  30. package/dist/lib/claude-process.js.map +1 -0
  31. package/dist/lib/daemon.d.ts +6 -0
  32. package/dist/lib/daemon.js +218 -0
  33. package/dist/lib/daemon.js.map +1 -0
  34. package/dist/lib/diff.d.ts +5 -0
  35. package/dist/lib/diff.js +85 -0
  36. package/dist/lib/diff.js.map +1 -0
  37. package/dist/lib/doctor.d.ts +1 -0
  38. package/dist/lib/doctor.js +108 -0
  39. package/dist/lib/doctor.js.map +1 -0
  40. package/dist/lib/history.d.ts +22 -0
  41. package/dist/lib/history.js +62 -0
  42. package/dist/lib/history.js.map +1 -0
  43. package/dist/lib/logger.d.ts +11 -0
  44. package/dist/lib/logger.js +62 -0
  45. package/dist/lib/logger.js.map +1 -0
  46. package/dist/lib/modes.d.ts +22 -0
  47. package/dist/lib/modes.js +58 -0
  48. package/dist/lib/modes.js.map +1 -0
  49. package/dist/lib/overrides.d.ts +13 -0
  50. package/dist/lib/overrides.js +74 -0
  51. package/dist/lib/overrides.js.map +1 -0
  52. package/dist/lib/session.d.ts +32 -0
  53. package/dist/lib/session.js +68 -0
  54. package/dist/lib/session.js.map +1 -0
  55. package/dist/lib/summarizer.d.ts +5 -0
  56. package/dist/lib/summarizer.js +46 -0
  57. package/dist/lib/summarizer.js.map +1 -0
  58. package/dist/lib/tunnel.d.ts +2 -0
  59. package/dist/lib/tunnel.js +48 -0
  60. package/dist/lib/tunnel.js.map +1 -0
  61. package/dist/relay/pending.d.ts +27 -0
  62. package/dist/relay/pending.js +65 -0
  63. package/dist/relay/pending.js.map +1 -0
  64. package/dist/rules/engine.d.ts +31 -0
  65. package/dist/rules/engine.js +203 -0
  66. package/dist/rules/engine.js.map +1 -0
  67. package/dist/server/http.d.ts +8 -0
  68. package/dist/server/http.js +359 -0
  69. package/dist/server/http.js.map +1 -0
  70. package/dist/socket/client.d.ts +16 -0
  71. package/dist/socket/client.js +81 -0
  72. package/dist/socket/client.js.map +1 -0
  73. package/dist/transport/cloudkit.d.ts +30 -0
  74. package/dist/transport/cloudkit.js +162 -0
  75. package/dist/transport/cloudkit.js.map +1 -0
  76. package/dist/transport/factory.d.ts +6 -0
  77. package/dist/transport/factory.js +20 -0
  78. package/dist/transport/factory.js.map +1 -0
  79. package/dist/transport/interface.d.ts +25 -0
  80. package/dist/transport/interface.js +13 -0
  81. package/dist/transport/interface.js.map +1 -0
  82. package/dist/transport/local.d.ts +46 -0
  83. package/dist/transport/local.js +320 -0
  84. package/dist/transport/local.js.map +1 -0
  85. package/dist/transport/remote.d.ts +17 -0
  86. package/dist/transport/remote.js +83 -0
  87. package/dist/transport/remote.js.map +1 -0
  88. package/package.json +44 -0
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRules = getRules;
4
+ exports.setCustomRules = setCustomRules;
5
+ exports.watchRules = watchRules;
6
+ exports.matchRules = matchRules;
7
+ exports.riskToLevel = riskToLevel;
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ const keys_1 = require("../crypto/keys");
11
+ const logger_1 = require("../lib/logger");
12
+ // ==================== Default Rules ====================
13
+ const DEFAULT_RULES = [
14
+ {
15
+ id: 'builtin-bash-high',
16
+ toolPattern: 'Bash',
17
+ pathPattern: null,
18
+ risk: 'require_faceid',
19
+ priority: 10,
20
+ description: 'Bash commands require Face ID',
21
+ },
22
+ {
23
+ id: 'builtin-write-confirm',
24
+ toolPattern: 'Write',
25
+ pathPattern: null,
26
+ risk: 'require_confirm',
27
+ priority: 20,
28
+ description: 'File writes require confirmation',
29
+ },
30
+ {
31
+ id: 'builtin-edit-confirm',
32
+ toolPattern: 'Edit',
33
+ pathPattern: null,
34
+ risk: 'require_confirm',
35
+ priority: 20,
36
+ description: 'File edits require confirmation',
37
+ },
38
+ {
39
+ id: 'builtin-tmp-allow',
40
+ toolPattern: '*',
41
+ pathPattern: '/tmp/**',
42
+ risk: 'auto_allow',
43
+ priority: 5,
44
+ description: 'Auto-allow /tmp operations',
45
+ },
46
+ {
47
+ id: 'builtin-env-faceid',
48
+ toolPattern: '*',
49
+ pathPattern: '**/.env*',
50
+ risk: 'require_faceid',
51
+ priority: 1,
52
+ description: '.env files require Face ID',
53
+ },
54
+ {
55
+ id: 'builtin-read-allow',
56
+ toolPattern: 'Read',
57
+ pathPattern: null,
58
+ risk: 'auto_allow',
59
+ priority: 50,
60
+ description: 'Auto-allow file reads',
61
+ },
62
+ {
63
+ id: 'builtin-glob-allow',
64
+ toolPattern: 'Glob',
65
+ pathPattern: null,
66
+ risk: 'auto_allow',
67
+ priority: 50,
68
+ description: 'Auto-allow glob searches',
69
+ },
70
+ {
71
+ id: 'builtin-grep-allow',
72
+ toolPattern: 'Grep',
73
+ pathPattern: null,
74
+ risk: 'auto_allow',
75
+ priority: 50,
76
+ description: 'Auto-allow grep searches',
77
+ },
78
+ ];
79
+ // ==================== Rules File ====================
80
+ const RULES_PATH = (0, path_1.join)((0, keys_1.getSentinelDir)(), 'rules.json');
81
+ let cachedRules = null;
82
+ let cacheLoading = false;
83
+ function loadRules() {
84
+ if (cachedRules)
85
+ return cachedRules;
86
+ // Prevent concurrent loads from overwriting each other
87
+ if (cacheLoading)
88
+ return DEFAULT_RULES;
89
+ cacheLoading = true;
90
+ try {
91
+ if (!(0, fs_1.existsSync)(RULES_PATH)) {
92
+ (0, fs_1.writeFileSync)(RULES_PATH, JSON.stringify(DEFAULT_RULES, null, 2), { mode: 0o600 });
93
+ cachedRules = DEFAULT_RULES;
94
+ return DEFAULT_RULES;
95
+ }
96
+ cachedRules = JSON.parse((0, fs_1.readFileSync)(RULES_PATH, 'utf-8'));
97
+ return cachedRules;
98
+ }
99
+ catch {
100
+ cachedRules = DEFAULT_RULES;
101
+ return DEFAULT_RULES;
102
+ }
103
+ finally {
104
+ cacheLoading = false;
105
+ }
106
+ }
107
+ function getRules() {
108
+ return loadRules();
109
+ }
110
+ // ==================== Custom Rules (from iOS) ====================
111
+ let iosCustomRules = [];
112
+ /** Set custom rules received from iOS (merged with file rules) */
113
+ function setCustomRules(rules) {
114
+ iosCustomRules = rules.map((r, i) => ({
115
+ ...r,
116
+ id: r.id ?? `ios-custom-${i}`,
117
+ priority: r.priority ?? 0,
118
+ risk: (r.risk ?? 'require_confirm'),
119
+ description: r.description ?? '',
120
+ }));
121
+ cachedRules = null; // invalidate cache to merge on next load
122
+ logger_1.log.info(`Custom rules from iOS: ${iosCustomRules.length}`);
123
+ }
124
+ /** Watch rules.json for changes and auto-reload */
125
+ function watchRules() {
126
+ // Ensure file exists first
127
+ loadRules();
128
+ try {
129
+ let debounce = null;
130
+ (0, fs_1.watch)(RULES_PATH, () => {
131
+ if (debounce)
132
+ clearTimeout(debounce);
133
+ debounce = setTimeout(() => {
134
+ cachedRules = null; // invalidate cache
135
+ const rules = loadRules();
136
+ logger_1.log.info(`Rules reloaded (${rules.length} rules)`);
137
+ }, 300);
138
+ });
139
+ logger_1.log.debug(`Watching ${RULES_PATH} for changes`);
140
+ }
141
+ catch {
142
+ logger_1.log.debug('Could not watch rules file');
143
+ }
144
+ }
145
+ // ==================== Glob Matching ====================
146
+ /**
147
+ * 简单 glob 匹配,支持 * 和 **
148
+ */
149
+ function globMatch(pattern, value) {
150
+ // Escape regex special chars, then convert glob patterns
151
+ const regex = pattern
152
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
153
+ .replace(/\*\*/g, '{{DOUBLESTAR}}')
154
+ .replace(/\*/g, '[^/]*')
155
+ .replace(/{{DOUBLESTAR}}/g, '.*');
156
+ return new RegExp(`^${regex}$`).test(value);
157
+ }
158
+ // ==================== Engine ====================
159
+ /**
160
+ * 匹配工具调用 against 规则列表
161
+ *
162
+ * @param toolName - 工具名,e.g. "Bash", "Write", "Edit"
163
+ * @param filePath - 文件路径(可选),e.g. "/tmp/foo.txt"
164
+ * @returns - 匹配结果:{ matched, rule, action }
165
+ */
166
+ function matchRules(toolName, filePath) {
167
+ // Merge: iOS custom rules (priority 0) + file rules, sorted by priority
168
+ const rules = [...iosCustomRules, ...loadRules()].sort((a, b) => a.priority - b.priority);
169
+ for (const rule of rules) {
170
+ let toolMatch = true;
171
+ let pathMatch = true;
172
+ // Tool pattern
173
+ if (rule.toolPattern) {
174
+ toolMatch = globMatch(rule.toolPattern, toolName);
175
+ }
176
+ // Path pattern — 只有当规则有 pathPattern 且调用有 filePath 时才匹配
177
+ if (rule.pathPattern) {
178
+ if (!filePath) {
179
+ pathMatch = false; // 规则要求路径但调用没有路径
180
+ }
181
+ else {
182
+ pathMatch = globMatch(rule.pathPattern, filePath);
183
+ }
184
+ }
185
+ if (toolMatch && pathMatch) {
186
+ logger_1.log.debug(`Rule matched: [${rule.id}] ${rule.description} → ${rule.risk}`);
187
+ return { matched: true, rule, action: rule.risk };
188
+ }
189
+ }
190
+ // 无匹配 → 默认需要确认
191
+ return { matched: false, rule: null, action: 'require_confirm' };
192
+ }
193
+ /**
194
+ * 将工具调用的风险等级映射为 server riskLevel
195
+ */
196
+ function riskToLevel(action) {
197
+ switch (action) {
198
+ case 'auto_allow': return 'low';
199
+ case 'require_confirm': return 'medium';
200
+ case 'require_faceid': return 'high';
201
+ }
202
+ }
203
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/rules/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import express from 'express';
2
+ export declare function pushEvent(data: Record<string, unknown>): void;
3
+ /** Send a terminal line to iOS via transport */
4
+ export declare function sendTerminalLine(text: string): void;
5
+ export declare function createHttpServer(port?: number): express.Application;
6
+ export declare function startHttpServer(port?: number): Promise<void>;
7
+ /** Setup user message handler from LocalTransport */
8
+ export declare function setupUserMessageHandler(): void;
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.pushEvent = pushEvent;
7
+ exports.sendTerminalLine = sendTerminalLine;
8
+ exports.createHttpServer = createHttpServer;
9
+ exports.startHttpServer = startHttpServer;
10
+ exports.setupUserMessageHandler = setupUserMessageHandler;
11
+ const express_1 = __importDefault(require("express"));
12
+ const zod_1 = require("zod");
13
+ const crypto_1 = require("crypto");
14
+ const child_process_1 = require("child_process");
15
+ const fs_1 = require("fs");
16
+ const path_1 = require("path");
17
+ const engine_1 = require("../rules/engine");
18
+ const interface_1 = require("../transport/interface");
19
+ const pending_1 = require("../relay/pending");
20
+ const history_1 = require("../lib/history");
21
+ const overrides_1 = require("../lib/overrides");
22
+ const budget_1 = require("../lib/budget");
23
+ const summarizer_1 = require("../lib/summarizer");
24
+ const modes_1 = require("../lib/modes");
25
+ const session_1 = require("../lib/session");
26
+ const diff_1 = require("../lib/diff");
27
+ const keys_1 = require("../crypto/keys");
28
+ const logger_1 = require("../lib/logger");
29
+ const unicode_animations_1 = __importDefault(require("unicode-animations"));
30
+ const claude_process_1 = require("../lib/claude-process");
31
+ /** Show an animated spinner for `durationMs`, then clear the line. */
32
+ function showSpinner(name, prefix, durationMs) {
33
+ const { frames, interval } = unicode_animations_1.default[name];
34
+ let i = 0;
35
+ const id = setInterval(() => {
36
+ process.stdout.write(`\r\x1B[2K ${frames[i++ % frames.length]} ${prefix}`);
37
+ }, interval);
38
+ setTimeout(() => {
39
+ clearInterval(id);
40
+ process.stdout.write('\r\x1B[2K');
41
+ }, durationMs);
42
+ }
43
+ const HookPayloadSchema = zod_1.z.object({
44
+ tool_name: zod_1.z.string(),
45
+ tool_input: zod_1.z.record(zod_1.z.unknown()),
46
+ });
47
+ const PENDING_MSG_PATH = (0, path_1.join)((0, keys_1.getSentinelDir)(), 'pending_message.txt');
48
+ // SSE access token — generated at startup, required for /events and /terminal
49
+ const SSE_TOKEN = (0, crypto_1.randomBytes)(16).toString('hex');
50
+ // SSE clients
51
+ const sseClients = new Set();
52
+ function pushEvent(data) {
53
+ const msg = `data: ${JSON.stringify(data)}\n\n`;
54
+ for (const client of sseClients) {
55
+ client.write(msg);
56
+ }
57
+ }
58
+ /** Send a terminal line to iOS via transport */
59
+ function sendTerminalLine(text) {
60
+ const transport = (0, interface_1.getTransport)();
61
+ if (transport?.isConnected) {
62
+ transport.sendEvent?.({ type: 'terminal', text });
63
+ }
64
+ const msg = `data: ${JSON.stringify({ text, time: Date.now() })}\n\n`;
65
+ for (const client of terminalClients) {
66
+ client.write(msg);
67
+ }
68
+ }
69
+ const terminalClients = new Set();
70
+ function sendActivity(type, data) {
71
+ const transport = (0, interface_1.getTransport)();
72
+ logger_1.log.debug(`sendActivity: transport=${transport?.mode ?? 'null'} connected=${transport?.isConnected} hasSendEvent=${!!transport?.sendEvent}`);
73
+ if (transport?.isConnected) {
74
+ transport.sendEvent?.({ type, ...data, timestamp: new Date().toISOString() });
75
+ }
76
+ }
77
+ function createHttpServer(port = 7749) {
78
+ const app = (0, express_1.default)();
79
+ app.use(express_1.default.json({ limit: '512kb' }));
80
+ // ==================== PreToolUse hook ====================
81
+ app.post('/hook', async (req, res) => {
82
+ const parsed = HookPayloadSchema.safeParse(req.body);
83
+ if (!parsed.success) {
84
+ logger_1.log.warn(`Invalid hook payload: ${parsed.error.message}`);
85
+ return res.status(400).json({ error: 'Invalid payload' });
86
+ }
87
+ const { tool_name, tool_input } = parsed.data;
88
+ const filePath = (tool_input.file_path ?? tool_input.path ?? null);
89
+ const requestId = (0, crypto_1.randomBytes)(8).toString('hex');
90
+ const ts = new Date().toISOString();
91
+ logger_1.log.info(`Hook: ${tool_name}${filePath ? ` → ${filePath}` : ''}`);
92
+ // Auto-start session on first hook
93
+ if (!(0, session_1.getCurrentSession)())
94
+ (0, session_1.startSession)();
95
+ // 0. Check overrides
96
+ const overrides = (0, overrides_1.getOverrideState)();
97
+ if (overrides.blockAll) {
98
+ logger_1.log.warn(`BLOCKED (override): ${tool_name}`);
99
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: 'override', decision: 'blocked', timestamp: ts });
100
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: 'blocked', reason: 'override' });
101
+ return res.json({ decision: 'block', reason: 'blocked by sentinel block' });
102
+ }
103
+ if (overrides.allowAll) {
104
+ logger_1.log.success(`ALLOWED (override): ${tool_name}`);
105
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: 'override', decision: 'allowed', timestamp: ts });
106
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: 'allowed', reason: 'override' });
107
+ return res.json({ decision: 'allow' });
108
+ }
109
+ if ((0, budget_1.isOverBudget)())
110
+ logger_1.log.warn('⚠ Over daily budget!');
111
+ // 0.6 Permission mode check
112
+ const modeResult = (0, modes_1.shouldAutoAllow)(tool_name);
113
+ if (modeResult === 'block') {
114
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: 'lockdown', decision: 'blocked', timestamp: ts });
115
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: 'blocked', reason: 'lockdown' });
116
+ return res.json({ decision: 'block', reason: 'lockdown mode' });
117
+ }
118
+ if (modeResult === 'auto_allow') {
119
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: 'mode', decision: 'auto_allow', timestamp: ts, summary: `${(0, modes_1.getMode)()} mode` });
120
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: 'allowed', reason: `mode:${(0, modes_1.getMode)()}` });
121
+ return res.json({ decision: 'allow' });
122
+ }
123
+ // 1. Local rules
124
+ const match = (0, engine_1.matchRules)(tool_name, filePath);
125
+ if (match.action === 'auto_allow') {
126
+ logger_1.log.success(`Auto-allow: ${tool_name} (rule: ${match.rule?.id ?? 'default'})`);
127
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: 'auto_allow', decision: 'auto_allow', timestamp: ts });
128
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: 'allowed', reason: `auto:${match.rule?.id ?? ''}` });
129
+ return res.json({ decision: 'allow' });
130
+ }
131
+ // 2. Check transport
132
+ const transport = (0, interface_1.getTransport)();
133
+ if (!transport || !transport.isConnected) {
134
+ logger_1.log.error(`${transport?.mode ?? 'no'} transport offline — blocking`);
135
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: (0, engine_1.riskToLevel)(match.action), decision: 'offline', timestamp: ts });
136
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: 'blocked', reason: 'offline' });
137
+ return res.json({ decision: 'block', reason: 'Sentinel offline' });
138
+ }
139
+ try {
140
+ // 为 Write/Edit 生成 diff
141
+ const diff = (0, diff_1.generateDiff)(tool_name, tool_input);
142
+ const contextSummary = req.body.context_summary
143
+ ?? req.body.contextSummary;
144
+ const remoteId = await transport.sendApprovalRequest({
145
+ toolName: tool_name,
146
+ toolInput: tool_input,
147
+ riskLevel: (0, engine_1.riskToLevel)(match.action),
148
+ diff,
149
+ contextSummary,
150
+ });
151
+ logger_1.log.info(`[${transport.mode}] Waiting: ${remoteId}`);
152
+ const action = await pending_1.pending.waitForDecision(remoteId, tool_name);
153
+ (0, history_1.appendLog)({ id: remoteId, toolName: tool_name, filePath, riskLevel: (0, engine_1.riskToLevel)(match.action), decision: action, timestamp: ts });
154
+ pushEvent({ time: ts, tool: tool_name, path: filePath, decision: action === 'allowed' ? 'allowed' : 'blocked', reason: action === 'allowed' ? 'manual' : action });
155
+ if (action === 'allowed') {
156
+ logger_1.log.success(`Allowed: ${tool_name} (${remoteId})`);
157
+ sendTerminalLine(`✅ ${tool_name}${filePath ? ` → ${filePath}` : ''} — allowed`);
158
+ return res.json({ decision: 'allow' });
159
+ }
160
+ else {
161
+ logger_1.log.warn(`Blocked: ${tool_name} (${remoteId}) — ${action}`);
162
+ sendTerminalLine(`❌ ${tool_name}${filePath ? ` → ${filePath}` : ''} — ${action}`);
163
+ return res.json({ decision: 'block', reason: action });
164
+ }
165
+ }
166
+ catch (err) {
167
+ logger_1.log.error(`Hook error: ${err.message}`);
168
+ (0, history_1.appendLog)({ id: requestId, toolName: tool_name, filePath, riskLevel: (0, engine_1.riskToLevel)(match.action), decision: 'blocked', timestamp: ts });
169
+ return res.json({ decision: 'block', reason: 'Internal error' });
170
+ }
171
+ });
172
+ // ==================== PostToolUse / Notification / Stop events ====================
173
+ app.post('/event', (req, res) => {
174
+ const body = req.body ?? {};
175
+ const hookEvent = body.hook_event_name ?? body.event ?? '';
176
+ const ts = new Date().toISOString();
177
+ if (hookEvent === 'PostToolUse' || hookEvent === 'post_tool_use') {
178
+ const toolName = body.tool_name ?? body.toolName ?? 'unknown';
179
+ const toolInput = body.tool_input ?? body.toolInput ?? {};
180
+ const toolResponse = typeof body.tool_response === 'string' ? body.tool_response : JSON.stringify(body.tool_response ?? '').slice(0, 200);
181
+ const summary = (0, summarizer_1.summarize)(toolName, toolInput, toolResponse);
182
+ logger_1.log.dim(`[event] ${toolName}: ${summary}`);
183
+ (0, history_1.appendLog)({ id: (0, crypto_1.randomBytes)(4).toString('hex'), toolName, filePath: (toolInput.file_path ?? toolInput.path ?? null), riskLevel: 'completed', decision: 'completed', timestamp: ts, result: 'success', summary });
184
+ sendActivity('tool_completed', { toolName, summary });
185
+ pushEvent({ time: ts, type: 'tool_completed', tool: toolName, summary });
186
+ // Terminal output: send tool response to iOS terminal view
187
+ const responseText = typeof body.tool_response === 'string'
188
+ ? body.tool_response
189
+ : JSON.stringify(body.tool_response ?? '', null, 2);
190
+ sendTerminalLine(`[${toolName}] ${summary}`);
191
+ if (responseText && responseText.length > 2) {
192
+ const lines = responseText.slice(0, 2000).split('\n');
193
+ for (const line of lines) {
194
+ sendTerminalLine(line);
195
+ }
196
+ }
197
+ }
198
+ else if (hookEvent === 'Notification' || hookEvent === 'notification') {
199
+ const message = body.message ?? body.text ?? '';
200
+ logger_1.log.info(`[event] Notification: ${message}`);
201
+ sendActivity('notification', { message });
202
+ sendTerminalLine(`📢 ${message}`);
203
+ // Also send system notification
204
+ const transport = (0, interface_1.getTransport)();
205
+ if (transport?.isConnected && transport.sendNotification) {
206
+ transport.sendNotification('Claude Code', message);
207
+ }
208
+ pushEvent({ time: ts, type: 'notification', message });
209
+ }
210
+ else if (hookEvent === 'Stop' || hookEvent === 'stop') {
211
+ const stopReason = body.stop_reason ?? body.reason ?? 'completed';
212
+ const summary = (0, summarizer_1.summarizeStop)(stopReason);
213
+ logger_1.log.info(`[event] Stop: ${summary}`);
214
+ sendActivity('stop', { stopReason, summary });
215
+ (0, session_1.addSessionEvent)({ type: 'stop', stopReason, summary, timestamp: ts });
216
+ // Send system notification (important — user may not be looking)
217
+ const transport = (0, interface_1.getTransport)();
218
+ if (transport?.isConnected && transport.sendNotification) {
219
+ const isError = stopReason === 'error';
220
+ transport.sendNotification(isError ? '❌ Claude Code' : '✅ Claude Code', summary);
221
+ }
222
+ pushEvent({ time: ts, type: 'stop', stopReason, summary });
223
+ // Check for pending user message → auto-resume
224
+ if ((0, fs_1.existsSync)(PENDING_MSG_PATH)) {
225
+ try {
226
+ const msg = (0, fs_1.readFileSync)(PENDING_MSG_PATH, 'utf-8').trim();
227
+ (0, fs_1.unlinkSync)(PENDING_MSG_PATH);
228
+ if (msg) {
229
+ logger_1.log.info(`[event] Resuming Claude with message: ${msg.slice(0, 50)}...`);
230
+ const child = (0, child_process_1.spawn)('claude', ['--continue', '--print', msg], {
231
+ detached: true, stdio: 'ignore',
232
+ });
233
+ child.unref();
234
+ showSpinner('helix', 'Claude Code 正在启动…', 3000);
235
+ }
236
+ }
237
+ catch { }
238
+ }
239
+ }
240
+ else if (hookEvent === 'TaskCompleted' || hookEvent === 'task_completed') {
241
+ logger_1.log.info('[event] Task completed');
242
+ sendActivity('task_completed', { summary: 'Sub-task completed' });
243
+ pushEvent({ time: ts, type: 'task_completed' });
244
+ }
245
+ else if (hookEvent === 'SessionEnd' || hookEvent === 'session_end') {
246
+ logger_1.log.info('[event] Session ended');
247
+ sendActivity('session_ended', { summary: 'Session ended' });
248
+ pushEvent({ time: ts, type: 'session_ended' });
249
+ }
250
+ res.json({ ok: true });
251
+ });
252
+ // ==================== Notify endpoint ====================
253
+ app.post('/notify', (req, res) => {
254
+ const { title, message } = req.body ?? {};
255
+ if (!message)
256
+ return res.status(400).json({ error: 'message required' });
257
+ const transport = (0, interface_1.getTransport)();
258
+ if (!transport?.isConnected)
259
+ return res.status(503).json({ error: 'iOS not connected' });
260
+ if (transport.sendNotification) {
261
+ transport.sendNotification(title ?? 'Sentinel', message);
262
+ }
263
+ else {
264
+ return res.status(501).json({ error: 'Not supported' });
265
+ }
266
+ logger_1.log.info(`Notification: ${title ?? 'Sentinel'} — ${message}`);
267
+ res.json({ success: true });
268
+ });
269
+ // ==================== Interrupt Claude ====================
270
+ app.post('/interrupt', (_req, res) => {
271
+ if (!(0, claude_process_1.isClaudeRunning)()) {
272
+ return res.status(409).json({ error: 'Claude not running' });
273
+ }
274
+ const ok = (0, claude_process_1.interruptClaude)();
275
+ logger_1.log.info('[interrupt] SIGINT sent to Claude');
276
+ res.json({ success: ok });
277
+ });
278
+ // ==================== User message from iOS ====================
279
+ app.post('/user-message', (req, res) => {
280
+ const text = req.body?.text;
281
+ if (!text)
282
+ return res.status(400).json({ error: 'text required' });
283
+ (0, fs_1.writeFileSync)(PENDING_MSG_PATH, text);
284
+ logger_1.log.info(`Pending message saved: ${text.slice(0, 50)}`);
285
+ showSpinner('pulse', '消息已排队,等待 Claude 停止…', 5000);
286
+ res.json({ success: true });
287
+ });
288
+ // ==================== SSE Auth Middleware ====================
289
+ function requireSseToken(req, res) {
290
+ const token = req.query.token;
291
+ if (token !== SSE_TOKEN) {
292
+ res.status(401).json({ error: 'Invalid or missing SSE token' });
293
+ return false;
294
+ }
295
+ return true;
296
+ }
297
+ // ==================== Terminal SSE ====================
298
+ app.get('/terminal', (req, res) => {
299
+ if (!requireSseToken(req, res))
300
+ return;
301
+ res.setHeader('Content-Type', 'text/event-stream');
302
+ res.setHeader('Cache-Control', 'no-cache');
303
+ res.setHeader('Connection', 'keep-alive');
304
+ res.flushHeaders();
305
+ terminalClients.add(res);
306
+ res.on('close', () => terminalClients.delete(res));
307
+ });
308
+ // ==================== SSE ====================
309
+ app.get('/events', (req, res) => {
310
+ if (!requireSseToken(req, res))
311
+ return;
312
+ res.setHeader('Content-Type', 'text/event-stream');
313
+ res.setHeader('Cache-Control', 'no-cache');
314
+ res.setHeader('Connection', 'keep-alive');
315
+ res.flushHeaders();
316
+ sseClients.add(res);
317
+ res.on('close', () => sseClients.delete(res));
318
+ });
319
+ // ==================== SSE Token (for CLI watch command) ====================
320
+ app.get('/sse-token', (_req, res) => {
321
+ // Only accessible from localhost
322
+ res.json({ token: SSE_TOKEN });
323
+ });
324
+ // ==================== Status ====================
325
+ app.get('/status', (_req, res) => {
326
+ const transport = (0, interface_1.getTransport)();
327
+ res.json({
328
+ mode: transport?.mode ?? 'none',
329
+ connected: transport?.isConnected ?? false,
330
+ pendingRequests: pending_1.pending.size,
331
+ uptime: process.uptime(),
332
+ version: '0.1.0',
333
+ });
334
+ });
335
+ return app;
336
+ }
337
+ function startHttpServer(port = 7749) {
338
+ return new Promise((resolve) => {
339
+ const app = createHttpServer(port);
340
+ app.listen(port, () => {
341
+ logger_1.log.success(`Hook server listening on http://localhost:${port}`);
342
+ logger_1.log.dim(` POST /hook — PreToolUse (approval)`);
343
+ logger_1.log.dim(` POST /event — PostToolUse / Notification / Stop`);
344
+ logger_1.log.dim(` GET /events — SSE stream`);
345
+ resolve();
346
+ });
347
+ });
348
+ }
349
+ /** Setup user message handler from LocalTransport */
350
+ function setupUserMessageHandler() {
351
+ const transport = (0, interface_1.getTransport)();
352
+ if (transport && 'onUserMessage' in transport) {
353
+ transport.onUserMessage((text) => {
354
+ (0, fs_1.writeFileSync)(PENDING_MSG_PATH, text);
355
+ logger_1.log.info(`Message from iOS saved: ${text.slice(0, 50)}`);
356
+ });
357
+ }
358
+ }
359
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Socket } from 'socket.io-client';
2
+ /**
3
+ * 连接 Socket.IO,带 JWT auth 和指数退避重连
4
+ */
5
+ export declare function connectSocket(serverURL: string, token: string): Socket;
6
+ /**
7
+ * 发送审批请求到 server,返回 requestId
8
+ */
9
+ export declare function emitApprovalRequest(data: {
10
+ toolName: string;
11
+ toolInput: Record<string, unknown>;
12
+ riskLevel: string;
13
+ }): Promise<string>;
14
+ export declare function getSocket(): Socket | null;
15
+ export declare function disconnectSocket(): void;
16
+ export declare function isConnected(): boolean;