sentinel-agentos 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.
- package/LICENSE +21 -0
- package/README.md +636 -0
- package/dist/api.d.ts +151 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +179 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +182 -0
- package/dist/cli.js.map +1 -0
- package/dist/core.d.ts +139 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +247 -0
- package/dist/core.js.map +1 -0
- package/dist/evaluator/exec-evaluator.d.ts +102 -0
- package/dist/evaluator/exec-evaluator.d.ts.map +1 -0
- package/dist/evaluator/exec-evaluator.js +266 -0
- package/dist/evaluator/exec-evaluator.js.map +1 -0
- package/dist/evaluator/feedback.d.ts +66 -0
- package/dist/evaluator/feedback.d.ts.map +1 -0
- package/dist/evaluator/feedback.js +195 -0
- package/dist/evaluator/feedback.js.map +1 -0
- package/dist/evaluator/profiler.d.ts +53 -0
- package/dist/evaluator/profiler.d.ts.map +1 -0
- package/dist/evaluator/profiler.js +108 -0
- package/dist/evaluator/profiler.js.map +1 -0
- package/dist/guard/audit-log.d.ts +75 -0
- package/dist/guard/audit-log.d.ts.map +1 -0
- package/dist/guard/audit-log.js +207 -0
- package/dist/guard/audit-log.js.map +1 -0
- package/dist/guard/risk-gate.d.ts +97 -0
- package/dist/guard/risk-gate.d.ts.map +1 -0
- package/dist/guard/risk-gate.js +160 -0
- package/dist/guard/risk-gate.js.map +1 -0
- package/dist/guard/sandbox.d.ts +112 -0
- package/dist/guard/sandbox.d.ts.map +1 -0
- package/dist/guard/sandbox.js +379 -0
- package/dist/guard/sandbox.js.map +1 -0
- package/dist/guard/schema-gate.d.ts +90 -0
- package/dist/guard/schema-gate.d.ts.map +1 -0
- package/dist/guard/schema-gate.js +452 -0
- package/dist/guard/schema-gate.js.map +1 -0
- package/dist/guard/snapshot-verify.d.ts +111 -0
- package/dist/guard/snapshot-verify.d.ts.map +1 -0
- package/dist/guard/snapshot-verify.js +578 -0
- package/dist/guard/snapshot-verify.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/episodic.d.ts +76 -0
- package/dist/memory/episodic.d.ts.map +1 -0
- package/dist/memory/episodic.js +289 -0
- package/dist/memory/episodic.js.map +1 -0
- package/dist/memory/semantic.d.ts +69 -0
- package/dist/memory/semantic.d.ts.map +1 -0
- package/dist/memory/semantic.js +243 -0
- package/dist/memory/semantic.js.map +1 -0
- package/dist/memory/working.d.ts +53 -0
- package/dist/memory/working.d.ts.map +1 -0
- package/dist/memory/working.js +150 -0
- package/dist/memory/working.js.map +1 -0
- package/dist/middleware/openclaw.d.ts +45 -0
- package/dist/middleware/openclaw.d.ts.map +1 -0
- package/dist/middleware/openclaw.js +95 -0
- package/dist/middleware/openclaw.js.map +1 -0
- package/dist/middleware/wrapper.d.ts +54 -0
- package/dist/middleware/wrapper.d.ts.map +1 -0
- package/dist/middleware/wrapper.js +155 -0
- package/dist/middleware/wrapper.js.map +1 -0
- package/dist/server.d.ts +45 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +229 -0
- package/dist/server.js.map +1 -0
- package/dist/types/index.d.ts +201 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentProfiler = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* AgentProfiler — builds and maintains the agent's quality profile.
|
|
6
|
+
*
|
|
7
|
+
* Aggregates PreExec + Runtime + PostExec metrics and
|
|
8
|
+
* ImplicitFeedback to produce a composite quality score
|
|
9
|
+
* that improves over time through self-correction.
|
|
10
|
+
*/
|
|
11
|
+
class AgentProfiler {
|
|
12
|
+
feedbackEngine;
|
|
13
|
+
preMetrics = [];
|
|
14
|
+
runMetrics = [];
|
|
15
|
+
postMetrics = [];
|
|
16
|
+
sessionScores = new Map();
|
|
17
|
+
constructor(feedbackEngine) {
|
|
18
|
+
this.feedbackEngine = feedbackEngine;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Record a complete evaluation cycle for one tool call.
|
|
22
|
+
*/
|
|
23
|
+
recordCycle(sessionId, pre, run, post) {
|
|
24
|
+
this.preMetrics.push(pre);
|
|
25
|
+
this.runMetrics.push(run);
|
|
26
|
+
this.postMetrics.push(post);
|
|
27
|
+
// Track per-session scores
|
|
28
|
+
const sessionScores = this.sessionScores.get(sessionId) ?? [];
|
|
29
|
+
sessionScores.push(post.outcomeScore);
|
|
30
|
+
this.sessionScores.set(sessionId, sessionScores);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build the current agent profile.
|
|
34
|
+
*/
|
|
35
|
+
getProfile(sessionId) {
|
|
36
|
+
const totalOps = this.preMetrics.length;
|
|
37
|
+
// Pre-exec scores
|
|
38
|
+
const preExecScore = this.average(this.preMetrics.map((m) => ((m.paramQuality.score + m.contextUtilization.score) / 2) * 100));
|
|
39
|
+
// Runtime scores
|
|
40
|
+
const runtimeScore = this.average(this.runMetrics.map((m) => m.adaptiveScore * 100));
|
|
41
|
+
// Post-exec scores
|
|
42
|
+
const postExecScore = this.average(this.postMetrics.map((m) => m.outcomeScore * 100));
|
|
43
|
+
// User satisfaction
|
|
44
|
+
const satisfaction = this.feedbackEngine.getSatisfactionScore(sessionId);
|
|
45
|
+
const satisfactionScore = ((satisfaction + 1) / 2) * 100; // Map -1..1 to 0..100
|
|
46
|
+
// Overall: weighted
|
|
47
|
+
const overallScore = Math.round(preExecScore * 0.2 +
|
|
48
|
+
runtimeScore * 0.25 +
|
|
49
|
+
postExecScore * 0.3 +
|
|
50
|
+
satisfactionScore * 0.25);
|
|
51
|
+
// Recent trend
|
|
52
|
+
const recentCutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
53
|
+
const recentPre = this.preMetrics.filter((m) => m.timestamp >= recentCutoff);
|
|
54
|
+
const recentRun = this.runMetrics.slice(-recentPre.length);
|
|
55
|
+
const recentPost = this.postMetrics.slice(-recentPre.length);
|
|
56
|
+
const recentScore = recentPre.length > 0
|
|
57
|
+
? Math.round(this.average(recentPre.map((m) => (m.paramQuality.score + m.contextUtilization.score) / 2)) * 100 * 0.2 +
|
|
58
|
+
this.average(recentRun.map((m) => m.adaptiveScore)) * 100 * 0.25 +
|
|
59
|
+
this.average(recentPost.map((m) => m.outcomeScore)) * 100 * 0.3 +
|
|
60
|
+
satisfactionScore * 0.25)
|
|
61
|
+
: overallScore;
|
|
62
|
+
// Warnings and strengths
|
|
63
|
+
const warnings = [];
|
|
64
|
+
const strengths = [];
|
|
65
|
+
if (runtimeScore < 0.5) {
|
|
66
|
+
warnings.push('High retry rate — consider more planning before execution');
|
|
67
|
+
}
|
|
68
|
+
if (postExecScore < 0.5) {
|
|
69
|
+
warnings.push('Low verify pass rate — verify results before claiming success');
|
|
70
|
+
}
|
|
71
|
+
if (satisfaction < -0.3) {
|
|
72
|
+
warnings.push('User satisfaction declining — review recent sessions');
|
|
73
|
+
}
|
|
74
|
+
if (runtimeScore > 0.9) {
|
|
75
|
+
strengths.push('Excellent execution reliability');
|
|
76
|
+
}
|
|
77
|
+
if (postExecScore > 0.9) {
|
|
78
|
+
strengths.push('Verify gate passing consistently');
|
|
79
|
+
}
|
|
80
|
+
if (satisfaction > 0.5) {
|
|
81
|
+
strengths.push('Strong positive user feedback');
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
overallScore: overallScore, // 0-100
|
|
85
|
+
totalOps,
|
|
86
|
+
breakdown: {
|
|
87
|
+
preExec: Math.round(preExecScore * 100) / 100,
|
|
88
|
+
runtime: Math.round(runtimeScore * 100) / 100,
|
|
89
|
+
postExec: Math.round(postExecScore * 100) / 100,
|
|
90
|
+
userSatisfaction: Math.round(satisfactionScore * 100) / 100,
|
|
91
|
+
},
|
|
92
|
+
trends: {
|
|
93
|
+
improving: recentScore > overallScore,
|
|
94
|
+
recentOps: recentPre.length,
|
|
95
|
+
recentScore: Math.round(recentScore) / 100,
|
|
96
|
+
},
|
|
97
|
+
warnings,
|
|
98
|
+
strengths,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
average(values) {
|
|
102
|
+
return values.length > 0
|
|
103
|
+
? values.reduce((s, v) => s + v, 0) / values.length
|
|
104
|
+
: 0;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.AgentProfiler = AgentProfiler;
|
|
108
|
+
//# sourceMappingURL=profiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../src/evaluator/profiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AuditEntry, VerifyStatus, Snapshot, VerifyCheck } from '../types';
|
|
2
|
+
import { RiskGate } from './risk-gate';
|
|
3
|
+
import { SchemaGate } from './schema-gate';
|
|
4
|
+
/**
|
|
5
|
+
* Audit Log — append-only, immutable operation record.
|
|
6
|
+
*
|
|
7
|
+
* Every tool call that passes through AgentOS Guard gets logged here.
|
|
8
|
+
* The log is an append-only JSONL file — entries are never deleted or modified.
|
|
9
|
+
*
|
|
10
|
+
* In production: use SQLite WAL or a remote append-only service.
|
|
11
|
+
* MVP: flat JSONL file.
|
|
12
|
+
*/
|
|
13
|
+
export declare class AuditLog {
|
|
14
|
+
private logPath;
|
|
15
|
+
private schemaGate;
|
|
16
|
+
private riskGate;
|
|
17
|
+
private snapshotGate;
|
|
18
|
+
constructor(workspaceRoot: string, schemaGate: SchemaGate, riskGate: RiskGate);
|
|
19
|
+
/**
|
|
20
|
+
* Record a tool call in the audit log.
|
|
21
|
+
*
|
|
22
|
+
* Called AFTER execution completes. Returns the full audit entry.
|
|
23
|
+
*/
|
|
24
|
+
record(options: {
|
|
25
|
+
sessionId: string;
|
|
26
|
+
agentId: string;
|
|
27
|
+
startedAt: number;
|
|
28
|
+
completedAt: number;
|
|
29
|
+
toolName: string;
|
|
30
|
+
toolParameters: Record<string, unknown>;
|
|
31
|
+
toolResult: unknown;
|
|
32
|
+
snapshot: Snapshot | null;
|
|
33
|
+
verifyStatus: VerifyStatus;
|
|
34
|
+
verifyChecks: VerifyCheck[];
|
|
35
|
+
}): AuditEntry;
|
|
36
|
+
/**
|
|
37
|
+
* Query audit entries by filter.
|
|
38
|
+
*/
|
|
39
|
+
query(filter?: {
|
|
40
|
+
sessionId?: string;
|
|
41
|
+
toolName?: string;
|
|
42
|
+
verifyStatus?: VerifyStatus;
|
|
43
|
+
minScore?: number;
|
|
44
|
+
maxScore?: number;
|
|
45
|
+
limit?: number;
|
|
46
|
+
}): AuditEntry[];
|
|
47
|
+
/**
|
|
48
|
+
* Get summary statistics from the audit log.
|
|
49
|
+
*/
|
|
50
|
+
stats(): {
|
|
51
|
+
totalOperations: number;
|
|
52
|
+
byTool: Record<string, number>;
|
|
53
|
+
averageRiskScore: number;
|
|
54
|
+
verifyFailures: number;
|
|
55
|
+
sessionsTracked: number;
|
|
56
|
+
highRiskOps: number;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Saintize sensitive parameters before logging.
|
|
60
|
+
*/
|
|
61
|
+
private sanitizeParams;
|
|
62
|
+
/**
|
|
63
|
+
* Truncate large results to prevent log bloat.
|
|
64
|
+
*/
|
|
65
|
+
private truncateResult;
|
|
66
|
+
/**
|
|
67
|
+
* Append an entry to the JSONL audit log file.
|
|
68
|
+
*/
|
|
69
|
+
private append;
|
|
70
|
+
/**
|
|
71
|
+
* Read all audit entries from the log file.
|
|
72
|
+
*/
|
|
73
|
+
private readAll;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=audit-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../src/guard/audit-log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE3E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAY3C;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAe;gBAGjC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ;IAQpB;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACxC,UAAU,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;QAC1B,YAAY,EAAE,YAAY,CAAC;QAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;KAC7B,GAAG,UAAU;IA2Bd;;OAEG;IACH,KAAK,CAAC,MAAM,GAAE;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KACX,GAAG,UAAU,EAAE;IAwBrB;;OAEG;IACH,KAAK,IAAI;QACP,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;KACrB;IA6BD;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,MAAM;IAUd;;OAEG;IACH,OAAO,CAAC,OAAO;CAWhB"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AuditLog = void 0;
|
|
37
|
+
const snapshot_verify_1 = require("./snapshot-verify");
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
/**
|
|
42
|
+
* Generate a unique audit entry ID.
|
|
43
|
+
*/
|
|
44
|
+
function generateAuditId() {
|
|
45
|
+
return `audit_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Audit Log — append-only, immutable operation record.
|
|
49
|
+
*
|
|
50
|
+
* Every tool call that passes through AgentOS Guard gets logged here.
|
|
51
|
+
* The log is an append-only JSONL file — entries are never deleted or modified.
|
|
52
|
+
*
|
|
53
|
+
* In production: use SQLite WAL or a remote append-only service.
|
|
54
|
+
* MVP: flat JSONL file.
|
|
55
|
+
*/
|
|
56
|
+
class AuditLog {
|
|
57
|
+
logPath;
|
|
58
|
+
schemaGate;
|
|
59
|
+
riskGate;
|
|
60
|
+
snapshotGate;
|
|
61
|
+
constructor(workspaceRoot, schemaGate, riskGate) {
|
|
62
|
+
this.logPath = path.join(workspaceRoot, '.agentos', 'audit.jsonl');
|
|
63
|
+
this.schemaGate = schemaGate;
|
|
64
|
+
this.riskGate = riskGate;
|
|
65
|
+
this.snapshotGate = new snapshot_verify_1.SnapshotGate(workspaceRoot);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Record a tool call in the audit log.
|
|
69
|
+
*
|
|
70
|
+
* Called AFTER execution completes. Returns the full audit entry.
|
|
71
|
+
*/
|
|
72
|
+
record(options) {
|
|
73
|
+
const entry = {
|
|
74
|
+
id: generateAuditId(),
|
|
75
|
+
sessionId: options.sessionId,
|
|
76
|
+
agentId: options.agentId,
|
|
77
|
+
startedAt: options.startedAt,
|
|
78
|
+
completedAt: options.completedAt,
|
|
79
|
+
durationMs: options.completedAt - options.startedAt,
|
|
80
|
+
toolName: options.toolName,
|
|
81
|
+
toolParameters: this.sanitizeParams(options.toolParameters),
|
|
82
|
+
toolResult: this.truncateResult(options.toolResult),
|
|
83
|
+
schemaGate: this.schemaGate.check(options.toolName, options.toolParameters),
|
|
84
|
+
riskGate: this.riskGate.evaluate(options.toolName, options.toolParameters),
|
|
85
|
+
snapshot: options.snapshot,
|
|
86
|
+
verifyGate: {
|
|
87
|
+
status: options.verifyStatus,
|
|
88
|
+
checks: options.verifyChecks,
|
|
89
|
+
},
|
|
90
|
+
diff: options.snapshot
|
|
91
|
+
? this.snapshotGate.computeDiff(options.snapshot)
|
|
92
|
+
: null,
|
|
93
|
+
};
|
|
94
|
+
this.append(entry);
|
|
95
|
+
return entry;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Query audit entries by filter.
|
|
99
|
+
*/
|
|
100
|
+
query(filter = {}) {
|
|
101
|
+
const entries = this.readAll();
|
|
102
|
+
let results = entries;
|
|
103
|
+
if (filter.sessionId) {
|
|
104
|
+
results = results.filter((e) => e.sessionId === filter.sessionId);
|
|
105
|
+
}
|
|
106
|
+
if (filter.toolName) {
|
|
107
|
+
results = results.filter((e) => e.toolName === filter.toolName);
|
|
108
|
+
}
|
|
109
|
+
if (filter.verifyStatus) {
|
|
110
|
+
results = results.filter((e) => e.verifyGate.status === filter.verifyStatus);
|
|
111
|
+
}
|
|
112
|
+
if (filter.minScore !== undefined) {
|
|
113
|
+
results = results.filter((e) => e.riskGate.score >= filter.minScore);
|
|
114
|
+
}
|
|
115
|
+
if (filter.maxScore !== undefined) {
|
|
116
|
+
results = results.filter((e) => e.riskGate.score <= filter.maxScore);
|
|
117
|
+
}
|
|
118
|
+
const limit = filter.limit ?? 100;
|
|
119
|
+
return results.slice(-limit);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get summary statistics from the audit log.
|
|
123
|
+
*/
|
|
124
|
+
stats() {
|
|
125
|
+
const entries = this.readAll();
|
|
126
|
+
const byTool = {};
|
|
127
|
+
let totalScore = 0;
|
|
128
|
+
let verifyFailures = 0;
|
|
129
|
+
let highRiskOps = 0;
|
|
130
|
+
const sessions = new Set();
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
byTool[entry.toolName] = (byTool[entry.toolName] || 0) + 1;
|
|
133
|
+
totalScore += entry.riskGate.score;
|
|
134
|
+
if (entry.verifyGate.status === 'FAIL')
|
|
135
|
+
verifyFailures++;
|
|
136
|
+
if (entry.riskGate.score > 3.0)
|
|
137
|
+
highRiskOps++;
|
|
138
|
+
sessions.add(entry.sessionId);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
totalOperations: entries.length,
|
|
142
|
+
byTool,
|
|
143
|
+
averageRiskScore: entries.length > 0
|
|
144
|
+
? Math.round((totalScore / entries.length) * 100) / 100
|
|
145
|
+
: 0,
|
|
146
|
+
verifyFailures,
|
|
147
|
+
sessionsTracked: sessions.size,
|
|
148
|
+
highRiskOps,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Saintize sensitive parameters before logging.
|
|
153
|
+
*/
|
|
154
|
+
sanitizeParams(params) {
|
|
155
|
+
const sensitive = ['token', 'password', 'secret', 'key', 'api_key', 'auth'];
|
|
156
|
+
const sanitized = {};
|
|
157
|
+
for (const [key, value] of Object.entries(params)) {
|
|
158
|
+
if (sensitive.some((s) => key.toLowerCase().includes(s))) {
|
|
159
|
+
sanitized[key] = '***REDACTED***';
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
sanitized[key] = value;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return sanitized;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Truncate large results to prevent log bloat.
|
|
169
|
+
*/
|
|
170
|
+
truncateResult(result, maxChars = 5000) {
|
|
171
|
+
const str = typeof result === 'string'
|
|
172
|
+
? result
|
|
173
|
+
: JSON.stringify(result);
|
|
174
|
+
if (str.length > maxChars) {
|
|
175
|
+
return str.slice(0, maxChars) + `... [truncated ${str.length - maxChars} chars]`;
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Append an entry to the JSONL audit log file.
|
|
181
|
+
*/
|
|
182
|
+
append(entry) {
|
|
183
|
+
const dir = path.dirname(this.logPath);
|
|
184
|
+
if (!fs.existsSync(dir)) {
|
|
185
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
186
|
+
}
|
|
187
|
+
const line = JSON.stringify(entry) + '\n';
|
|
188
|
+
fs.appendFileSync(this.logPath, line, 'utf-8');
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Read all audit entries from the log file.
|
|
192
|
+
*/
|
|
193
|
+
readAll() {
|
|
194
|
+
try {
|
|
195
|
+
if (!fs.existsSync(this.logPath))
|
|
196
|
+
return [];
|
|
197
|
+
const content = fs.readFileSync(this.logPath, 'utf-8');
|
|
198
|
+
const lines = content.split('\n').filter((l) => l.trim());
|
|
199
|
+
return lines.map((l) => JSON.parse(l));
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.AuditLog = AuditLog;
|
|
207
|
+
//# sourceMappingURL=audit-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-log.js","sourceRoot":"","sources":["../../src/guard/audit-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { RiskScore } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Impact level — how broadly the operation affects the system.
|
|
4
|
+
*/
|
|
5
|
+
export type ImpactLevel = 'local' | 'workspace' | 'project' | 'system';
|
|
6
|
+
/**
|
|
7
|
+
* Sensitivity level — how sensitive the data involved is.
|
|
8
|
+
*/
|
|
9
|
+
export type SensitivityLevel = 'none' | 'low' | 'medium' | 'high' | 'critical';
|
|
10
|
+
/**
|
|
11
|
+
* Tool-level risk profile — users define this per tool.
|
|
12
|
+
*/
|
|
13
|
+
export interface ToolRiskProfile {
|
|
14
|
+
/** Tool name to match */
|
|
15
|
+
tool: string;
|
|
16
|
+
/** Impact level of this tool */
|
|
17
|
+
impact: ImpactLevel;
|
|
18
|
+
/** How reversible the operation is (0 = irreversible, 1 = fully reversible) */
|
|
19
|
+
reversibility: number;
|
|
20
|
+
/** Sensitivity of data this tool accesses */
|
|
21
|
+
sensitivity: SensitivityLevel;
|
|
22
|
+
/** Tool category for default error rate */
|
|
23
|
+
category?: 'read' | 'write' | 'delete' | 'network' | 'compute';
|
|
24
|
+
/** Optional override for initial error rate (skips category default) */
|
|
25
|
+
initialErrorRate?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Tool call statistics for dynamic error-rate tracking.
|
|
29
|
+
*/
|
|
30
|
+
interface ToolStats {
|
|
31
|
+
totalCalls: number;
|
|
32
|
+
failures: number;
|
|
33
|
+
errorRate: number;
|
|
34
|
+
lastUpdated: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Threshold configuration for risk-based actions.
|
|
38
|
+
*/
|
|
39
|
+
export interface RiskThresholds {
|
|
40
|
+
/** Score ≤ autoApprove → execute immediately */
|
|
41
|
+
autoApprove: number;
|
|
42
|
+
/** Score ≤ notify → execute but notify user */
|
|
43
|
+
notify: number;
|
|
44
|
+
/** Score ≤ confirm → pause and ask for user confirmation */
|
|
45
|
+
confirm: number;
|
|
46
|
+
/** Score > deny → block entirely */
|
|
47
|
+
deny: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Default thresholds — conservative but workable.
|
|
51
|
+
*/
|
|
52
|
+
export declare const DEFAULT_RISK_THRESHOLDS: RiskThresholds;
|
|
53
|
+
/**
|
|
54
|
+
* Risk Gate — deterministic, pure-math risk scoring.
|
|
55
|
+
*
|
|
56
|
+
* Formula: RiskScore = Impact × (1 - Reversibility) × Sensitivity × (1 + ErrorRate)
|
|
57
|
+
*
|
|
58
|
+
* Zero LLM dependency. The formula, thresholds, and mappings are all
|
|
59
|
+
* explicit and auditable.
|
|
60
|
+
*/
|
|
61
|
+
export declare class RiskGate {
|
|
62
|
+
private profiles;
|
|
63
|
+
private stats;
|
|
64
|
+
private thresholds;
|
|
65
|
+
constructor(thresholds?: RiskThresholds);
|
|
66
|
+
/** Register a risk profile for a tool */
|
|
67
|
+
registerProfile(profile: ToolRiskProfile): void;
|
|
68
|
+
/** Register multiple profiles at once */
|
|
69
|
+
registerProfiles(profiles: ToolRiskProfile[]): void;
|
|
70
|
+
/** Get all registered profiles */
|
|
71
|
+
getProfiles(): ToolRiskProfile[];
|
|
72
|
+
/** Check if a tool has a registered profile */
|
|
73
|
+
hasProfile(tool: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Compute the risk score for a tool call.
|
|
76
|
+
*
|
|
77
|
+
* If no profile is registered, returns a default moderate-risk score
|
|
78
|
+
* (auto-approve with notification).
|
|
79
|
+
*/
|
|
80
|
+
evaluate(tool: string, _params?: Record<string, unknown>): RiskScore;
|
|
81
|
+
/** Record the outcome of a tool call to update stats */
|
|
82
|
+
recordOutcome(tool: string, success: boolean): void;
|
|
83
|
+
/** Get tool statistics */
|
|
84
|
+
getStats(tool: string): ToolStats | undefined;
|
|
85
|
+
/** Get all tool statistics */
|
|
86
|
+
getAllStats(): Map<string, ToolStats>;
|
|
87
|
+
/** Update thresholds at runtime */
|
|
88
|
+
setThresholds(thresholds: Partial<RiskThresholds>): void;
|
|
89
|
+
/** Get current thresholds */
|
|
90
|
+
getThresholds(): RiskThresholds;
|
|
91
|
+
/**
|
|
92
|
+
* Map a numeric risk score to the appropriate action.
|
|
93
|
+
*/
|
|
94
|
+
private scoreToAction;
|
|
95
|
+
}
|
|
96
|
+
export {};
|
|
97
|
+
//# sourceMappingURL=risk-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-gate.d.ts","sourceRoot":"","sources":["../../src/guard/risk-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AASvE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAqB/E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,WAAW,EAAE,gBAAgB,CAAC;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC/D,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,UAAU,SAAS;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAKrC,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,UAAU,CAAiB;gBAEvB,UAAU,GAAE,cAAwC;IAIhE,yCAAyC;IACzC,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAgB/C,yCAAyC;IACzC,gBAAgB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,IAAI;IAInD,kCAAkC;IAClC,WAAW,IAAI,eAAe,EAAE;IAIhC,+CAA+C;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAyCpE,wDAAwD;IACxD,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAWnD,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI7C,8BAA8B;IAC9B,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IAIrC,mCAAmC;IACnC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAIxD,6BAA6B;IAC7B,aAAa,IAAI,cAAc;IAI/B;;OAEG;IACH,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RiskGate = exports.DEFAULT_RISK_THRESHOLDS = void 0;
|
|
4
|
+
const IMPACT_VALUES = {
|
|
5
|
+
local: 1,
|
|
6
|
+
workspace: 3,
|
|
7
|
+
project: 6,
|
|
8
|
+
system: 10,
|
|
9
|
+
};
|
|
10
|
+
const SENSITIVITY_VALUES = {
|
|
11
|
+
none: 0.0,
|
|
12
|
+
low: 0.3,
|
|
13
|
+
medium: 0.6,
|
|
14
|
+
high: 0.9,
|
|
15
|
+
critical: 1.0,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Default error rates by tool category (cold start).
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_ERROR_RATES = {
|
|
21
|
+
read: 0.01,
|
|
22
|
+
write: 0.05,
|
|
23
|
+
delete: 0.10,
|
|
24
|
+
network: 0.08,
|
|
25
|
+
compute: 0.02,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Default thresholds — conservative but workable.
|
|
29
|
+
*/
|
|
30
|
+
exports.DEFAULT_RISK_THRESHOLDS = {
|
|
31
|
+
autoApprove: 0.5,
|
|
32
|
+
notify: 1.0,
|
|
33
|
+
confirm: 3.0,
|
|
34
|
+
deny: 8.0,
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Risk Gate — deterministic, pure-math risk scoring.
|
|
38
|
+
*
|
|
39
|
+
* Formula: RiskScore = Impact × (1 - Reversibility) × Sensitivity × (1 + ErrorRate)
|
|
40
|
+
*
|
|
41
|
+
* Zero LLM dependency. The formula, thresholds, and mappings are all
|
|
42
|
+
* explicit and auditable.
|
|
43
|
+
*/
|
|
44
|
+
class RiskGate {
|
|
45
|
+
profiles = new Map();
|
|
46
|
+
stats = new Map();
|
|
47
|
+
thresholds;
|
|
48
|
+
constructor(thresholds = exports.DEFAULT_RISK_THRESHOLDS) {
|
|
49
|
+
this.thresholds = thresholds;
|
|
50
|
+
}
|
|
51
|
+
/** Register a risk profile for a tool */
|
|
52
|
+
registerProfile(profile) {
|
|
53
|
+
this.profiles.set(profile.tool, profile);
|
|
54
|
+
// Initialize stats if not already tracked
|
|
55
|
+
if (!this.stats.has(profile.tool)) {
|
|
56
|
+
const errorRate = profile.initialErrorRate ??
|
|
57
|
+
(profile.category ? (DEFAULT_ERROR_RATES[profile.category] ?? 0.05) : 0.05);
|
|
58
|
+
this.stats.set(profile.tool, {
|
|
59
|
+
totalCalls: 0,
|
|
60
|
+
failures: 0,
|
|
61
|
+
errorRate,
|
|
62
|
+
lastUpdated: Date.now(),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Register multiple profiles at once */
|
|
67
|
+
registerProfiles(profiles) {
|
|
68
|
+
profiles.forEach((p) => this.registerProfile(p));
|
|
69
|
+
}
|
|
70
|
+
/** Get all registered profiles */
|
|
71
|
+
getProfiles() {
|
|
72
|
+
return Array.from(this.profiles.values());
|
|
73
|
+
}
|
|
74
|
+
/** Check if a tool has a registered profile */
|
|
75
|
+
hasProfile(tool) {
|
|
76
|
+
return this.profiles.has(tool);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Compute the risk score for a tool call.
|
|
80
|
+
*
|
|
81
|
+
* If no profile is registered, returns a default moderate-risk score
|
|
82
|
+
* (auto-approve with notification).
|
|
83
|
+
*/
|
|
84
|
+
evaluate(tool, _params) {
|
|
85
|
+
const profile = this.profiles.get(tool);
|
|
86
|
+
// Fallback for unregistered tools — moderate risk, allow but notify
|
|
87
|
+
if (!profile) {
|
|
88
|
+
const fallbackScore = this.thresholds.autoApprove + 0.1;
|
|
89
|
+
return {
|
|
90
|
+
score: fallbackScore,
|
|
91
|
+
action: 'auto',
|
|
92
|
+
dimensions: {
|
|
93
|
+
impact: 1,
|
|
94
|
+
reversibility: 1,
|
|
95
|
+
sensitivity: 0,
|
|
96
|
+
errorRate: 0,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const impact = IMPACT_VALUES[profile.impact];
|
|
101
|
+
const reversibility = Math.min(1, Math.max(0, profile.reversibility));
|
|
102
|
+
const sensitivity = SENSITIVITY_VALUES[profile.sensitivity];
|
|
103
|
+
const stats = this.stats.get(profile.tool);
|
|
104
|
+
const errorRate = stats?.errorRate ?? 0.05;
|
|
105
|
+
const score = impact * (1 - reversibility) * sensitivity * (1 + errorRate);
|
|
106
|
+
const action = this.scoreToAction(score);
|
|
107
|
+
return {
|
|
108
|
+
score: Math.round(score * 100) / 100, // round to 2 decimal places
|
|
109
|
+
action,
|
|
110
|
+
dimensions: {
|
|
111
|
+
impact,
|
|
112
|
+
reversibility,
|
|
113
|
+
sensitivity,
|
|
114
|
+
errorRate: Math.round(errorRate * 1000) / 1000,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Record the outcome of a tool call to update stats */
|
|
119
|
+
recordOutcome(tool, success) {
|
|
120
|
+
const stats = this.stats.get(tool);
|
|
121
|
+
if (!stats)
|
|
122
|
+
return;
|
|
123
|
+
stats.totalCalls++;
|
|
124
|
+
if (!success)
|
|
125
|
+
stats.failures++;
|
|
126
|
+
stats.errorRate =
|
|
127
|
+
stats.totalCalls > 0 ? stats.failures / stats.totalCalls : 0;
|
|
128
|
+
stats.lastUpdated = Date.now();
|
|
129
|
+
}
|
|
130
|
+
/** Get tool statistics */
|
|
131
|
+
getStats(tool) {
|
|
132
|
+
return this.stats.get(tool);
|
|
133
|
+
}
|
|
134
|
+
/** Get all tool statistics */
|
|
135
|
+
getAllStats() {
|
|
136
|
+
return new Map(this.stats);
|
|
137
|
+
}
|
|
138
|
+
/** Update thresholds at runtime */
|
|
139
|
+
setThresholds(thresholds) {
|
|
140
|
+
this.thresholds = { ...this.thresholds, ...thresholds };
|
|
141
|
+
}
|
|
142
|
+
/** Get current thresholds */
|
|
143
|
+
getThresholds() {
|
|
144
|
+
return { ...this.thresholds };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Map a numeric risk score to the appropriate action.
|
|
148
|
+
*/
|
|
149
|
+
scoreToAction(score) {
|
|
150
|
+
if (score <= this.thresholds.autoApprove)
|
|
151
|
+
return 'auto';
|
|
152
|
+
if (score <= this.thresholds.notify)
|
|
153
|
+
return 'notify';
|
|
154
|
+
if (score <= this.thresholds.confirm)
|
|
155
|
+
return 'confirm';
|
|
156
|
+
return 'deny';
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.RiskGate = RiskGate;
|
|
160
|
+
//# sourceMappingURL=risk-gate.js.map
|