@jigyasudham/veto 1.2.12 → 1.2.14
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/README.md +8 -0
- package/dist/memory/config.d.ts +11 -0
- package/dist/memory/config.d.ts.map +1 -0
- package/dist/memory/config.js +40 -0
- package/dist/memory/config.js.map +1 -0
- package/dist/memory/local.d.ts +22 -0
- package/dist/memory/local.d.ts.map +1 -1
- package/dist/memory/local.js +39 -0
- package/dist/memory/local.js.map +1 -1
- package/dist/memory/schema.d.ts +1 -1
- package/dist/memory/schema.d.ts.map +1 -1
- package/dist/memory/schema.js +10 -0
- package/dist/memory/schema.js.map +1 -1
- package/dist/router/index.d.ts +2 -2
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +2 -2
- package/dist/router/index.js.map +1 -1
- package/dist/router/rate-monitor.d.ts +3 -1
- package/dist/router/rate-monitor.d.ts.map +1 -1
- package/dist/router/rate-monitor.js +35 -16
- package/dist/router/rate-monitor.js.map +1 -1
- package/dist/server.js +169 -45
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Veto MCP Server — 45 tools,
|
|
2
|
+
// Veto MCP Server — 45 tools, 17 phases complete, self-learning router
|
|
3
3
|
// Suppress node:sqlite experimental warning — it would corrupt the MCP stdio protocol
|
|
4
4
|
process.removeAllListeners('warning');
|
|
5
5
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
6
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
7
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { buildContextString } from './context/reader.js';
|
|
9
|
-
import { saveSession, restoreSession, listSessions, closeSession, getDbPath, saveCouncilOutcome, storeKnowledge, searchKnowledge, deleteKnowledge, updateProjectMap, getProjectMap, upsertPattern, getPatterns, getContextStatus, fetchAndCacheDocs, saveTaskPlan, getUsageStatus, getAuditLog, getHealthStats, CONTEXT_WINDOWS, } from './memory/local.js';
|
|
9
|
+
import { saveSession, restoreSession, listSessions, closeSession, getDbPath, saveCouncilOutcome, storeKnowledge, searchKnowledge, deleteKnowledge, updateProjectMap, getProjectMap, upsertPattern, getPatterns, getContextStatus, fetchAndCacheDocs, saveTaskPlan, getUsageStatus, getAuditLog, getHealthStats, CONTEXT_WINDOWS, logUsage, getUsageLogs, } from './memory/local.js';
|
|
10
10
|
import { exportMemory, importMemory } from './memory/sync.js';
|
|
11
11
|
import { runDebate } from './council/index.js';
|
|
12
|
-
import { routeTask, getRateStatus, recordOutcome, getLearningStats, getLearnedThresholds, applyLearnedThresholds, getAgentPerformanceStats, getTaskTypeBreakdown, getCouncilInsights, getRecommendedAgent } from './router/index.js';
|
|
12
|
+
import { routeTask, getRateStatus, trackTokens, recordOutcome, getLearningStats, getLearnedThresholds, applyLearnedThresholds, getAgentPerformanceStats, getTaskTypeBreakdown, getCouncilInsights, getRecommendedAgent } from './router/index.js';
|
|
13
|
+
import { getConfig, setConfig } from './memory/config.js';
|
|
13
14
|
import { executeParallel, executeOne } from './agents/executor.js';
|
|
14
15
|
import { handoff, continueSession, getPlatformSetup } from './adapters/index.js';
|
|
15
16
|
import { startWatch, pollWatch, stopWatch } from './watcher/index.js';
|
|
@@ -63,9 +64,62 @@ const server = new Server({ name: 'veto', version: VERSION }, {
|
|
|
63
64
|
prompts: {},
|
|
64
65
|
},
|
|
65
66
|
});
|
|
67
|
+
// ─── Tool Risk Annotations (#21) ─────────────────────────────────────────────
|
|
68
|
+
// readOnlyHint: tool makes no writes. destructiveHint: writes are irreversible.
|
|
69
|
+
// openWorldHint: tool reaches outside the local DB (network, filesystem, processes).
|
|
70
|
+
const TOOL_ANNOTATIONS = {
|
|
71
|
+
// read-only — query/inspect only
|
|
72
|
+
veto_status: { readOnlyHint: true },
|
|
73
|
+
veto_autosave_status: { readOnlyHint: true },
|
|
74
|
+
veto_sessions_list: { readOnlyHint: true },
|
|
75
|
+
veto_rate_status: { readOnlyHint: true },
|
|
76
|
+
veto_route_task: { readOnlyHint: true },
|
|
77
|
+
veto_agent_plan: { readOnlyHint: true },
|
|
78
|
+
veto_code_review: { readOnlyHint: true },
|
|
79
|
+
veto_diff_review: { readOnlyHint: true },
|
|
80
|
+
veto_security_scan: { readOnlyHint: true },
|
|
81
|
+
veto_secrets_scan: { readOnlyHint: true },
|
|
82
|
+
veto_project_map_get: { readOnlyHint: true },
|
|
83
|
+
veto_patterns_list: { readOnlyHint: true },
|
|
84
|
+
veto_learning_stats: { readOnlyHint: true },
|
|
85
|
+
veto_watch_poll: { readOnlyHint: true },
|
|
86
|
+
veto_plugins: { readOnlyHint: true },
|
|
87
|
+
veto_context_status: { readOnlyHint: true },
|
|
88
|
+
veto_audit_log: { readOnlyHint: true },
|
|
89
|
+
veto_health: { readOnlyHint: true },
|
|
90
|
+
veto_discover: { readOnlyHint: true },
|
|
91
|
+
veto_summarize: { readOnlyHint: true },
|
|
92
|
+
veto_explain: { readOnlyHint: true },
|
|
93
|
+
// read-only + open world (external network)
|
|
94
|
+
veto_docs_fetch: { readOnlyHint: true, openWorldHint: true },
|
|
95
|
+
veto_pr_review: { readOnlyHint: true, openWorldHint: true },
|
|
96
|
+
// reversible writes (local DB — can be deleted/reset)
|
|
97
|
+
veto_council_debate: { readOnlyHint: false, destructiveHint: false },
|
|
98
|
+
veto_execute_parallel: { readOnlyHint: false, destructiveHint: false },
|
|
99
|
+
veto_session_save: { readOnlyHint: false, destructiveHint: false },
|
|
100
|
+
veto_session_restore: { readOnlyHint: false, destructiveHint: false },
|
|
101
|
+
veto_memory_store: { readOnlyHint: false, destructiveHint: false },
|
|
102
|
+
veto_project_map_update: { readOnlyHint: false, destructiveHint: false },
|
|
103
|
+
veto_pattern_store: { readOnlyHint: false, destructiveHint: false },
|
|
104
|
+
veto_memory_export: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
105
|
+
veto_record_outcome: { readOnlyHint: false, destructiveHint: false },
|
|
106
|
+
veto_learning_apply: { readOnlyHint: false, destructiveHint: false },
|
|
107
|
+
veto_handoff: { readOnlyHint: false, destructiveHint: false },
|
|
108
|
+
veto_continue: { readOnlyHint: false, destructiveHint: false },
|
|
109
|
+
veto_task_parse: { readOnlyHint: false, destructiveHint: false },
|
|
110
|
+
veto_watch: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
111
|
+
veto_watch_stop: { readOnlyHint: false, destructiveHint: false },
|
|
112
|
+
veto_workflow: { readOnlyHint: false, destructiveHint: false },
|
|
113
|
+
veto_ci_gate: { readOnlyHint: false, destructiveHint: false },
|
|
114
|
+
veto_usage_status: { readOnlyHint: false, destructiveHint: false },
|
|
115
|
+
// destructive — permanent deletes or config overwrites
|
|
116
|
+
veto_memory_delete: { readOnlyHint: false, destructiveHint: true },
|
|
117
|
+
veto_memory_import: { readOnlyHint: false, destructiveHint: true },
|
|
118
|
+
veto_platform_setup: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
|
|
119
|
+
};
|
|
66
120
|
// ─── Tool Definitions ─────────────────────────────────────────────────────────
|
|
67
|
-
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
|
68
|
-
tools
|
|
121
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
122
|
+
const tools = [
|
|
69
123
|
{
|
|
70
124
|
name: 'veto_status',
|
|
71
125
|
description: 'Returns Veto server status, version, and database info. Pass token_count to trigger auto-save if context usage crosses 70%.',
|
|
@@ -240,6 +294,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
240
294
|
type: 'string',
|
|
241
295
|
description: 'Optional: session ID to associate this council outcome with an active session.',
|
|
242
296
|
},
|
|
297
|
+
max_tokens: {
|
|
298
|
+
type: 'number',
|
|
299
|
+
description: 'Optional: token budget for this operation. Veto estimates output tokens and warns in the response if the estimate exceeds this limit. Logged to usage_log for tracking.',
|
|
300
|
+
},
|
|
243
301
|
},
|
|
244
302
|
required: ['task'],
|
|
245
303
|
},
|
|
@@ -333,6 +391,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
333
391
|
},
|
|
334
392
|
},
|
|
335
393
|
project_dir: { type: 'string', description: 'Optional: project directory applied to all tasks (per-task project_dir overrides this). Auto-injects codebase context.' },
|
|
394
|
+
max_tokens: {
|
|
395
|
+
type: 'number',
|
|
396
|
+
description: 'Optional: token budget for this parallel execution. Veto estimates combined output tokens and warns if the estimate exceeds this limit. Logged to usage_log.',
|
|
397
|
+
},
|
|
336
398
|
},
|
|
337
399
|
required: ['tasks'],
|
|
338
400
|
},
|
|
@@ -763,8 +825,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
763
825
|
required: [],
|
|
764
826
|
},
|
|
765
827
|
},
|
|
766
|
-
]
|
|
767
|
-
}));
|
|
828
|
+
];
|
|
829
|
+
return { tools: tools.map(t => ({ ...t, annotations: TOOL_ANNOTATIONS[t.name] ?? {} })) };
|
|
830
|
+
});
|
|
768
831
|
// ─── Shared Scan Utility ──────────────────────────────────────────────────────
|
|
769
832
|
async function runTripleScan(diff, context) {
|
|
770
833
|
const [reviewResult, secResult, secretsResult] = await Promise.all([
|
|
@@ -787,6 +850,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
787
850
|
case 'veto_status': {
|
|
788
851
|
const statusTokenCount = typeof args?.token_count === 'number' ? args.token_count : null;
|
|
789
852
|
const statusPlatform = args?.platform ? String(args.platform) : 'claude';
|
|
853
|
+
if (statusTokenCount !== null && statusTokenCount > 0) {
|
|
854
|
+
trackTokens(statusPlatform, statusTokenCount);
|
|
855
|
+
}
|
|
790
856
|
const autoSaveResult = statusTokenCount !== null ? maybeAutoSave(statusTokenCount, statusPlatform) : null;
|
|
791
857
|
return {
|
|
792
858
|
content: [
|
|
@@ -980,8 +1046,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
980
1046
|
project_dir: args?.project_dir ? String(args.project_dir) : undefined,
|
|
981
1047
|
});
|
|
982
1048
|
const debateDuration = Date.now() - debateStart;
|
|
1049
|
+
const sessionId = args?.session_id ? String(args.session_id) : undefined;
|
|
983
1050
|
const outcomeId = saveCouncilOutcome({
|
|
984
|
-
session_id:
|
|
1051
|
+
session_id: sessionId,
|
|
985
1052
|
task,
|
|
986
1053
|
verdict: result.final_verdict,
|
|
987
1054
|
lead_dev: JSON.stringify(result.votes.lead_dev),
|
|
@@ -994,29 +1061,37 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
994
1061
|
recommended: result.recommended,
|
|
995
1062
|
duration_ms: debateDuration,
|
|
996
1063
|
});
|
|
1064
|
+
const responsePayload = {
|
|
1065
|
+
outcome_id: outcomeId,
|
|
1066
|
+
final_verdict: result.final_verdict,
|
|
1067
|
+
block_reasons: result.block_reasons,
|
|
1068
|
+
warnings: result.warnings,
|
|
1069
|
+
recommended: result.recommended,
|
|
1070
|
+
debated_at: result.debated_at,
|
|
1071
|
+
votes: {
|
|
1072
|
+
lead_dev: result.votes.lead_dev.verdict,
|
|
1073
|
+
pm: result.votes.pm.verdict,
|
|
1074
|
+
architect: result.votes.architect.verdict,
|
|
1075
|
+
ux: result.votes.ux.verdict,
|
|
1076
|
+
devil: result.votes.devil.verdict,
|
|
1077
|
+
legal: result.votes.legal.verdict,
|
|
1078
|
+
security: result.votes.security.verdict,
|
|
1079
|
+
},
|
|
1080
|
+
};
|
|
1081
|
+
const fullText = result.formatted_output + '\n\n' + JSON.stringify(responsePayload, null, 2);
|
|
1082
|
+
if (typeof args?.max_tokens === 'number') {
|
|
1083
|
+
const { exceeded, estimated_tokens } = logUsage({
|
|
1084
|
+
tool_name: 'veto_council_debate',
|
|
1085
|
+
session_id: sessionId,
|
|
1086
|
+
max_tokens: args.max_tokens,
|
|
1087
|
+
output: fullText,
|
|
1088
|
+
});
|
|
1089
|
+
if (exceeded) {
|
|
1090
|
+
responsePayload.budget_warning = `Estimated output tokens (${estimated_tokens}) exceeded max_tokens budget (${args.max_tokens}).`;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
997
1093
|
return {
|
|
998
|
-
content: [
|
|
999
|
-
{
|
|
1000
|
-
type: 'text',
|
|
1001
|
-
text: result.formatted_output + '\n\n' + JSON.stringify({
|
|
1002
|
-
outcome_id: outcomeId,
|
|
1003
|
-
final_verdict: result.final_verdict,
|
|
1004
|
-
block_reasons: result.block_reasons,
|
|
1005
|
-
warnings: result.warnings,
|
|
1006
|
-
recommended: result.recommended,
|
|
1007
|
-
debated_at: result.debated_at,
|
|
1008
|
-
votes: {
|
|
1009
|
-
lead_dev: result.votes.lead_dev.verdict,
|
|
1010
|
-
pm: result.votes.pm.verdict,
|
|
1011
|
-
architect: result.votes.architect.verdict,
|
|
1012
|
-
ux: result.votes.ux.verdict,
|
|
1013
|
-
devil: result.votes.devil.verdict,
|
|
1014
|
-
legal: result.votes.legal.verdict,
|
|
1015
|
-
security: result.votes.security.verdict,
|
|
1016
|
-
},
|
|
1017
|
-
}, null, 2),
|
|
1018
|
-
},
|
|
1019
|
-
],
|
|
1094
|
+
content: [{ type: 'text', text: fullText }],
|
|
1020
1095
|
};
|
|
1021
1096
|
}
|
|
1022
1097
|
case 'veto_agent_plan': {
|
|
@@ -1158,21 +1233,30 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1158
1233
|
project_dir: t.project_dir ? String(t.project_dir) : parallelProjectDir,
|
|
1159
1234
|
}));
|
|
1160
1235
|
const results = await executeParallel(tasks);
|
|
1236
|
+
const parallelPayload = {
|
|
1237
|
+
count: results.length,
|
|
1238
|
+
total_duration_ms: results.reduce((s, r) => s + r.duration_ms, 0),
|
|
1239
|
+
results: results.map(r => ({
|
|
1240
|
+
id: r.id,
|
|
1241
|
+
agent: r.agent,
|
|
1242
|
+
duration_ms: r.duration_ms,
|
|
1243
|
+
error: r.error,
|
|
1244
|
+
output: { ...(r.plan ?? r.analysis), structured: r.output },
|
|
1245
|
+
})),
|
|
1246
|
+
};
|
|
1247
|
+
if (typeof args?.max_tokens === 'number') {
|
|
1248
|
+
const outputText = JSON.stringify(parallelPayload, null, 2);
|
|
1249
|
+
const { exceeded, estimated_tokens } = logUsage({
|
|
1250
|
+
tool_name: 'veto_execute_parallel',
|
|
1251
|
+
max_tokens: args.max_tokens,
|
|
1252
|
+
output: outputText,
|
|
1253
|
+
});
|
|
1254
|
+
if (exceeded) {
|
|
1255
|
+
parallelPayload.budget_warning = `Estimated output tokens (${estimated_tokens}) exceeded max_tokens budget (${args.max_tokens}).`;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1161
1258
|
return {
|
|
1162
|
-
content: [{
|
|
1163
|
-
type: 'text',
|
|
1164
|
-
text: JSON.stringify({
|
|
1165
|
-
count: results.length,
|
|
1166
|
-
total_duration_ms: results.reduce((s, r) => s + r.duration_ms, 0),
|
|
1167
|
-
results: results.map(r => ({
|
|
1168
|
-
id: r.id,
|
|
1169
|
-
agent: r.agent,
|
|
1170
|
-
duration_ms: r.duration_ms,
|
|
1171
|
-
error: r.error,
|
|
1172
|
-
output: { ...(r.plan ?? r.analysis), structured: r.output },
|
|
1173
|
-
})),
|
|
1174
|
-
}, null, 2),
|
|
1175
|
-
}],
|
|
1259
|
+
content: [{ type: 'text', text: JSON.stringify(parallelPayload, null, 2) }],
|
|
1176
1260
|
};
|
|
1177
1261
|
}
|
|
1178
1262
|
case 'veto_memory_store': {
|
|
@@ -1600,8 +1684,48 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1600
1684
|
}
|
|
1601
1685
|
// ── Phase 14: Observability & Safety ──────────────────────────────────────
|
|
1602
1686
|
case 'veto_usage_status': {
|
|
1687
|
+
if (args?.set_budget && typeof args.set_budget === 'object') {
|
|
1688
|
+
const b = args.set_budget;
|
|
1689
|
+
const current = getConfig().dailyTokenBudget;
|
|
1690
|
+
setConfig({
|
|
1691
|
+
dailyTokenBudget: {
|
|
1692
|
+
claude: typeof b.claude === 'number' ? b.claude : current.claude,
|
|
1693
|
+
gemini: typeof b.gemini === 'number' ? b.gemini : current.gemini,
|
|
1694
|
+
codex: typeof b.codex === 'number' ? b.codex : current.codex,
|
|
1695
|
+
},
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1603
1698
|
const status = getUsageStatus();
|
|
1604
|
-
|
|
1699
|
+
const { dailyTokenBudget } = getConfig();
|
|
1700
|
+
const rateStatus = getRateStatus();
|
|
1701
|
+
const recentBudgetLog = getUsageLogs({ limit: 10 });
|
|
1702
|
+
return {
|
|
1703
|
+
content: [{
|
|
1704
|
+
type: 'text',
|
|
1705
|
+
text: JSON.stringify({
|
|
1706
|
+
success: true,
|
|
1707
|
+
...status,
|
|
1708
|
+
daily_token_budget: dailyTokenBudget,
|
|
1709
|
+
tokens_today: {
|
|
1710
|
+
claude: rateStatus.claude.tokens_today,
|
|
1711
|
+
gemini: rateStatus.gemini.tokens_today,
|
|
1712
|
+
codex: rateStatus.codex.tokens_today,
|
|
1713
|
+
},
|
|
1714
|
+
budget_used_pct: {
|
|
1715
|
+
claude: rateStatus.claude.used_percent,
|
|
1716
|
+
gemini: rateStatus.gemini.used_percent,
|
|
1717
|
+
codex: rateStatus.codex.used_percent,
|
|
1718
|
+
},
|
|
1719
|
+
operation_budget_log: recentBudgetLog.map(e => ({
|
|
1720
|
+
tool: e.tool_name,
|
|
1721
|
+
max_tokens: e.max_tokens,
|
|
1722
|
+
estimated_tokens: e.estimated_tokens,
|
|
1723
|
+
exceeded: e.exceeded === 1,
|
|
1724
|
+
at: e.created_at,
|
|
1725
|
+
})),
|
|
1726
|
+
}, null, 2),
|
|
1727
|
+
}],
|
|
1728
|
+
};
|
|
1605
1729
|
}
|
|
1606
1730
|
case 'veto_audit_log': {
|
|
1607
1731
|
const events = getAuditLog({
|