@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.
- package/dist/__tests__/rules-engine.test.d.ts +1 -0
- package/dist/__tests__/rules-engine.test.js +69 -0
- package/dist/__tests__/rules-engine.test.js.map +1 -0
- package/dist/__tests__/transport-encryption.test.d.ts +1 -0
- package/dist/__tests__/transport-encryption.test.js +95 -0
- package/dist/__tests__/transport-encryption.test.js.map +1 -0
- package/dist/api/client.d.ts +27 -0
- package/dist/api/client.js +91 -0
- package/dist/api/client.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +12 -0
- package/dist/cli/bootstrap.js +132 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +534 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/crypto/keys.d.ts +40 -0
- package/dist/crypto/keys.js +125 -0
- package/dist/crypto/keys.js.map +1 -0
- package/dist/crypto/transport-encryption.d.ts +13 -0
- package/dist/crypto/transport-encryption.js +62 -0
- package/dist/crypto/transport-encryption.js.map +1 -0
- package/dist/install/setup.d.ts +2 -0
- package/dist/install/setup.js +80 -0
- package/dist/install/setup.js.map +1 -0
- package/dist/lib/budget.d.ts +14 -0
- package/dist/lib/budget.js +93 -0
- package/dist/lib/budget.js.map +1 -0
- package/dist/lib/claude-process.d.ts +16 -0
- package/dist/lib/claude-process.js +98 -0
- package/dist/lib/claude-process.js.map +1 -0
- package/dist/lib/daemon.d.ts +6 -0
- package/dist/lib/daemon.js +218 -0
- package/dist/lib/daemon.js.map +1 -0
- package/dist/lib/diff.d.ts +5 -0
- package/dist/lib/diff.js +85 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/doctor.d.ts +1 -0
- package/dist/lib/doctor.js +108 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/history.d.ts +22 -0
- package/dist/lib/history.js +62 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/logger.d.ts +11 -0
- package/dist/lib/logger.js +62 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/modes.d.ts +22 -0
- package/dist/lib/modes.js +58 -0
- package/dist/lib/modes.js.map +1 -0
- package/dist/lib/overrides.d.ts +13 -0
- package/dist/lib/overrides.js +74 -0
- package/dist/lib/overrides.js.map +1 -0
- package/dist/lib/session.d.ts +32 -0
- package/dist/lib/session.js +68 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/summarizer.d.ts +5 -0
- package/dist/lib/summarizer.js +46 -0
- package/dist/lib/summarizer.js.map +1 -0
- package/dist/lib/tunnel.d.ts +2 -0
- package/dist/lib/tunnel.js +48 -0
- package/dist/lib/tunnel.js.map +1 -0
- package/dist/relay/pending.d.ts +27 -0
- package/dist/relay/pending.js +65 -0
- package/dist/relay/pending.js.map +1 -0
- package/dist/rules/engine.d.ts +31 -0
- package/dist/rules/engine.js +203 -0
- package/dist/rules/engine.js.map +1 -0
- package/dist/server/http.d.ts +8 -0
- package/dist/server/http.js +359 -0
- package/dist/server/http.js.map +1 -0
- package/dist/socket/client.d.ts +16 -0
- package/dist/socket/client.js +81 -0
- package/dist/socket/client.js.map +1 -0
- package/dist/transport/cloudkit.d.ts +30 -0
- package/dist/transport/cloudkit.js +162 -0
- package/dist/transport/cloudkit.js.map +1 -0
- package/dist/transport/factory.d.ts +6 -0
- package/dist/transport/factory.js +20 -0
- package/dist/transport/factory.js.map +1 -0
- package/dist/transport/interface.d.ts +25 -0
- package/dist/transport/interface.js +13 -0
- package/dist/transport/interface.js.map +1 -0
- package/dist/transport/local.d.ts +46 -0
- package/dist/transport/local.js +320 -0
- package/dist/transport/local.js.map +1 -0
- package/dist/transport/remote.d.ts +17 -0
- package/dist/transport/remote.js +83 -0
- package/dist/transport/remote.js.map +1 -0
- 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,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,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;
|