@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,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALL_MODES = exports.MODE_DESCRIPTIONS = void 0;
4
+ exports.getMode = getMode;
5
+ exports.setMode = setMode;
6
+ exports.getModeInfo = getModeInfo;
7
+ exports.shouldAutoAllow = shouldAutoAllow;
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ const keys_1 = require("../crypto/keys");
11
+ const MODES_PATH = (0, path_1.join)((0, keys_1.getSentinelDir)(), 'mode.json');
12
+ function loadMode() {
13
+ if (!(0, fs_1.existsSync)(MODES_PATH))
14
+ return { mode: 'strict', changedAt: new Date().toISOString() };
15
+ try {
16
+ return JSON.parse((0, fs_1.readFileSync)(MODES_PATH, 'utf-8'));
17
+ }
18
+ catch {
19
+ return { mode: 'strict', changedAt: new Date().toISOString() };
20
+ }
21
+ }
22
+ function getMode() {
23
+ return loadMode().mode;
24
+ }
25
+ function setMode(mode) {
26
+ (0, fs_1.writeFileSync)(MODES_PATH, JSON.stringify({ mode, changedAt: new Date().toISOString() }, null, 2), { mode: 0o600 });
27
+ }
28
+ function getModeInfo() {
29
+ return loadMode();
30
+ }
31
+ /** Check if a tool should be auto-allowed based on current mode */
32
+ function shouldAutoAllow(toolName) {
33
+ const mode = getMode();
34
+ switch (mode) {
35
+ case 'lockdown':
36
+ return 'block';
37
+ case 'yolo':
38
+ return 'auto_allow';
39
+ case 'relaxed':
40
+ // Only Bash and destructive ops need approval
41
+ if (['Bash', 'Delete'].includes(toolName))
42
+ return 'require';
43
+ return 'auto_allow';
44
+ case 'plan':
45
+ case 'strict':
46
+ default:
47
+ return 'require'; // Let the rule engine decide
48
+ }
49
+ }
50
+ exports.MODE_DESCRIPTIONS = {
51
+ strict: 'Every write/bash needs approval (default)',
52
+ relaxed: 'Only bash & destructive ops need approval',
53
+ yolo: 'Auto-approve everything (logged)',
54
+ plan: 'Strict + group related operations',
55
+ lockdown: 'Block all operations',
56
+ };
57
+ exports.ALL_MODES = ['strict', 'relaxed', 'yolo', 'plan', 'lockdown'];
58
+ //# sourceMappingURL=modes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modes.js","sourceRoot":"","sources":["../../src/lib/modes.ts"],"names":[],"mappings":";;;AAgCA,0BAEC;AAED,0BAEC;AAED,kCAEC;AAGD,0CAoBC;AAjED,2BAA6D;AAC7D,+BAA4B;AAC5B,yCAAgD;AAchD,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,IAAA,qBAAc,GAAE,EAAE,WAAW,CAAC,CAAC;AAOvD,SAAS,QAAQ;IACf,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC5F,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IACjE,CAAC;AACH,CAAC;AAED,SAAgB,OAAO;IACrB,OAAO,QAAQ,EAAE,CAAC,IAAI,CAAC;AACzB,CAAC;AAED,SAAgB,OAAO,CAAC,IAAoB;IAC1C,IAAA,kBAAa,EAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACrH,CAAC;AAED,SAAgB,WAAW;IACzB,OAAO,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED,mEAAmE;AACnE,SAAgB,eAAe,CAAC,QAAgB;IAC9C,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,OAAO,CAAC;QAEjB,KAAK,MAAM;YACT,OAAO,YAAY,CAAC;QAEtB,KAAK,SAAS;YACZ,8CAA8C;YAC9C,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC5D,OAAO,YAAY,CAAC;QAEtB,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,SAAS,CAAC,CAAC,6BAA6B;IACnD,CAAC;AACH,CAAC;AAEY,QAAA,iBAAiB,GAAmC;IAC/D,MAAM,EAAE,2CAA2C;IACnD,OAAO,EAAE,2CAA2C;IACpD,IAAI,EAAE,kCAAkC;IACxC,IAAI,EAAE,mCAAmC;IACzC,QAAQ,EAAE,sBAAsB;CACjC,CAAC;AAEW,QAAA,SAAS,GAAqB,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /** Check current override state (auto-clears expired) */
2
+ export declare function getOverrideState(): {
3
+ blockAll: boolean;
4
+ allowAll: boolean;
5
+ };
6
+ export declare function setBlockAll(on: boolean, durationMinutes?: number): void;
7
+ export declare function setAllowAll(on: boolean, durationMinutes?: number): void;
8
+ export declare function getOverrideInfo(): {
9
+ blockAll: boolean;
10
+ allowAll: boolean;
11
+ blockUntil: string | null;
12
+ allowUntil: string | null;
13
+ };
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOverrideState = getOverrideState;
4
+ exports.setBlockAll = setBlockAll;
5
+ exports.setAllowAll = setAllowAll;
6
+ exports.getOverrideInfo = getOverrideInfo;
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const keys_1 = require("../crypto/keys");
10
+ const OVERRIDES_PATH = (0, path_1.join)((0, keys_1.getSentinelDir)(), 'overrides.json');
11
+ function loadOverrides() {
12
+ if (!(0, fs_1.existsSync)(OVERRIDES_PATH))
13
+ return { blockAll: false, allowAll: false, blockUntil: null, allowUntil: null };
14
+ try {
15
+ return JSON.parse((0, fs_1.readFileSync)(OVERRIDES_PATH, 'utf-8'));
16
+ }
17
+ catch {
18
+ return { blockAll: false, allowAll: false, blockUntil: null, allowUntil: null };
19
+ }
20
+ }
21
+ function saveOverrides(o) {
22
+ (0, fs_1.writeFileSync)(OVERRIDES_PATH, JSON.stringify(o, null, 2), { mode: 0o600 });
23
+ }
24
+ function isExpired(until) {
25
+ if (!until)
26
+ return false;
27
+ return new Date(until) <= new Date();
28
+ }
29
+ /** Check current override state (auto-clears expired) */
30
+ function getOverrideState() {
31
+ const o = loadOverrides();
32
+ let changed = false;
33
+ if (o.blockAll && o.blockUntil && isExpired(o.blockUntil)) {
34
+ o.blockAll = false;
35
+ o.blockUntil = null;
36
+ changed = true;
37
+ }
38
+ if (o.allowAll && o.allowUntil && isExpired(o.allowUntil)) {
39
+ o.allowAll = false;
40
+ o.allowUntil = null;
41
+ changed = true;
42
+ }
43
+ if (changed)
44
+ saveOverrides(o);
45
+ return { blockAll: o.blockAll, allowAll: o.allowAll };
46
+ }
47
+ function setBlockAll(on, durationMinutes) {
48
+ const o = loadOverrides();
49
+ o.blockAll = on;
50
+ o.allowAll = false;
51
+ o.allowUntil = null;
52
+ o.blockUntil = on && durationMinutes
53
+ ? new Date(Date.now() + durationMinutes * 60_000).toISOString()
54
+ : null;
55
+ saveOverrides(o);
56
+ }
57
+ function setAllowAll(on, durationMinutes) {
58
+ const o = loadOverrides();
59
+ o.allowAll = on;
60
+ o.blockAll = false;
61
+ o.blockUntil = null;
62
+ o.allowUntil = on && durationMinutes
63
+ ? new Date(Date.now() + durationMinutes * 60_000).toISOString()
64
+ : null;
65
+ saveOverrides(o);
66
+ }
67
+ function getOverrideInfo() {
68
+ const o = loadOverrides();
69
+ // Check expiry
70
+ getOverrideState();
71
+ const fresh = loadOverrides();
72
+ return fresh;
73
+ }
74
+ //# sourceMappingURL=overrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overrides.js","sourceRoot":"","sources":["../../src/lib/overrides.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface SessionEvent {
2
+ type: 'tool_use' | 'tool_result' | 'notification' | 'stop' | 'user_message' | 'claude_response';
3
+ toolName?: string;
4
+ filePath?: string;
5
+ summary?: string;
6
+ decision?: string;
7
+ message?: string;
8
+ stopReason?: string;
9
+ timestamp: string;
10
+ }
11
+ export interface Session {
12
+ id: string;
13
+ startedAt: string;
14
+ endedAt?: string;
15
+ events: SessionEvent[];
16
+ stats: {
17
+ tools: number;
18
+ approved: number;
19
+ blocked: number;
20
+ };
21
+ }
22
+ export declare function startSession(): Session;
23
+ export declare function addSessionEvent(event: SessionEvent): void;
24
+ export declare function endSession(): void;
25
+ export declare function getCurrentSession(): Session | null;
26
+ /** List recent sessions (newest first) */
27
+ export declare function listSessions(limit?: number): {
28
+ id: string;
29
+ startedAt: string;
30
+ events: number;
31
+ stats: Session['stats'];
32
+ }[];
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startSession = startSession;
4
+ exports.addSessionEvent = addSessionEvent;
5
+ exports.endSession = endSession;
6
+ exports.getCurrentSession = getCurrentSession;
7
+ exports.listSessions = listSessions;
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ const keys_1 = require("../crypto/keys");
11
+ const SESSIONS_DIR = (0, path_1.join)((0, keys_1.getSentinelDir)(), 'sessions');
12
+ let currentSession = null;
13
+ function startSession() {
14
+ if (!(0, fs_1.existsSync)(SESSIONS_DIR))
15
+ (0, fs_1.mkdirSync)(SESSIONS_DIR, { recursive: true });
16
+ currentSession = {
17
+ id: new Date().toISOString().replace(/[:.]/g, '-'),
18
+ startedAt: new Date().toISOString(),
19
+ events: [],
20
+ stats: { tools: 0, approved: 0, blocked: 0 },
21
+ };
22
+ return currentSession;
23
+ }
24
+ function addSessionEvent(event) {
25
+ if (!currentSession)
26
+ return;
27
+ currentSession.events.push(event);
28
+ if (event.type === 'tool_use')
29
+ currentSession.stats.tools++;
30
+ if (event.decision === 'allowed' || event.decision === 'auto_allow')
31
+ currentSession.stats.approved++;
32
+ if (event.decision === 'blocked')
33
+ currentSession.stats.blocked++;
34
+ }
35
+ function endSession() {
36
+ if (!currentSession)
37
+ return;
38
+ currentSession.endedAt = new Date().toISOString();
39
+ // Save to file
40
+ const path = (0, path_1.join)(SESSIONS_DIR, `${currentSession.id}.json`);
41
+ (0, fs_1.writeFileSync)(path, JSON.stringify(currentSession, null, 2), { mode: 0o600 });
42
+ currentSession = null;
43
+ }
44
+ function getCurrentSession() {
45
+ return currentSession;
46
+ }
47
+ /** List recent sessions (newest first) */
48
+ function listSessions(limit = 10) {
49
+ if (!(0, fs_1.existsSync)(SESSIONS_DIR))
50
+ return [];
51
+ const files = require('fs').readdirSync(SESSIONS_DIR);
52
+ return files
53
+ .filter((f) => f.endsWith('.json'))
54
+ .sort()
55
+ .reverse()
56
+ .slice(0, limit)
57
+ .map((f) => {
58
+ try {
59
+ const s = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(SESSIONS_DIR, f), 'utf-8'));
60
+ return { id: s.id, startedAt: s.startedAt, events: s.events.length, stats: s.stats };
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ })
66
+ .filter(Boolean);
67
+ }
68
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Convert tool call results into human-readable one-line summaries.
3
+ */
4
+ export declare function summarize(toolName: string, toolInput: Record<string, unknown>, toolResponse?: string): string;
5
+ export declare function summarizeStop(reason: string): string;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.summarize = summarize;
4
+ exports.summarizeStop = summarizeStop;
5
+ const path_1 = require("path");
6
+ /**
7
+ * Convert tool call results into human-readable one-line summaries.
8
+ */
9
+ function summarize(toolName, toolInput, toolResponse) {
10
+ const filePath = (toolInput.file_path ?? toolInput.path ?? '');
11
+ const fileName = filePath ? (0, path_1.basename)(filePath) : '';
12
+ const command = (toolInput.command ?? '');
13
+ switch (toolName) {
14
+ case 'Write':
15
+ return `${fileName || 'file'} written`;
16
+ case 'Edit':
17
+ return `${fileName || 'file'} edited`;
18
+ case 'Read':
19
+ return `${fileName || 'file'} read`;
20
+ case 'Bash': {
21
+ const cmd = command.length > 40 ? command.slice(0, 37) + '...' : command;
22
+ const ok = !toolResponse?.includes('error') && !toolResponse?.includes('Error');
23
+ return `${cmd || 'command'}${ok ? '' : ' (error)'}`;
24
+ }
25
+ case 'Glob':
26
+ return `search: ${(toolInput.pattern ?? '*')}`;
27
+ case 'Grep':
28
+ return `grep: ${(toolInput.pattern ?? '')}`;
29
+ case 'WebSearch':
30
+ return `search: ${(toolInput.query ?? '')}`;
31
+ case 'WebFetch':
32
+ return `fetch: ${(toolInput.url ?? '')}`;
33
+ default:
34
+ return `${toolName} completed`;
35
+ }
36
+ }
37
+ function summarizeStop(reason) {
38
+ switch (reason) {
39
+ case 'completed':
40
+ case 'end_turn': return 'Task completed';
41
+ case 'error': return 'Task failed';
42
+ case 'interrupted': return 'Task interrupted';
43
+ default: return `Stopped: ${reason}`;
44
+ }
45
+ }
46
+ //# sourceMappingURL=summarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../src/lib/summarizer.ts"],"names":[],"mappings":";;AAKA,8BA4BC;AAED,sCAOC;AA1CD,+BAAgC;AAEhC;;GAEG;AACH,SAAgB,SAAS,CAAC,QAAgB,EAAE,SAAkC,EAAE,YAAqB;IACnG,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,IAAI,EAAE,CAAW,CAAC;IACzE,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAA,eAAQ,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,OAAO,GAAG,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAW,CAAC;IAEpD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,GAAG,QAAQ,IAAI,MAAM,UAAU,CAAC;QACzC,KAAK,MAAM;YACT,OAAO,GAAG,QAAQ,IAAI,MAAM,SAAS,CAAC;QACxC,KAAK,MAAM;YACT,OAAO,GAAG,QAAQ,IAAI,MAAM,OAAO,CAAC;QACtC,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;YACzE,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChF,OAAO,GAAG,GAAG,IAAI,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QACtD,CAAC;QACD,KAAK,MAAM;YACT,OAAO,WAAW,CAAC,SAAS,CAAC,OAAO,IAAI,GAAG,CAAW,EAAE,CAAC;QAC3D,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAW,EAAE,CAAC;QACxD,KAAK,WAAW;YACd,OAAO,WAAW,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAW,EAAE,CAAC;QACxD,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAW,EAAE,CAAC;QACrD;YACE,OAAO,GAAG,QAAQ,YAAY,CAAC;IACnC,CAAC;AACH,CAAC;AAED,SAAgB,aAAa,CAAC,MAAc;IAC1C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW,CAAC;QAAC,KAAK,UAAU,CAAC,CAAC,OAAO,gBAAgB,CAAC;QAC3D,KAAK,OAAO,CAAC,CAAC,OAAO,aAAa,CAAC;QACnC,KAAK,aAAa,CAAC,CAAC,OAAO,kBAAkB,CAAC;QAC9C,OAAO,CAAC,CAAC,OAAO,YAAY,MAAM,EAAE,CAAC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function startTunnel(port: number): Promise<string>;
2
+ export declare function stopTunnel(): void;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startTunnel = startTunnel;
4
+ exports.stopTunnel = stopTunnel;
5
+ const child_process_1 = require("child_process");
6
+ const logger_1 = require("./logger");
7
+ let tunnelProcess = null;
8
+ async function startTunnel(port) {
9
+ return new Promise((resolve, reject) => {
10
+ const timeout = setTimeout(() => reject(new Error('Tunnel timed out (30s). Is cloudflared installed?')), 30000);
11
+ tunnelProcess = (0, child_process_1.spawn)('cloudflared', ['tunnel', '--url', `tcp://localhost:${port}`, '--no-tls-verify'], {
12
+ stdio: ['ignore', 'pipe', 'pipe'],
13
+ });
14
+ tunnelProcess.on('error', (err) => {
15
+ clearTimeout(timeout);
16
+ if (err.code === 'ENOENT') {
17
+ reject(new Error('cloudflared not found. Install: brew install cloudflared'));
18
+ }
19
+ else {
20
+ reject(err);
21
+ }
22
+ });
23
+ const handleOutput = (data) => {
24
+ const line = data.toString();
25
+ const match = line.match(/https?:\/\/[a-z0-9-]+\.trycloudflare\.com/);
26
+ if (match) {
27
+ clearTimeout(timeout);
28
+ resolve(match[0]);
29
+ }
30
+ };
31
+ tunnelProcess.stdout?.on('data', handleOutput);
32
+ tunnelProcess.stderr?.on('data', handleOutput);
33
+ tunnelProcess.on('exit', (code) => {
34
+ clearTimeout(timeout);
35
+ if (code !== 0 && code !== null) {
36
+ reject(new Error(`cloudflared exited with code ${code}`));
37
+ }
38
+ });
39
+ });
40
+ }
41
+ function stopTunnel() {
42
+ if (tunnelProcess) {
43
+ tunnelProcess.kill();
44
+ tunnelProcess = null;
45
+ logger_1.log.info('Tunnel stopped');
46
+ }
47
+ }
48
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../src/lib/tunnel.ts"],"names":[],"mappings":";;AAKA,kCAoCC;AAED,gCAMC;AAjDD,iDAAoD;AACpD,qCAA+B;AAE/B,IAAI,aAAa,GAAwB,IAAI,CAAC;AAEvC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAEhH,aAAa,GAAG,IAAA,qBAAK,EAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,mBAAmB,IAAI,EAAE,EAAE,iBAAiB,CAAC,EAAE;YACtG,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAChC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,IAAK,GAAW,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACnC,MAAM,CAAC,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;YACtE,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC;QAEF,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC/C,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAE/C,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAChC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,UAAU;IACxB,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,CAAC,IAAI,EAAE,CAAC;QACrB,aAAa,GAAG,IAAI,CAAC;QACrB,YAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,27 @@
1
+ type DecisionAction = 'allowed' | 'blocked' | 'timeout';
2
+ /**
3
+ * 管理等待决策的审批请求
4
+ * 每个请求对应一个 Promise — Socket 收到 decision 事件时 resolve
5
+ */
6
+ declare class PendingStore {
7
+ private requests;
8
+ /**
9
+ * 注册一个等待中的请求,返回 Promise<action>
10
+ * 超时自动 resolve 为 'timeout'
11
+ */
12
+ waitForDecision(requestId: string, toolName: string): Promise<DecisionAction>;
13
+ /**
14
+ * 收到决策时调用 — 从 Socket decision 事件触发
15
+ */
16
+ resolve(requestId: string, action: DecisionAction): void;
17
+ /**
18
+ * 当前等待中的请求数量
19
+ */
20
+ get size(): number;
21
+ /**
22
+ * 清理所有请求(shutdown 时使用)
23
+ */
24
+ clear(): void;
25
+ }
26
+ export declare const pending: PendingStore;
27
+ export {};
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pending = void 0;
4
+ const logger_1 = require("../lib/logger");
5
+ const TIMEOUT_MS = 120_000; // 120s
6
+ /**
7
+ * 管理等待决策的审批请求
8
+ * 每个请求对应一个 Promise — Socket 收到 decision 事件时 resolve
9
+ */
10
+ class PendingStore {
11
+ requests = new Map();
12
+ /**
13
+ * 注册一个等待中的请求,返回 Promise<action>
14
+ * 超时自动 resolve 为 'timeout'
15
+ */
16
+ waitForDecision(requestId, toolName) {
17
+ return new Promise((resolve) => {
18
+ const timer = setTimeout(() => {
19
+ if (this.requests.has(requestId)) {
20
+ this.requests.delete(requestId);
21
+ logger_1.log.warn(`Request ${requestId} timed out (${TIMEOUT_MS / 1000}s)`);
22
+ resolve('timeout');
23
+ }
24
+ }, TIMEOUT_MS);
25
+ this.requests.set(requestId, {
26
+ requestId,
27
+ toolName,
28
+ createdAt: Date.now(),
29
+ resolve,
30
+ timer,
31
+ });
32
+ });
33
+ }
34
+ /**
35
+ * 收到决策时调用 — 从 Socket decision 事件触发
36
+ */
37
+ resolve(requestId, action) {
38
+ const entry = this.requests.get(requestId);
39
+ if (!entry) {
40
+ logger_1.log.debug(`Decision for unknown request: ${requestId}`);
41
+ return;
42
+ }
43
+ clearTimeout(entry.timer);
44
+ this.requests.delete(requestId);
45
+ entry.resolve(action);
46
+ }
47
+ /**
48
+ * 当前等待中的请求数量
49
+ */
50
+ get size() {
51
+ return this.requests.size;
52
+ }
53
+ /**
54
+ * 清理所有请求(shutdown 时使用)
55
+ */
56
+ clear() {
57
+ for (const [, entry] of this.requests) {
58
+ clearTimeout(entry.timer);
59
+ entry.resolve('timeout');
60
+ }
61
+ this.requests.clear();
62
+ }
63
+ }
64
+ exports.pending = new PendingStore();
65
+ //# sourceMappingURL=pending.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/relay/pending.ts"],"names":[],"mappings":";;;AAAA,0CAAoC;AAYpC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,OAAO;AAEnC;;;GAGG;AACH,MAAM,YAAY;IACR,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IAErD;;;OAGG;IACH,eAAe,CAAC,SAAiB,EAAE,QAAgB;QACjD,OAAO,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE;YAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACjC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;oBAChC,YAAG,CAAC,IAAI,CAAC,WAAW,SAAS,eAAe,UAAU,GAAG,IAAI,IAAI,CAAC,CAAC;oBACnE,OAAO,CAAC,SAAS,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC,EAAE,UAAU,CAAC,CAAC;YAEf,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE;gBAC3B,SAAS;gBACT,QAAQ;gBACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,OAAO;gBACP,KAAK;aACN,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,SAAiB,EAAE,MAAsB;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,YAAG,CAAC,KAAK,CAAC,iCAAiC,SAAS,EAAE,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QAED,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF;AAEY,QAAA,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,31 @@
1
+ export type RiskAction = 'auto_allow' | 'require_confirm' | 'require_faceid';
2
+ export interface Rule {
3
+ id: string;
4
+ toolPattern: string | null;
5
+ pathPattern: string | null;
6
+ risk: RiskAction;
7
+ priority: number;
8
+ description: string;
9
+ }
10
+ export interface RuleMatchResult {
11
+ matched: boolean;
12
+ rule: Rule | null;
13
+ action: RiskAction;
14
+ }
15
+ export declare function getRules(): Rule[];
16
+ /** Set custom rules received from iOS (merged with file rules) */
17
+ export declare function setCustomRules(rules: Rule[]): void;
18
+ /** Watch rules.json for changes and auto-reload */
19
+ export declare function watchRules(): void;
20
+ /**
21
+ * 匹配工具调用 against 规则列表
22
+ *
23
+ * @param toolName - 工具名,e.g. "Bash", "Write", "Edit"
24
+ * @param filePath - 文件路径(可选),e.g. "/tmp/foo.txt"
25
+ * @returns - 匹配结果:{ matched, rule, action }
26
+ */
27
+ export declare function matchRules(toolName: string, filePath: string | null): RuleMatchResult;
28
+ /**
29
+ * 将工具调用的风险等级映射为 server riskLevel
30
+ */
31
+ export declare function riskToLevel(action: RiskAction): string;