sessix-server 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 (61) hide show
  1. package/dist/approval/ApprovalProxy.d.ts +86 -0
  2. package/dist/approval/ApprovalProxy.d.ts.map +1 -0
  3. package/dist/approval/ApprovalProxy.js +363 -0
  4. package/dist/approval/ApprovalProxy.js.map +1 -0
  5. package/dist/hooks/HookInstaller.d.ts +55 -0
  6. package/dist/hooks/HookInstaller.d.ts.map +1 -0
  7. package/dist/hooks/HookInstaller.js +215 -0
  8. package/dist/hooks/HookInstaller.js.map +1 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +3115 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mdns/MdnsService.d.ts +36 -0
  14. package/dist/mdns/MdnsService.d.ts.map +1 -0
  15. package/dist/mdns/MdnsService.js +66 -0
  16. package/dist/mdns/MdnsService.js.map +1 -0
  17. package/dist/notification/ActivityPushChannel.d.ts +54 -0
  18. package/dist/notification/ActivityPushChannel.d.ts.map +1 -0
  19. package/dist/notification/ActivityPushChannel.js +235 -0
  20. package/dist/notification/ActivityPushChannel.js.map +1 -0
  21. package/dist/notification/ExpoNotificationChannel.d.ts +17 -0
  22. package/dist/notification/ExpoNotificationChannel.d.ts.map +1 -0
  23. package/dist/notification/ExpoNotificationChannel.js +57 -0
  24. package/dist/notification/ExpoNotificationChannel.js.map +1 -0
  25. package/dist/notification/MacNotificationChannel.d.ts +22 -0
  26. package/dist/notification/MacNotificationChannel.d.ts.map +1 -0
  27. package/dist/notification/MacNotificationChannel.js +33 -0
  28. package/dist/notification/MacNotificationChannel.js.map +1 -0
  29. package/dist/notification/NotificationService.d.ts +50 -0
  30. package/dist/notification/NotificationService.d.ts.map +1 -0
  31. package/dist/notification/NotificationService.js +177 -0
  32. package/dist/notification/NotificationService.js.map +1 -0
  33. package/dist/providers/ExecutionProvider.d.ts +60 -0
  34. package/dist/providers/ExecutionProvider.d.ts.map +1 -0
  35. package/dist/providers/ExecutionProvider.js +3 -0
  36. package/dist/providers/ExecutionProvider.js.map +1 -0
  37. package/dist/providers/ProcessProvider.d.ts +117 -0
  38. package/dist/providers/ProcessProvider.d.ts.map +1 -0
  39. package/dist/providers/ProcessProvider.js +507 -0
  40. package/dist/providers/ProcessProvider.js.map +1 -0
  41. package/dist/server.d.ts +32 -0
  42. package/dist/server.d.ts.map +1 -0
  43. package/dist/server.js +3054 -0
  44. package/dist/server.js.map +1 -0
  45. package/dist/session/ProjectReader.d.ts +44 -0
  46. package/dist/session/ProjectReader.d.ts.map +1 -0
  47. package/dist/session/ProjectReader.js +471 -0
  48. package/dist/session/ProjectReader.js.map +1 -0
  49. package/dist/session/SessionFileWatcher.d.ts +35 -0
  50. package/dist/session/SessionFileWatcher.d.ts.map +1 -0
  51. package/dist/session/SessionFileWatcher.js +207 -0
  52. package/dist/session/SessionFileWatcher.js.map +1 -0
  53. package/dist/session/SessionManager.d.ts +114 -0
  54. package/dist/session/SessionManager.d.ts.map +1 -0
  55. package/dist/session/SessionManager.js +356 -0
  56. package/dist/session/SessionManager.js.map +1 -0
  57. package/dist/ws/WsBridge.d.ts +55 -0
  58. package/dist/ws/WsBridge.d.ts.map +1 -0
  59. package/dist/ws/WsBridge.js +220 -0
  60. package/dist/ws/WsBridge.js.map +1 -0
  61. package/package.json +38 -0
