@weaveaijs/mcp-observatory 0.3.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 +201 -0
- package/README.md +322 -0
- package/dist/core/context.d.ts +46 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +38 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/tracer.d.ts +17 -0
- package/dist/core/tracer.d.ts.map +1 -0
- package/dist/core/tracer.js +29 -0
- package/dist/core/tracer.js.map +1 -0
- package/dist/core/wrapper.d.ts +34 -0
- package/dist/core/wrapper.d.ts.map +1 -0
- package/dist/core/wrapper.js +93 -0
- package/dist/core/wrapper.js.map +1 -0
- package/dist/cost/pricing.d.ts +6 -0
- package/dist/cost/pricing.d.ts.map +1 -0
- package/dist/cost/pricing.js +21 -0
- package/dist/cost/pricing.js.map +1 -0
- package/dist/cost/tokenizer.d.ts +7 -0
- package/dist/cost/tokenizer.d.ts.map +1 -0
- package/dist/cost/tokenizer.js +25 -0
- package/dist/cost/tokenizer.js.map +1 -0
- package/dist/demo/client.d.ts +18 -0
- package/dist/demo/client.d.ts.map +1 -0
- package/dist/demo/client.js +57 -0
- package/dist/demo/client.js.map +1 -0
- package/dist/demo/runDemo.d.ts +2 -0
- package/dist/demo/runDemo.d.ts.map +1 -0
- package/dist/demo/runDemo.js +15 -0
- package/dist/demo/runDemo.js.map +1 -0
- package/dist/demo/server.d.ts +19 -0
- package/dist/demo/server.d.ts.map +1 -0
- package/dist/demo/server.js +100 -0
- package/dist/demo/server.js.map +1 -0
- package/dist/hallucination/scoring.d.ts +14 -0
- package/dist/hallucination/scoring.d.ts.map +1 -0
- package/dist/hallucination/scoring.js +67 -0
- package/dist/hallucination/scoring.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/proposal/proposer.d.ts +30 -0
- package/dist/proposal/proposer.d.ts.map +1 -0
- package/dist/proposal/proposer.js +73 -0
- package/dist/proposal/proposer.js.map +1 -0
- package/dist/proposal/storage.d.ts +38 -0
- package/dist/proposal/storage.d.ts.map +1 -0
- package/dist/proposal/storage.js +115 -0
- package/dist/proposal/storage.js.map +1 -0
- package/dist/proposal/token.d.ts +34 -0
- package/dist/proposal/token.d.ts.map +1 -0
- package/dist/proposal/token.js +52 -0
- package/dist/proposal/token.js.map +1 -0
- package/dist/proposal/verifier.d.ts +20 -0
- package/dist/proposal/verifier.d.ts.map +1 -0
- package/dist/proposal/verifier.js +34 -0
- package/dist/proposal/verifier.js.map +1 -0
- package/dist/risk/scoring.d.ts +11 -0
- package/dist/risk/scoring.d.ts.map +1 -0
- package/dist/risk/scoring.js +54 -0
- package/dist/risk/scoring.js.map +1 -0
- package/dist/tests/hashing.test.d.ts +2 -0
- package/dist/tests/hashing.test.d.ts.map +1 -0
- package/dist/tests/hashing.test.js +39 -0
- package/dist/tests/hashing.test.js.map +1 -0
- package/dist/tests/proposer.test.d.ts +2 -0
- package/dist/tests/proposer.test.d.ts.map +1 -0
- package/dist/tests/proposer.test.js +49 -0
- package/dist/tests/proposer.test.js.map +1 -0
- package/dist/tests/scoring.test.d.ts +2 -0
- package/dist/tests/scoring.test.d.ts.map +1 -0
- package/dist/tests/scoring.test.js +41 -0
- package/dist/tests/scoring.test.js.map +1 -0
- package/dist/tests/token.test.d.ts +2 -0
- package/dist/tests/token.test.d.ts.map +1 -0
- package/dist/tests/token.test.js +51 -0
- package/dist/tests/token.test.js.map +1 -0
- package/dist/tests/tracer.test.d.ts +2 -0
- package/dist/tests/tracer.test.d.ts.map +1 -0
- package/dist/tests/tracer.test.js +38 -0
- package/dist/tests/tracer.test.js.map +1 -0
- package/dist/utils/hashing.d.ts +5 -0
- package/dist/utils/hashing.d.ts.map +1 -0
- package/dist/utils/hashing.js +18 -0
- package/dist/utils/hashing.js.map +1 -0
- package/dist/utils/time.d.ts +6 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +22 -0
- package/dist/utils/time.js.map +1 -0
- package/package.json +63 -0
- package/sql/schema.sql +73 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { TokenManager } from './token.js';
|
|
2
|
+
export interface ProposalOptions {
|
|
3
|
+
toolName: string;
|
|
4
|
+
toolArgs: Record<string, unknown>;
|
|
5
|
+
outputInstability?: number;
|
|
6
|
+
numericVariance?: number;
|
|
7
|
+
promptDrift?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ProposalResult {
|
|
10
|
+
proposalId: string;
|
|
11
|
+
status: 'allowed' | 'blocked' | 'review';
|
|
12
|
+
reason?: string;
|
|
13
|
+
commitToken?: string;
|
|
14
|
+
fallbackResponse?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface ScoringOptions {
|
|
17
|
+
outputInstability?: number;
|
|
18
|
+
numericVariance?: number;
|
|
19
|
+
promptDrift?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class ToolProposer {
|
|
22
|
+
private tokenManager;
|
|
23
|
+
private blockThreshold;
|
|
24
|
+
private reviewThreshold;
|
|
25
|
+
constructor(tokenManager?: TokenManager);
|
|
26
|
+
propose(options: ProposalOptions): Promise<ProposalResult>;
|
|
27
|
+
private computeCompositeScore;
|
|
28
|
+
private deterministicFallback;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=proposer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposer.d.ts","sourceRoot":"","sources":["../../src/proposal/proposer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,cAAc,CAAe;IACrC,OAAO,CAAC,eAAe,CAAe;gBAE1B,YAAY,CAAC,EAAE,YAAY;IAIjC,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IA+ChE,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,qBAAqB;CAW9B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { hashJson } from '../utils/hashing.js';
|
|
3
|
+
import { TokenManager } from './token.js';
|
|
4
|
+
export class ToolProposer {
|
|
5
|
+
constructor(tokenManager) {
|
|
6
|
+
this.blockThreshold = 0.7;
|
|
7
|
+
this.reviewThreshold = 0.4;
|
|
8
|
+
this.tokenManager = tokenManager || new TokenManager();
|
|
9
|
+
}
|
|
10
|
+
async propose(options) {
|
|
11
|
+
const proposalId = randomUUID();
|
|
12
|
+
const toolArgsHash = hashJson(options.toolArgs);
|
|
13
|
+
const compositeScore = this.computeCompositeScore({
|
|
14
|
+
outputInstability: options.outputInstability,
|
|
15
|
+
numericVariance: options.numericVariance,
|
|
16
|
+
promptDrift: options.promptDrift,
|
|
17
|
+
});
|
|
18
|
+
if (compositeScore > this.blockThreshold) {
|
|
19
|
+
return {
|
|
20
|
+
proposalId,
|
|
21
|
+
status: 'blocked',
|
|
22
|
+
reason: 'low_integrity',
|
|
23
|
+
fallbackResponse: this.deterministicFallback(options.toolName, options.toolArgs),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (compositeScore > this.reviewThreshold) {
|
|
27
|
+
const { token } = this.tokenManager.issueToken({
|
|
28
|
+
proposalId,
|
|
29
|
+
toolName: options.toolName,
|
|
30
|
+
toolArgsHash,
|
|
31
|
+
compositeScore,
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
proposalId,
|
|
35
|
+
status: 'review',
|
|
36
|
+
commitToken: token,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const { token } = this.tokenManager.issueToken({
|
|
40
|
+
proposalId,
|
|
41
|
+
toolName: options.toolName,
|
|
42
|
+
toolArgsHash,
|
|
43
|
+
compositeScore,
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
proposalId,
|
|
47
|
+
status: 'allowed',
|
|
48
|
+
commitToken: token,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
computeCompositeScore(scoring) {
|
|
52
|
+
const instability = Math.max(0, Math.min(1, scoring.outputInstability || 0));
|
|
53
|
+
const variance = Math.max(0, Math.min(1, scoring.numericVariance || 0));
|
|
54
|
+
const drift = Math.max(0, Math.min(1, scoring.promptDrift || 0));
|
|
55
|
+
const weights = {
|
|
56
|
+
instability: 0.5,
|
|
57
|
+
variance: 0.3,
|
|
58
|
+
drift: 0.2,
|
|
59
|
+
};
|
|
60
|
+
return (instability * weights.instability +
|
|
61
|
+
variance * weights.variance +
|
|
62
|
+
drift * weights.drift);
|
|
63
|
+
}
|
|
64
|
+
deterministicFallback(toolName, toolArgs) {
|
|
65
|
+
return {
|
|
66
|
+
status: 'blocked',
|
|
67
|
+
action: 'create_draft',
|
|
68
|
+
reason: 'low_integrity',
|
|
69
|
+
draft: { tool: toolName, ...toolArgs },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=proposer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposer.js","sourceRoot":"","sources":["../../src/proposal/proposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Proposal {
|
|
2
|
+
id: string;
|
|
3
|
+
toolName: string;
|
|
4
|
+
toolArgsHash: string;
|
|
5
|
+
status: 'allowed' | 'blocked' | 'review';
|
|
6
|
+
createdAt: Date;
|
|
7
|
+
expiresAt: Date;
|
|
8
|
+
}
|
|
9
|
+
export interface Commit {
|
|
10
|
+
id: string;
|
|
11
|
+
proposalId: string;
|
|
12
|
+
executed: boolean;
|
|
13
|
+
executedAt?: Date;
|
|
14
|
+
}
|
|
15
|
+
export declare class InMemoryProposalStorage {
|
|
16
|
+
private proposals;
|
|
17
|
+
private commits;
|
|
18
|
+
saveProposal(proposal: Proposal): Promise<void>;
|
|
19
|
+
getProposal(id: string): Promise<Proposal | null>;
|
|
20
|
+
saveCommit(commit: Commit): Promise<void>;
|
|
21
|
+
getCommit(id: string): Promise<Commit | null>;
|
|
22
|
+
saveNonce(nonce: string): Promise<void>;
|
|
23
|
+
hasNonce(nonce: string): Promise<boolean>;
|
|
24
|
+
cleanup(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare class PostgresProposalStorage {
|
|
27
|
+
private pool;
|
|
28
|
+
constructor(dsn: string);
|
|
29
|
+
saveProposal(proposal: Proposal): Promise<void>;
|
|
30
|
+
getProposal(id: string): Promise<Proposal | null>;
|
|
31
|
+
saveCommit(commit: Commit): Promise<void>;
|
|
32
|
+
getCommit(id: string): Promise<Commit | null>;
|
|
33
|
+
saveNonce(nonce: string): Promise<void>;
|
|
34
|
+
hasNonce(nonce: string): Promise<boolean>;
|
|
35
|
+
cleanup(): Promise<void>;
|
|
36
|
+
close(): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/proposal/storage.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,IAAI,CAAC;CACnB;AAED,qBAAa,uBAAuB;IAClC,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,OAAO,CAAkC;IAE3C,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAYjD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI7C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ/B;AAED,qBAAa,uBAAuB;IAClC,OAAO,CAAC,IAAI,CAAO;gBAEP,GAAG,EAAE,MAAM;IAIjB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/C,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAiBjD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAazC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAY7C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOzC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Pool } from 'pg';
|
|
2
|
+
export class InMemoryProposalStorage {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.proposals = new Map();
|
|
5
|
+
this.commits = new Map();
|
|
6
|
+
}
|
|
7
|
+
async saveProposal(proposal) {
|
|
8
|
+
this.proposals.set(proposal.id, proposal);
|
|
9
|
+
}
|
|
10
|
+
async getProposal(id) {
|
|
11
|
+
const proposal = this.proposals.get(id);
|
|
12
|
+
if (!proposal)
|
|
13
|
+
return null;
|
|
14
|
+
if (proposal.expiresAt < new Date()) {
|
|
15
|
+
this.proposals.delete(id);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return proposal;
|
|
19
|
+
}
|
|
20
|
+
async saveCommit(commit) {
|
|
21
|
+
this.commits.set(commit.id, commit);
|
|
22
|
+
}
|
|
23
|
+
async getCommit(id) {
|
|
24
|
+
return this.commits.get(id) || null;
|
|
25
|
+
}
|
|
26
|
+
async saveNonce(nonce) {
|
|
27
|
+
// In-memory storage for nonce tracking
|
|
28
|
+
}
|
|
29
|
+
async hasNonce(nonce) {
|
|
30
|
+
// Would need separate nonce tracking
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
async cleanup() {
|
|
34
|
+
const now = new Date();
|
|
35
|
+
for (const [id, proposal] of this.proposals.entries()) {
|
|
36
|
+
if (proposal.expiresAt < now) {
|
|
37
|
+
this.proposals.delete(id);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export class PostgresProposalStorage {
|
|
43
|
+
constructor(dsn) {
|
|
44
|
+
this.pool = new Pool({ connectionString: dsn });
|
|
45
|
+
}
|
|
46
|
+
async saveProposal(proposal) {
|
|
47
|
+
const query = `
|
|
48
|
+
INSERT INTO proposals (id, tool_name, tool_args_hash, status, created_at, expires_at)
|
|
49
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
50
|
+
ON CONFLICT (id) DO UPDATE SET status = $4, expires_at = $6
|
|
51
|
+
`;
|
|
52
|
+
await this.pool.query(query, [
|
|
53
|
+
proposal.id,
|
|
54
|
+
proposal.toolName,
|
|
55
|
+
proposal.toolArgsHash,
|
|
56
|
+
proposal.status,
|
|
57
|
+
proposal.createdAt,
|
|
58
|
+
proposal.expiresAt,
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
async getProposal(id) {
|
|
62
|
+
const result = await this.pool.query('SELECT * FROM proposals WHERE id = $1 AND expires_at > NOW()', [id]);
|
|
63
|
+
if (result.rows.length === 0)
|
|
64
|
+
return null;
|
|
65
|
+
const row = result.rows[0];
|
|
66
|
+
return {
|
|
67
|
+
id: row.id,
|
|
68
|
+
toolName: row.tool_name,
|
|
69
|
+
toolArgsHash: row.tool_args_hash,
|
|
70
|
+
status: row.status,
|
|
71
|
+
createdAt: row.created_at,
|
|
72
|
+
expiresAt: row.expires_at,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async saveCommit(commit) {
|
|
76
|
+
const query = `
|
|
77
|
+
INSERT INTO commits (id, proposal_id, executed, executed_at)
|
|
78
|
+
VALUES ($1, $2, $3, $4)
|
|
79
|
+
`;
|
|
80
|
+
await this.pool.query(query, [
|
|
81
|
+
commit.id,
|
|
82
|
+
commit.proposalId,
|
|
83
|
+
commit.executed,
|
|
84
|
+
commit.executedAt,
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
async getCommit(id) {
|
|
88
|
+
const result = await this.pool.query('SELECT * FROM commits WHERE id = $1', [id]);
|
|
89
|
+
if (result.rows.length === 0)
|
|
90
|
+
return null;
|
|
91
|
+
const row = result.rows[0];
|
|
92
|
+
return {
|
|
93
|
+
id: row.id,
|
|
94
|
+
proposalId: row.proposal_id,
|
|
95
|
+
executed: row.executed,
|
|
96
|
+
executedAt: row.executed_at,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
async saveNonce(nonce) {
|
|
100
|
+
await this.pool.query('INSERT INTO nonces (nonce, created_at) VALUES ($1, NOW())', [nonce]);
|
|
101
|
+
}
|
|
102
|
+
async hasNonce(nonce) {
|
|
103
|
+
const result = await this.pool.query('SELECT 1 FROM nonces WHERE nonce = $1', [
|
|
104
|
+
nonce,
|
|
105
|
+
]);
|
|
106
|
+
return result.rows.length > 0;
|
|
107
|
+
}
|
|
108
|
+
async cleanup() {
|
|
109
|
+
await this.pool.query('DELETE FROM proposals WHERE expires_at < NOW()');
|
|
110
|
+
}
|
|
111
|
+
async close() {
|
|
112
|
+
await this.pool.end();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/proposal/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface TokenPayload {
|
|
2
|
+
tokenId: string;
|
|
3
|
+
proposalId: string;
|
|
4
|
+
toolName: string;
|
|
5
|
+
toolArgsHash: string;
|
|
6
|
+
issuedAt: number;
|
|
7
|
+
expiresAt: number;
|
|
8
|
+
nonce: string;
|
|
9
|
+
compositeScore: number;
|
|
10
|
+
}
|
|
11
|
+
export interface TokenVerificationResult {
|
|
12
|
+
valid: boolean;
|
|
13
|
+
reason?: string;
|
|
14
|
+
payload?: TokenPayload;
|
|
15
|
+
}
|
|
16
|
+
export declare class TokenManager {
|
|
17
|
+
private secret;
|
|
18
|
+
private tokenExpiryMs;
|
|
19
|
+
constructor(secret?: string);
|
|
20
|
+
issueToken(options: {
|
|
21
|
+
proposalId: string;
|
|
22
|
+
toolName: string;
|
|
23
|
+
toolArgsHash: string;
|
|
24
|
+
compositeScore: number;
|
|
25
|
+
expiryMs?: number;
|
|
26
|
+
}): {
|
|
27
|
+
token: string;
|
|
28
|
+
payload: TokenPayload;
|
|
29
|
+
};
|
|
30
|
+
verifyToken(token: string): TokenVerificationResult;
|
|
31
|
+
private sign;
|
|
32
|
+
private randomId;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/proposal/token.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAkB;gBAE3B,MAAM,CAAC,EAAE,MAAM;IAI3B,UAAU,CAAC,OAAO,EAAE;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,YAAY,CAAA;KAAE;IAuB5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB;IAuBnD,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,QAAQ;CAGjB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from 'crypto';
|
|
2
|
+
import { getCurrentTimeMs, addMs } from '../utils/time.js';
|
|
3
|
+
export class TokenManager {
|
|
4
|
+
constructor(secret) {
|
|
5
|
+
this.tokenExpiryMs = 300000; // 5 minutes
|
|
6
|
+
this.secret = secret ? Buffer.from(secret) : randomBytes(32);
|
|
7
|
+
}
|
|
8
|
+
issueToken(options) {
|
|
9
|
+
const now = getCurrentTimeMs();
|
|
10
|
+
const expiryMs = options.expiryMs || this.tokenExpiryMs;
|
|
11
|
+
const payload = {
|
|
12
|
+
tokenId: this.randomId(),
|
|
13
|
+
proposalId: options.proposalId,
|
|
14
|
+
toolName: options.toolName,
|
|
15
|
+
toolArgsHash: options.toolArgsHash,
|
|
16
|
+
issuedAt: now,
|
|
17
|
+
expiresAt: addMs(new Date(now), expiryMs).getTime(),
|
|
18
|
+
nonce: randomBytes(16).toString('hex'),
|
|
19
|
+
compositeScore: options.compositeScore,
|
|
20
|
+
};
|
|
21
|
+
const signature = this.sign(payload);
|
|
22
|
+
const token = Buffer.from(JSON.stringify({ ...payload, signature })).toString('base64');
|
|
23
|
+
return { token, payload };
|
|
24
|
+
}
|
|
25
|
+
verifyToken(token) {
|
|
26
|
+
try {
|
|
27
|
+
const data = JSON.parse(Buffer.from(token, 'base64').toString());
|
|
28
|
+
const { signature, ...payload } = data;
|
|
29
|
+
if (!signature) {
|
|
30
|
+
return { valid: false, reason: 'missing_signature' };
|
|
31
|
+
}
|
|
32
|
+
if (this.sign(payload) !== signature) {
|
|
33
|
+
return { valid: false, reason: 'bad_signature' };
|
|
34
|
+
}
|
|
35
|
+
if (payload.expiresAt < getCurrentTimeMs()) {
|
|
36
|
+
return { valid: false, reason: 'expired' };
|
|
37
|
+
}
|
|
38
|
+
return { valid: true, payload: payload };
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return { valid: false, reason: 'invalid_token_format' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
sign(payload) {
|
|
45
|
+
const data = JSON.stringify(payload);
|
|
46
|
+
return createHmac('sha256', this.secret).update(data).digest('hex');
|
|
47
|
+
}
|
|
48
|
+
randomId() {
|
|
49
|
+
return randomBytes(8).toString('hex');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/proposal/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAmB3D,MAAM,OAAO,YAAY;IAIvB,YAAY,MAAe;QAFnB,kBAAa,GAAW,MAAM,CAAC,CAAC,YAAY;QAGlD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,UAAU,CAAC,OAMV;QACC,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,aAAa,CAAC;QAExD,MAAM,OAAO,GAAiB;YAC5B,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE;YACxB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,QAAQ,EAAE,GAAG;YACb,SAAS,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,OAAO,EAAE;YACnD,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtC,cAAc,EAAE,OAAO,CAAC,cAAc;SACvC,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CACvB,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,CAC1C,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAErB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC5B,CAAC;IAED,WAAW,CAAC,KAAa;QACvB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjE,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,GAAG,IAA4C,CAAC;YAE/E,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;YACvD,CAAC;YAED,IAAI,IAAI,CAAC,IAAI,CAAC,OAAuB,CAAC,KAAK,SAAS,EAAE,CAAC;gBACrD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;YACnD,CAAC;YAED,IAAI,OAAO,CAAC,SAAS,GAAG,gBAAgB,EAAE,EAAE,CAAC;gBAC3C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YAC7C,CAAC;YAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAuB,EAAE,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;IAEO,IAAI,CAAC,OAAqB;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC;IAEO,QAAQ;QACd,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TokenManager } from './token.js';
|
|
2
|
+
export interface VerificationOptions {
|
|
3
|
+
token: string;
|
|
4
|
+
proposalId: string;
|
|
5
|
+
toolName: string;
|
|
6
|
+
toolArgs: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface VerificationResult {
|
|
9
|
+
valid: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
canExecute: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class CommitVerifier {
|
|
14
|
+
private tokenManager;
|
|
15
|
+
private usedNonces;
|
|
16
|
+
constructor(tokenManager?: TokenManager);
|
|
17
|
+
verify(options: VerificationOptions): VerificationResult;
|
|
18
|
+
resetNonces(): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/proposal/verifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,UAAU,CAA0B;gBAEhC,YAAY,CAAC,EAAE,YAAY;IAIvC,MAAM,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB;IA6BxD,WAAW,IAAI,IAAI;CAGpB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { hashJson } from '../utils/hashing.js';
|
|
2
|
+
import { TokenManager } from './token.js';
|
|
3
|
+
export class CommitVerifier {
|
|
4
|
+
constructor(tokenManager) {
|
|
5
|
+
this.usedNonces = new Set();
|
|
6
|
+
this.tokenManager = tokenManager || new TokenManager();
|
|
7
|
+
}
|
|
8
|
+
verify(options) {
|
|
9
|
+
const tokenResult = this.tokenManager.verifyToken(options.token);
|
|
10
|
+
if (!tokenResult.valid) {
|
|
11
|
+
return { valid: false, reason: tokenResult.reason, canExecute: false };
|
|
12
|
+
}
|
|
13
|
+
const payload = tokenResult.payload;
|
|
14
|
+
if (payload.proposalId !== options.proposalId) {
|
|
15
|
+
return { valid: false, reason: 'unknown_proposal', canExecute: false };
|
|
16
|
+
}
|
|
17
|
+
if (payload.toolName !== options.toolName) {
|
|
18
|
+
return { valid: false, reason: 'tool_name_mismatch', canExecute: false };
|
|
19
|
+
}
|
|
20
|
+
const argsHash = hashJson(options.toolArgs);
|
|
21
|
+
if (argsHash !== payload.toolArgsHash) {
|
|
22
|
+
return { valid: false, reason: 'args_hash_mismatch', canExecute: false };
|
|
23
|
+
}
|
|
24
|
+
if (this.usedNonces.has(payload.nonce)) {
|
|
25
|
+
return { valid: false, reason: 'nonce_replay', canExecute: false };
|
|
26
|
+
}
|
|
27
|
+
this.usedNonces.add(payload.nonce);
|
|
28
|
+
return { valid: true, canExecute: true };
|
|
29
|
+
}
|
|
30
|
+
resetNonces() {
|
|
31
|
+
this.usedNonces.clear();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../src/proposal/verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAe1C,MAAM,OAAO,cAAc;IAIzB,YAAY,YAA2B;QAF/B,eAAU,GAAgB,IAAI,GAAG,EAAE,CAAC;QAG1C,IAAI,CAAC,YAAY,GAAG,YAAY,IAAI,IAAI,YAAY,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,OAA4B;QACjC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QACzE,CAAC;QAED,MAAM,OAAO,GAAG,WAAW,CAAC,OAAQ,CAAC;QAErC,IAAI,OAAO,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;YAC9C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QACzE,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC1C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC3E,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,QAAQ,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;YACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC3E,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QACrE,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAC3C,CAAC;IAED,WAAW;QACT,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface RiskSignals {
|
|
2
|
+
isDestructive: boolean;
|
|
3
|
+
isIrreversible: boolean;
|
|
4
|
+
isOpenWorld: boolean;
|
|
5
|
+
impactScope: 'high' | 'medium' | 'low';
|
|
6
|
+
confidenceLevel: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function computeRiskScore(signals: RiskSignals): number;
|
|
9
|
+
export declare function riskLevelForScore(score: number): 'low' | 'medium' | 'high';
|
|
10
|
+
export declare function categorizeRisk(toolName: string, args: Record<string, unknown>): RiskSignals;
|
|
11
|
+
//# sourceMappingURL=scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../../src/risk/scoring.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACvC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAkB7D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAI1E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAqC3F"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function computeRiskScore(signals) {
|
|
2
|
+
let score = 0;
|
|
3
|
+
if (signals.isDestructive)
|
|
4
|
+
score += 0.3;
|
|
5
|
+
if (signals.isIrreversible)
|
|
6
|
+
score += 0.3;
|
|
7
|
+
if (signals.isOpenWorld)
|
|
8
|
+
score += 0.15;
|
|
9
|
+
const scopeWeights = {
|
|
10
|
+
high: 0.2,
|
|
11
|
+
medium: 0.1,
|
|
12
|
+
low: 0.05,
|
|
13
|
+
};
|
|
14
|
+
score += scopeWeights[signals.impactScope];
|
|
15
|
+
const confidencePenalty = 1 - signals.confidenceLevel;
|
|
16
|
+
score += confidencePenalty * 0.15;
|
|
17
|
+
return Math.min(1, Math.max(0, score));
|
|
18
|
+
}
|
|
19
|
+
export function riskLevelForScore(score) {
|
|
20
|
+
if (score < 0.33)
|
|
21
|
+
return 'low';
|
|
22
|
+
if (score < 0.67)
|
|
23
|
+
return 'medium';
|
|
24
|
+
return 'high';
|
|
25
|
+
}
|
|
26
|
+
export function categorizeRisk(toolName, args) {
|
|
27
|
+
const lowerToolName = toolName.toLowerCase();
|
|
28
|
+
const isDestructive = lowerToolName.includes('delete') ||
|
|
29
|
+
lowerToolName.includes('drop') ||
|
|
30
|
+
lowerToolName.includes('remove') ||
|
|
31
|
+
lowerToolName.includes('destroy');
|
|
32
|
+
const isIrreversible = isDestructive;
|
|
33
|
+
const isOpenWorld = lowerToolName.includes('execute') ||
|
|
34
|
+
lowerToolName.includes('run') ||
|
|
35
|
+
lowerToolName.includes('eval');
|
|
36
|
+
let impactScope = 'low';
|
|
37
|
+
if (lowerToolName.includes('user') ||
|
|
38
|
+
lowerToolName.includes('account') ||
|
|
39
|
+
lowerToolName.includes('database')) {
|
|
40
|
+
impactScope = 'high';
|
|
41
|
+
}
|
|
42
|
+
else if (lowerToolName.includes('file') ||
|
|
43
|
+
lowerToolName.includes('resource')) {
|
|
44
|
+
impactScope = 'medium';
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
isDestructive,
|
|
48
|
+
isIrreversible,
|
|
49
|
+
isOpenWorld,
|
|
50
|
+
impactScope,
|
|
51
|
+
confidenceLevel: 0.8,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../src/risk/scoring.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACnD,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,IAAI,OAAO,CAAC,aAAa;QAAE,KAAK,IAAI,GAAG,CAAC;IACxC,IAAI,OAAO,CAAC,cAAc;QAAE,KAAK,IAAI,GAAG,CAAC;IACzC,IAAI,OAAO,CAAC,WAAW;QAAE,KAAK,IAAI,IAAI,CAAC;IAEvC,MAAM,YAAY,GAA2B;QAC3C,IAAI,EAAE,GAAG;QACT,MAAM,EAAE,GAAG;QACX,GAAG,EAAE,IAAI;KACV,CAAC;IACF,KAAK,IAAI,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAE3C,MAAM,iBAAiB,GAAG,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IACtD,KAAK,IAAI,iBAAiB,GAAG,IAAI,CAAC;IAElC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,QAAQ,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,IAA6B;IAC5E,MAAM,aAAa,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAE7C,MAAM,aAAa,GACjB,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAChC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9B,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAChC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAEpC,MAAM,cAAc,GAAG,aAAa,CAAC;IAErC,MAAM,WAAW,GACf,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;QACjC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC7B,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEjC,IAAI,WAAW,GAA8B,KAAK,CAAC;IACnD,IACE,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9B,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;QACjC,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,EAClC,CAAC;QACD,WAAW,GAAG,MAAM,CAAC;IACvB,CAAC;SAAM,IACL,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9B,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,EAClC,CAAC;QACD,WAAW,GAAG,QAAQ,CAAC;IACzB,CAAC;IAED,OAAO;QACL,aAAa;QACb,cAAc;QACd,WAAW;QACX,WAAW;QACX,eAAe,EAAE,GAAG;KACrB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashing.test.d.ts","sourceRoot":"","sources":["../../src/tests/hashing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import { strict as assert } from 'node:assert';
|
|
3
|
+
import { hashText, hashJson, normalizePrompt, computePromptHash } from '../utils/hashing.js';
|
|
4
|
+
test('hashText produces consistent hashes', async () => {
|
|
5
|
+
const hash1 = hashText('hello world');
|
|
6
|
+
const hash2 = hashText('hello world');
|
|
7
|
+
assert.equal(hash1, hash2);
|
|
8
|
+
assert.equal(hash1.length, 64); // SHA256 hex
|
|
9
|
+
});
|
|
10
|
+
test('hashText produces different hashes for different inputs', async () => {
|
|
11
|
+
const hash1 = hashText('hello');
|
|
12
|
+
const hash2 = hashText('world');
|
|
13
|
+
assert.notEqual(hash1, hash2);
|
|
14
|
+
});
|
|
15
|
+
test('hashJson handles objects', async () => {
|
|
16
|
+
const obj = { b: 2, a: 1 };
|
|
17
|
+
const hash = hashJson(obj);
|
|
18
|
+
assert.ok(hash);
|
|
19
|
+
assert.equal(hash.length, 64);
|
|
20
|
+
});
|
|
21
|
+
test('hashJson is order-independent', async () => {
|
|
22
|
+
const obj1 = { a: 1, b: 2 };
|
|
23
|
+
const obj2 = { b: 2, a: 1 };
|
|
24
|
+
const hash1 = hashJson(obj1);
|
|
25
|
+
const hash2 = hashJson(obj2);
|
|
26
|
+
assert.equal(hash1, hash2);
|
|
27
|
+
});
|
|
28
|
+
test('normalizePrompt handles whitespace', async () => {
|
|
29
|
+
const prompt = ' Hello WORLD ';
|
|
30
|
+
const normalized = normalizePrompt(prompt);
|
|
31
|
+
assert.equal(normalized, 'hello world');
|
|
32
|
+
});
|
|
33
|
+
test('computePromptHash is stable', async () => {
|
|
34
|
+
const prompt = 'Generate a deployment plan';
|
|
35
|
+
const hash1 = computePromptHash(prompt);
|
|
36
|
+
const hash2 = computePromptHash('GENERATE A DEPLOYMENT PLAN');
|
|
37
|
+
assert.equal(hash1, hash2);
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=hashing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashing.test.js","sourceRoot":"","sources":["../../src/tests/hashing.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7F,IAAI,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;IACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IAEtC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;AAC/C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;IACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEhC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;IAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE3B,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAChB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;IAC/C,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAE5B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE7B,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;IACpD,MAAM,MAAM,GAAG,mBAAmB,CAAC;IACnC,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;IAC7C,MAAM,MAAM,GAAG,4BAA4B,CAAC;IAC5C,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,4BAA4B,CAAC,CAAC;IAE9D,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposer.test.d.ts","sourceRoot":"","sources":["../../src/tests/proposer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import { strict as assert } from 'node:assert';
|
|
3
|
+
import { ToolProposer } from '../proposal/proposer.js';
|
|
4
|
+
test('Proposer creates proposals', async () => {
|
|
5
|
+
const proposer = new ToolProposer();
|
|
6
|
+
const result = await proposer.propose({
|
|
7
|
+
toolName: 'transfer_funds',
|
|
8
|
+
toolArgs: { amount: 100, to: 'acct_123' },
|
|
9
|
+
outputInstability: 0.1,
|
|
10
|
+
});
|
|
11
|
+
assert.ok(result.proposalId);
|
|
12
|
+
assert.ok(['allowed', 'blocked', 'review'].includes(result.status));
|
|
13
|
+
});
|
|
14
|
+
test('Proposer blocks high-risk proposals', async () => {
|
|
15
|
+
const proposer = new ToolProposer();
|
|
16
|
+
const result = await proposer.propose({
|
|
17
|
+
toolName: 'transfer_funds',
|
|
18
|
+
toolArgs: { amount: 1000000, to: 'unknown' },
|
|
19
|
+
outputInstability: 0.9,
|
|
20
|
+
numericVariance: 0.9,
|
|
21
|
+
promptDrift: 0.8,
|
|
22
|
+
});
|
|
23
|
+
assert.equal(result.status, 'blocked');
|
|
24
|
+
assert.ok(result.fallbackResponse);
|
|
25
|
+
});
|
|
26
|
+
test('Proposer allows low-risk proposals', async () => {
|
|
27
|
+
const proposer = new ToolProposer();
|
|
28
|
+
const result = await proposer.propose({
|
|
29
|
+
toolName: 'get_account_info',
|
|
30
|
+
toolArgs: { accountId: 'acct_123' },
|
|
31
|
+
outputInstability: 0.05,
|
|
32
|
+
numericVariance: 0.02,
|
|
33
|
+
promptDrift: 0.01,
|
|
34
|
+
});
|
|
35
|
+
assert.equal(result.status, 'allowed');
|
|
36
|
+
assert.ok(result.commitToken);
|
|
37
|
+
});
|
|
38
|
+
test('Proposer includes commit token for non-blocked proposals', async () => {
|
|
39
|
+
const proposer = new ToolProposer();
|
|
40
|
+
const result = await proposer.propose({
|
|
41
|
+
toolName: 'read_file',
|
|
42
|
+
toolArgs: { path: '/tmp/test.txt' },
|
|
43
|
+
outputInstability: 0.3,
|
|
44
|
+
});
|
|
45
|
+
if (result.status !== 'blocked') {
|
|
46
|
+
assert.ok(result.commitToken);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=proposer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposer.test.js","sourceRoot":"","sources":["../../src/tests/proposer.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGvD,IAAI,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;IAC5C,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;QACpC,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE;QACzC,iBAAiB,EAAE,GAAG;KACvB,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;IACrD,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;QACpC,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE;QAC5C,iBAAiB,EAAE,GAAG;QACtB,eAAe,EAAE,GAAG;QACpB,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;IACpD,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;QACpC,QAAQ,EAAE,kBAAkB;QAC5B,QAAQ,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE;QACnC,iBAAiB,EAAE,IAAI;QACvB,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;IAC1E,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;QACpC,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;QACnC,iBAAiB,EAAE,GAAG;KACvB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.test.d.ts","sourceRoot":"","sources":["../../src/tests/scoring.test.ts"],"names":[],"mappings":""}
|