@@ -0,0 +1,86 @@
1
+ import type { ApprovalRequest, ApprovalDecision } from '@sessix/shared';
2
+ /** ApprovalProxy 配置 */
3
+ interface ApprovalProxyOptions {
4
+ port: number;
5
+ token: string;
6
+ }
7
+ /** 外部注入的连接信息回调(用于 /health 端点) */
8
+ interface StatusInfo {
9
+ connections: number;
10
+ activeSessions: number;
11
+ }
12
+ /**
13
+ * 审批代理 HTTP 服务
14
+ *
15
+ * 接收 Claude Code hook 发来的工具审批请求,通过长轮询机制
16
+ * hold 住响应,等待手机端用户做出审批决策后再返回。
17
+ */
18
+ export declare class ApprovalProxy {
19
+ private server;
20
+ private token;
21
+ private port;
22
+ private settingsPath;
23
+ /** 待处理的审批请求:requestId -> { resolve, timer, request } */
24
+ private pendingApprovals;
25
+ /** 审批请求回调(通知外部推送到手机) */
26
+ private approvalRequestCallbacks;
27
+ /** 获取状态信息的回调(由外部注入) */
28
+ private statusInfoProvider;
29
+ constructor(options: ApprovalProxyOptions);
30
+ /**
31
+ * 异步工厂方法:等待端口监听成功后 resolve,端口占用等错误时 reject。
32
+ */
33
+ static create(options: ApprovalProxyOptions): Promise<ApprovalProxy>;
34
+ /** 注册审批请求回调(当有新的审批请求时触发) */
35
+ onApprovalRequest(callback: (request: ApprovalRequest) => void): void;
36
+ /** 设置状态信息提供者(用于 /health 端点) */
37
+ setStatusInfoProvider(provider: () => StatusInfo): void;
38
+ /**
39
+ * 注入审批结果
40
+ *
41
+ * 从 pendingApprovals 中取出对应请求,resolve promise,
42
+ * 让长轮询的 HTTP 响应返回审批结果给 Claude Code hook。
43
+ */
44
+ resolveApproval(requestId: string, decision: ApprovalDecision): boolean;
45
+ /** 获取当前待处理的审批数量 */
46
+ getPendingCount(): number;
47
+ /** 检查指定审批请求是否仍在等待用户决策 */
48
+ isPending(requestId: string): boolean;
49
+ /** 检查工具是否已在 settings.json permissions.allow 中(检查项目级和全局) */
50
+ private isToolInClaudeSettings;
51
+ /** 将工具写入 settings.json permissions.allow(项目级或全局) */
52
+ addToClaudeSettings(projectPath: string | undefined, toolName: string): void;
53
+ /** 获取指定会话的所有 pending approval requests(用于 subscribe 重发) */
54
+ getPendingRequestsForSession(sessionId: string): ApprovalRequest[];
55
+ /**
56
+ * 批量允许所有待处理的审批请求(手机端断线时调用)
57
+ */
58
+ approveAll(reason?: string): void;
59
+ /** 优雅关闭 HTTP 服务 */
60
+ close(): Promise<void>;
61
+ /** 路由请求 */
62
+ private handleRequest;
63
+ /**
64
+ * 核心端点:处理 Claude Code hook 的审批请求
65
+ *
66
+ * 长轮询实现:
67
+ * 1. 解析请求 body
68
+ * 2. 创建 ApprovalRequest 对象
69
+ * 3. 通知外部(推到手机)
70
+ * 4. 创建 Promise 并 hold 住 response
71
+ * 5. 等待 resolveApproval() 被调用或超时
72
+ */
73
+ private handleApprovalHook;
74
+ /** 健康检查端点 */
75
+ private handleHealth;
76
+ /** 返回连接 token(仅本机访问) */
77
+ private handleToken;
78
+ /** 通知所有注册的审批请求回调 */
79
+ private notifyApprovalRequest;
80
+ /** 手动解析请求的 JSON body(限制最大 1MB 防止滥用) */
81
+ private parseJsonBody;
82
+ /** 发送 JSON 响应的辅助方法 */
83
+ private sendJson;
84
+ }
85
+ export {};
86
+ //# sourceMappingURL=ApprovalProxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApprovalProxy.d.ts","sourceRoot":"","sources":["../../src/approval/ApprovalProxy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEvE,uBAAuB;AACvB,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAED,iCAAiC;AACjC,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,YAAY,CAAsD;IAE1E,wDAAwD;IACxD,OAAO,CAAC,gBAAgB,CAIpB;IAEJ,wBAAwB;IACxB,OAAO,CAAC,wBAAwB,CAAgD;IAEhF,uBAAuB;IACvB,OAAO,CAAC,kBAAkB,CAAkC;gBAEhD,OAAO,EAAE,oBAAoB;IAazC;;OAEG;WACU,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAe1E,4BAA4B;IAC5B,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAIrE,+BAA+B;IAC/B,qBAAqB,CAAC,QAAQ,EAAE,MAAM,UAAU,GAAG,IAAI;IAIvD;;;;;OAKG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO;IAkBvE,mBAAmB;IACnB,eAAe,IAAI,MAAM;IAIzB,yBAAyB;IACzB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIrC,2DAA2D;IAC3D,OAAO,CAAC,sBAAsB;IAsB9B,oDAAoD;IACpD,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAwC5E,2DAA2D;IAC3D,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE;IAUlE;;OAEG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAUjC,mBAAmB;IACnB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BtB,WAAW;IACX,OAAO,CAAC,aAAa;IA2BrB;;;;;;;;;OASG;YACW,kBAAkB;IAyDhC,aAAa;IACb,OAAO,CAAC,YAAY;IASpB,wBAAwB;IACxB,OAAO,CAAC,WAAW;IAenB,oBAAoB;IACpB,OAAO,CAAC,qBAAqB;IAU7B,uCAAuC;IACvC,OAAO,CAAC,aAAa;IAgCrB,sBAAsB;IACtB,OAAO,CAAC,QAAQ;CAQjB"}
@@ -0,0 +1,363 @@
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.ApprovalProxy = void 0;
7
+ const node_http_1 = __importDefault(require("node:http"));
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_os_1 = __importDefault(require("node:os"));
11
+ const uuid_1 = require("uuid");
12
+ /**
13
+ * 审批代理 HTTP 服务
14
+ *
15
+ * 接收 Claude Code hook 发来的工具审批请求,通过长轮询机制
16
+ * hold 住响应,等待手机端用户做出审批决策后再返回。
17
+ */
18
+ class ApprovalProxy {
19
+ server;
20
+ token;
21
+ port;
22
+ settingsPath = node_path_1.default.join(node_os_1.default.homedir(), '.claude', 'settings.json');
23
+ /** 待处理的审批请求:requestId -> { resolve, timer, request } */
24
+ pendingApprovals = new Map();
25
+ /** 审批请求回调(通知外部推送到手机) */
26
+ approvalRequestCallbacks = [];
27
+ /** 获取状态信息的回调(由外部注入) */
28
+ statusInfoProvider = null;
29
+ constructor(options) {
30
+ this.token = options.token;
31
+ this.port = options.port;
32
+ this.server = node_http_1.default.createServer((req, res) => {
33
+ this.handleRequest(req, res);
34
+ });
35
+ this.server.listen(options.port, () => {
36
+ console.log(`[ApprovalProxy] HTTP 审批服务已启动,端口 ${options.port}`);
37
+ });
38
+ }
39
+ /**
40
+ * 异步工厂方法:等待端口监听成功后 resolve,端口占用等错误时 reject。
41
+ */
42
+ static async create(options) {
43
+ return new Promise((resolve, reject) => {
44
+ const proxy = new ApprovalProxy(options);
45
+ proxy.server.once('listening', () => {
46
+ proxy.server.on('error', (err) => console.error('[ApprovalProxy] 服务运行错误:', err));
47
+ resolve(proxy);
48
+ });
49
+ proxy.server.once('error', reject);
50
+ });
51
+ }
52
+ // ============================================
53
+ // 公开 API
54
+ // ============================================
55
+ /** 注册审批请求回调(当有新的审批请求时触发) */
56
+ onApprovalRequest(callback) {
57
+ this.approvalRequestCallbacks.push(callback);
58
+ }
59
+ /** 设置状态信息提供者(用于 /health 端点) */
60
+ setStatusInfoProvider(provider) {
61
+ this.statusInfoProvider = provider;
62
+ }
63
+ /**
64
+ * 注入审批结果
65
+ *
66
+ * 从 pendingApprovals 中取出对应请求,resolve promise,
67
+ * 让长轮询的 HTTP 响应返回审批结果给 Claude Code hook。
68
+ */
69
+ resolveApproval(requestId, decision) {
70
+ const pending = this.pendingApprovals.get(requestId);
71
+ if (!pending) {
72
+ console.warn(`[ApprovalProxy] 审批请求 ${requestId} 不存在或已超时`);
73
+ return false;
74
+ }
75
+ // 清除超时定时器
76
+ clearTimeout(pending.timer);
77
+ // resolve promise,长轮询响应将返回
78
+ pending.resolve(decision);
79
+ // 从 map 中移除
80
+ this.pendingApprovals.delete(requestId);
81
+ console.log(`[ApprovalProxy] 审批请求 ${requestId} 已处理: ${decision.decision}`);
82
+ return true;
83
+ }
84
+ /** 获取当前待处理的审批数量 */
85
+ getPendingCount() {
86
+ return this.pendingApprovals.size;
87
+ }
88
+ /** 检查指定审批请求是否仍在等待用户决策 */
89
+ isPending(requestId) {
90
+ return this.pendingApprovals.has(requestId);
91
+ }
92
+ /** 检查工具是否已在 settings.json permissions.allow 中(检查项目级和全局) */
93
+ isToolInClaudeSettings(toolName, projectPath) {
94
+ const checkPath = (filepath) => {
95
+ try {
96
+ const raw = node_fs_1.default.readFileSync(filepath, 'utf-8');
97
+ const settings = JSON.parse(raw);
98
+ const allow = settings?.permissions?.allow ?? [];
99
+ // 匹配 "Edit(*)" 或 "Edit" 开头的任何条目
100
+ return allow.some(entry => entry === `${toolName}(*)` || entry === toolName);
101
+ }
102
+ catch {
103
+ return false;
104
+ }
105
+ };
106
+ // 优先检查项目级(若提供)
107
+ if (projectPath) {
108
+ const projectSettingsPath = node_path_1.default.join(projectPath, '.claude', 'settings.json');
109
+ if (checkPath(projectSettingsPath))
110
+ return true;
111
+ }
112
+ // 再检查全局
113
+ return checkPath(this.settingsPath);
114
+ }
115
+ /** 将工具写入 settings.json permissions.allow(项目级或全局) */
116
+ addToClaudeSettings(projectPath, toolName) {
117
+ const targetPath = projectPath
118
+ ? node_path_1.default.join(projectPath, '.claude', 'settings.json')
119
+ : this.settingsPath;
120
+ try {
121
+ // 确保目录存在
122
+ if (projectPath) {
123
+ const dir = node_path_1.default.dirname(targetPath);
124
+ if (!node_fs_1.default.existsSync(dir)) {
125
+ node_fs_1.default.mkdirSync(dir, { recursive: true });
126
+ }
127
+ }
128
+ let settings = {};
129
+ try {
130
+ settings = JSON.parse(node_fs_1.default.readFileSync(targetPath, 'utf-8'));
131
+ }
132
+ catch {
133
+ // 文件不存在时从空对象开始
134
+ }
135
+ if (!settings.permissions) {
136
+ settings.permissions = {};
137
+ }
138
+ const perms = settings.permissions;
139
+ if (!Array.isArray(perms.allow)) {
140
+ perms.allow = [];
141
+ }
142
+ const allow = perms.allow;
143
+ const entry = `${toolName}(*)`;
144
+ if (!allow.includes(entry)) {
145
+ allow.push(entry);
146
+ node_fs_1.default.writeFileSync(targetPath, JSON.stringify(settings, null, 2), 'utf-8');
147
+ const label = projectPath ? `${projectPath}/.claude/settings.json` : '~/.claude/settings.json';
148
+ console.log(`[ApprovalProxy] 已将 ${entry} 写入 ${label}`);
149
+ }
150
+ }
151
+ catch (err) {
152
+ console.error('[ApprovalProxy] 写入 settings.json 失败:', err);
153
+ }
154
+ }
155
+ /** 获取指定会话的所有 pending approval requests(用于 subscribe 重发) */
156
+ getPendingRequestsForSession(sessionId) {
157
+ const result = [];
158
+ for (const { request } of this.pendingApprovals.values()) {
159
+ if (request.sessionId === sessionId) {
160
+ result.push(request);
161
+ }
162
+ }
163
+ return result;
164
+ }
165
+ /**
166
+ * 批量允许所有待处理的审批请求(手机端断线时调用)
167
+ */
168
+ approveAll(reason) {
169
+ const entries = Array.from(this.pendingApprovals.entries());
170
+ for (const [requestId, pending] of entries) {
171
+ clearTimeout(pending.timer);
172
+ pending.resolve({ decision: 'allow' });
173
+ this.pendingApprovals.delete(requestId);
174
+ console.log(`[ApprovalProxy] 审批请求 ${requestId} 已自动允许${reason ? `(${reason})` : ''}`);
175
+ }
176
+ }
177
+ /** 优雅关闭 HTTP 服务 */
178
+ close() {
179
+ return new Promise((resolve, reject) => {
180
+ // 清理所有待处理的审批(默认放行)
181
+ // 先收集再清理,避免迭代中删除
182
+ const pendingEntries = Array.from(this.pendingApprovals.entries());
183
+ for (const [, pending] of pendingEntries) {
184
+ clearTimeout(pending.timer);
185
+ pending.resolve({ decision: 'deny', reason: '服务器已关闭' });
186
+ }
187
+ this.pendingApprovals.clear();
188
+ this.server.close((err) => {
189
+ if (err) {
190
+ reject(err);
191
+ }
192
+ else {
193
+ console.log('[ApprovalProxy] HTTP 审批服务已关闭');
194
+ resolve();
195
+ }
196
+ });
197
+ });
198
+ }
199
+ // ============================================
200
+ // 内部方法
201
+ // ============================================
202
+ /** 路由请求 */
203
+ handleRequest(req, res) {
204
+ // CORS 支持(局域网跨域)
205
+ res.setHeader('Access-Control-Allow-Origin', '*');
206
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
207
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
208
+ // 预检请求直接返回
209
+ if (req.method === 'OPTIONS') {
210
+ res.writeHead(204);
211
+ res.end();
212
+ return;
213
+ }
214
+ const url = new URL(req.url ?? '/', `http://${req.headers.host}`);
215
+ const pathname = url.pathname;
216
+ if (req.method === 'POST' && pathname === '/hook/approval') {
217
+ this.handleApprovalHook(req, res);
218
+ }
219
+ else if (req.method === 'GET' && pathname === '/health') {
220
+ this.handleHealth(req, res);
221
+ }
222
+ else if (req.method === 'GET' && pathname === '/token') {
223
+ this.handleToken(req, res);
224
+ }
225
+ else {
226
+ this.sendJson(res, 404, { error: 'Not Found' });
227
+ }
228
+ }
229
+ /**
230
+ * 核心端点:处理 Claude Code hook 的审批请求
231
+ *
232
+ * 长轮询实现:
233
+ * 1. 解析请求 body
234
+ * 2. 创建 ApprovalRequest 对象
235
+ * 3. 通知外部(推到手机)
236
+ * 4. 创建 Promise 并 hold 住 response
237
+ * 5. 等待 resolveApproval() 被调用或超时
238
+ */
239
+ async handleApprovalHook(req, res) {
240
+ try {
241
+ // 手动解析 JSON body
242
+ const body = await this.parseJsonBody(req);
243
+ // 构建 ApprovalRequest 对象
244
+ // hook 脚本发送格式: { sessionId, projectPath, payload: { tool_name, tool_input, ... } }
245
+ const payload = body.payload ?? body;
246
+ const requestId = (0, uuid_1.v4)();
247
+ const projectPath = String(body.projectPath ?? 'unknown');
248
+ const toolName = String(payload.tool_name ?? body.tool_name ?? 'unknown');
249
+ const toolInput = payload.tool_input ?? body.tool_input ?? {};
250
+ const approvalRequest = {
251
+ id: requestId,
252
+ sessionId: String(body.sessionId ?? 'unknown'),
253
+ projectPath,
254
+ toolName,
255
+ toolInput,
256
+ description: String(payload.description ?? body.description ?? `${toolName} 工具调用请求`),
257
+ createdAt: Date.now(),
258
+ };
259
+ console.log(`[ApprovalProxy] 收到审批请求: ${requestId} (${approvalRequest.toolName})`);
260
+ // 检查工具是否已在 Claude Code settings 中被允许,如果是直接放行(不需要手机审批)
261
+ // 优先检查项目级,再检查全局
262
+ if (this.isToolInClaudeSettings(approvalRequest.toolName, projectPath !== 'unknown' ? projectPath : undefined)) {
263
+ console.log(`[ApprovalProxy] ${approvalRequest.toolName} 已在 settings.json 中被允许,直接放行`);
264
+ this.sendJson(res, 200, { decision: 'allow' });
265
+ return;
266
+ }
267
+ // 通知外部(会被推送到手机端)
268
+ this.notifyApprovalRequest(approvalRequest);
269
+ // 长轮询:创建 Promise,等待审批结果或超时
270
+ const decision = await new Promise((resolve) => {
271
+ // 5 分钟超时,默认允许(手机端可能已断线,不应阻塞任务)
272
+ const timer = setTimeout(() => {
273
+ console.log(`[ApprovalProxy] 审批请求 ${requestId} 已超时,默认允许`);
274
+ this.pendingApprovals.delete(requestId);
275
+ resolve({ decision: 'allow' });
276
+ }, 300_000);
277
+ // 存入待处理 map(包含完整的 request 对象用于 subscribe 重发)
278
+ this.pendingApprovals.set(requestId, { resolve, timer, request: approvalRequest });
279
+ });
280
+ // 返回审批结果给 Claude Code hook
281
+ this.sendJson(res, 200, decision);
282
+ }
283
+ catch (err) {
284
+ console.error('[ApprovalProxy] 处理审批请求失败:', err);
285
+ // 出错时默认拒绝(安全优先)
286
+ this.sendJson(res, 200, { decision: 'deny', reason: '服务器处理请求失败' });
287
+ }
288
+ }
289
+ /** 健康检查端点 */
290
+ handleHealth(_req, res) {
291
+ const info = this.statusInfoProvider?.() ?? { connections: 0, activeSessions: 0 };
292
+ this.sendJson(res, 200, {
293
+ status: 'ok',
294
+ connections: info.connections,
295
+ activeSessions: info.activeSessions,
296
+ });
297
+ }
298
+ /** 返回连接 token(仅本机访问) */
299
+ handleToken(req, res) {
300
+ // 检查是否为本机访问
301
+ const remoteAddress = req.socket.remoteAddress;
302
+ const isLocal = remoteAddress === '127.0.0.1'
303
+ || remoteAddress === '::1'
304
+ || remoteAddress === '::ffff:127.0.0.1';
305
+ if (!isLocal) {
306
+ this.sendJson(res, 403, { error: 'Forbidden: 仅允许本机访问' });
307
+ return;
308
+ }
309
+ this.sendJson(res, 200, { token: this.token });
310
+ }
311
+ /** 通知所有注册的审批请求回调 */
312
+ notifyApprovalRequest(request) {
313
+ for (const callback of this.approvalRequestCallbacks) {
314
+ try {
315
+ callback(request);
316
+ }
317
+ catch (err) {
318
+ console.error('[ApprovalProxy] 审批请求回调执行异常:', err);
319
+ }
320
+ }
321
+ }
322
+ /** 手动解析请求的 JSON body(限制最大 1MB 防止滥用) */
323
+ parseJsonBody(req) {
324
+ const MAX_BODY_SIZE = 1024 * 1024; // 1MB
325
+ return new Promise((resolve, reject) => {
326
+ const chunks = [];
327
+ let totalSize = 0;
328
+ req.on('data', (chunk) => {
329
+ totalSize += chunk.length;
330
+ if (totalSize > MAX_BODY_SIZE) {
331
+ req.destroy();
332
+ reject(new Error('请求 body 过大(超过 1MB)'));
333
+ return;
334
+ }
335
+ chunks.push(chunk);
336
+ });
337
+ req.on('end', () => {
338
+ try {
339
+ const raw = Buffer.concat(chunks).toString('utf-8');
340
+ const parsed = JSON.parse(raw);
341
+ resolve(parsed);
342
+ }
343
+ catch {
344
+ reject(new Error('无效的 JSON body'));
345
+ }
346
+ });
347
+ req.on('error', (err) => {
348
+ reject(err);
349
+ });
350
+ });
351
+ }
352
+ /** 发送 JSON 响应的辅助方法 */
353
+ sendJson(res, statusCode, data) {
354
+ const body = JSON.stringify(data);
355
+ res.writeHead(statusCode, {
356
+ 'Content-Type': 'application/json; charset=utf-8',
357
+ 'Content-Length': Buffer.byteLength(body),
358
+ });
359
+ res.end(body);
360
+ }
361
+ }
362
+ exports.ApprovalProxy = ApprovalProxy;
363
+ //# sourceMappingURL=ApprovalProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApprovalProxy.js","sourceRoot":"","sources":["../../src/approval/ApprovalProxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Hook 安装器
3
+ *
4
+ * 负责将 Sessix 的审批 hook 脚本安装到 Claude Code 中:
5
+ * 1. 创建 ~/.sessix/hooks/ 目录并写入 approval-hook.sh
6
+ * 2. 在 ~/.claude/settings.json 中注册 PreToolUse hook
7
+ */
8
+ export declare class HookInstaller {
9
+ /**
10
+ * 安装 hook
11
+ *
12
+ * 1. 创建 ~/.sessix/hooks/ 目录
13
+ * 2. 写入 approval-hook.sh 脚本
14
+ * 3. 赋予执行权限
15
+ * 4. 更新 Claude Code settings.json 添加 hook 配置
16
+ */
17
+ install(): Promise<void>;
18
+ /**
19
+ * 卸载 hook
20
+ *
21
+ * 从 Claude Code settings.json 中移除 Sessix hook 配置。
22
+ * 注意:不删除 hook 脚本文件(保持幂等性,避免误删)。
23
+ */
24
+ uninstall(): Promise<void>;
25
+ /**
26
+ * 检查 hook 是否已安装
27
+ * 脚本文件和 settings.json 配置必须同时存在才算已安装
28
+ */
29
+ isInstalled(): Promise<boolean>;
30
+ /**
31
+ * 向 Claude Code settings.json 添加 Sessix hook 配置
32
+ */
33
+ private addHookToSettings;
34
+ /**
35
+ * 从 Claude Code settings.json 移除 Sessix hook 配置
36
+ */
37
+ private removeHookFromSettings;
38
+ /**
39
+ * 读取 Claude Code settings.json
40
+ */
41
+ private readClaudeSettings;
42
+ /**
43
+ * 写入 Claude Code settings.json
44
+ */
45
+ private writeClaudeSettings;
46
+ /**
47
+ * 检查 settings 中是否已包含 Sessix hook 配置
48
+ */
49
+ private hasHookConfig;
50
+ /**
51
+ * 判断一个 hook 条目是否是 Sessix 的
52
+ */
53
+ private isSessionHookEntry;
54
+ }
55
+ //# sourceMappingURL=HookInstaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HookInstaller.d.ts","sourceRoot":"","sources":["../../src/hooks/HookInstaller.ts"],"names":[],"mappings":"AAkEA;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB;;;;;;;OAOG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB9B;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAKhC;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAsBrC;;OAEG;YACW,iBAAiB;IA+B/B;;OAEG;YACW,sBAAsB;IAyBpC;;OAEG;YACW,kBAAkB;IAUhC;;OAEG;YACW,mBAAmB;IAMjC;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAS3B"}