@jigyasudham/veto 3.1.0 → 3.1.2
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 -21
- package/README.md +633 -627
- package/dist/agents/llm-runner.js +57 -57
- package/dist/cli/statusline.js +2 -2
- package/dist/cli.js +26 -26
- package/dist/memory/decisions.js +1 -1
- package/dist/memory/local.js +144 -144
- package/dist/memory/schema.js +228 -228
- package/dist/memory/sync.js +27 -27
- package/dist/memory/sync.js.map +1 -1
- package/dist/router/implicit-outcomes.js +4 -4
- package/dist/router/learning-updater.js +45 -45
- package/dist/server.js +1 -1
- package/dist/tools/compact.js +3 -3
- package/dist/transcripts/archive.js +5 -5
- package/dist/transcripts/ingest.js +6 -6
- package/dist/transcripts/mapping.js +5 -5
- package/dist/transcripts/pyramid.js +2 -2
- package/dist/transcripts/schema.js +104 -104
- package/dist/transcripts/search.js +3 -3
- package/dist/transcripts/vectors.js +2 -2
- package/package.json +70 -62
- package/server.json +23 -23
- package/dist/skills/development/skill-api-design.d.ts +0 -15
- package/dist/skills/development/skill-api-design.d.ts.map +0 -1
- package/dist/skills/development/skill-api-design.js +0 -313
- package/dist/skills/development/skill-api-design.js.map +0 -1
- package/dist/skills/development/skill-auth.d.ts +0 -15
- package/dist/skills/development/skill-auth.d.ts.map +0 -1
- package/dist/skills/development/skill-auth.js +0 -255
- package/dist/skills/development/skill-auth.js.map +0 -1
- package/dist/skills/development/skill-ci-cd.d.ts +0 -2
- package/dist/skills/development/skill-ci-cd.d.ts.map +0 -1
- package/dist/skills/development/skill-ci-cd.js +0 -2
- package/dist/skills/development/skill-ci-cd.js.map +0 -1
- package/dist/skills/development/skill-crud.d.ts +0 -15
- package/dist/skills/development/skill-crud.d.ts.map +0 -1
- package/dist/skills/development/skill-crud.js +0 -193
- package/dist/skills/development/skill-crud.js.map +0 -1
- package/dist/skills/development/skill-db-schema.d.ts +0 -2
- package/dist/skills/development/skill-db-schema.d.ts.map +0 -1
- package/dist/skills/development/skill-db-schema.js +0 -2
- package/dist/skills/development/skill-db-schema.js.map +0 -1
- package/dist/skills/development/skill-docker.d.ts +0 -2
- package/dist/skills/development/skill-docker.d.ts.map +0 -1
- package/dist/skills/development/skill-docker.js +0 -2
- package/dist/skills/development/skill-docker.js.map +0 -1
- package/dist/skills/development/skill-env-setup.d.ts +0 -2
- package/dist/skills/development/skill-env-setup.d.ts.map +0 -1
- package/dist/skills/development/skill-env-setup.js +0 -2
- package/dist/skills/development/skill-env-setup.js.map +0 -1
- package/dist/skills/development/skill-scaffold.d.ts +0 -15
- package/dist/skills/development/skill-scaffold.d.ts.map +0 -1
- package/dist/skills/development/skill-scaffold.js +0 -299
- package/dist/skills/development/skill-scaffold.js.map +0 -1
- package/dist/skills/intelligence/skill-complexity-score.d.ts +0 -15
- package/dist/skills/intelligence/skill-complexity-score.d.ts.map +0 -1
- package/dist/skills/intelligence/skill-complexity-score.js +0 -66
- package/dist/skills/intelligence/skill-complexity-score.js.map +0 -1
- package/dist/skills/intelligence/skill-cost-track.d.ts +0 -14
- package/dist/skills/intelligence/skill-cost-track.d.ts.map +0 -1
- package/dist/skills/intelligence/skill-cost-track.js +0 -36
- package/dist/skills/intelligence/skill-cost-track.js.map +0 -1
- package/dist/skills/intelligence/skill-learning-loop.d.ts +0 -15
- package/dist/skills/intelligence/skill-learning-loop.d.ts.map +0 -1
- package/dist/skills/intelligence/skill-learning-loop.js +0 -66
- package/dist/skills/intelligence/skill-learning-loop.js.map +0 -1
- package/dist/skills/intelligence/skill-pattern-detect.d.ts +0 -14
- package/dist/skills/intelligence/skill-pattern-detect.d.ts.map +0 -1
- package/dist/skills/intelligence/skill-pattern-detect.js +0 -35
- package/dist/skills/intelligence/skill-pattern-detect.js.map +0 -1
- package/dist/skills/intelligence/skill-rate-watch.d.ts +0 -15
- package/dist/skills/intelligence/skill-rate-watch.d.ts.map +0 -1
- package/dist/skills/intelligence/skill-rate-watch.js +0 -58
- package/dist/skills/intelligence/skill-rate-watch.js.map +0 -1
- package/dist/skills/memory/skill-context-compress.d.ts +0 -15
- package/dist/skills/memory/skill-context-compress.d.ts.map +0 -1
- package/dist/skills/memory/skill-context-compress.js +0 -82
- package/dist/skills/memory/skill-context-compress.js.map +0 -1
- package/dist/skills/memory/skill-cross-sync.d.ts +0 -15
- package/dist/skills/memory/skill-cross-sync.d.ts.map +0 -1
- package/dist/skills/memory/skill-cross-sync.js +0 -88
- package/dist/skills/memory/skill-cross-sync.js.map +0 -1
- package/dist/skills/memory/skill-decision-log.d.ts +0 -15
- package/dist/skills/memory/skill-decision-log.d.ts.map +0 -1
- package/dist/skills/memory/skill-decision-log.js +0 -103
- package/dist/skills/memory/skill-decision-log.js.map +0 -1
- package/dist/skills/memory/skill-session-restore.d.ts +0 -15
- package/dist/skills/memory/skill-session-restore.d.ts.map +0 -1
- package/dist/skills/memory/skill-session-restore.js +0 -39
- package/dist/skills/memory/skill-session-restore.js.map +0 -1
- package/dist/skills/memory/skill-session-save.d.ts +0 -15
- package/dist/skills/memory/skill-session-save.d.ts.map +0 -1
- package/dist/skills/memory/skill-session-save.js +0 -74
- package/dist/skills/memory/skill-session-save.js.map +0 -1
- package/dist/skills/quality/skill-accessibility.d.ts +0 -2
- package/dist/skills/quality/skill-accessibility.d.ts.map +0 -1
- package/dist/skills/quality/skill-accessibility.js +0 -2
- package/dist/skills/quality/skill-accessibility.js.map +0 -1
- package/dist/skills/quality/skill-code-review.d.ts +0 -15
- package/dist/skills/quality/skill-code-review.d.ts.map +0 -1
- package/dist/skills/quality/skill-code-review.js +0 -60
- package/dist/skills/quality/skill-code-review.js.map +0 -1
- package/dist/skills/quality/skill-docs-gen.d.ts +0 -2
- package/dist/skills/quality/skill-docs-gen.d.ts.map +0 -1
- package/dist/skills/quality/skill-docs-gen.js +0 -2
- package/dist/skills/quality/skill-docs-gen.js.map +0 -1
- package/dist/skills/quality/skill-perf-audit.d.ts +0 -2
- package/dist/skills/quality/skill-perf-audit.d.ts.map +0 -1
- package/dist/skills/quality/skill-perf-audit.js +0 -2
- package/dist/skills/quality/skill-perf-audit.js.map +0 -1
- package/dist/skills/quality/skill-security-scan.d.ts +0 -15
- package/dist/skills/quality/skill-security-scan.d.ts.map +0 -1
- package/dist/skills/quality/skill-security-scan.js +0 -67
- package/dist/skills/quality/skill-security-scan.js.map +0 -1
- package/dist/skills/quality/skill-test-suite.d.ts +0 -15
- package/dist/skills/quality/skill-test-suite.d.ts.map +0 -1
- package/dist/skills/quality/skill-test-suite.js +0 -274
- package/dist/skills/quality/skill-test-suite.js.map +0 -1
- package/dist/skills/workflow/skill-deploy.d.ts +0 -2
- package/dist/skills/workflow/skill-deploy.d.ts.map +0 -1
- package/dist/skills/workflow/skill-deploy.js +0 -2
- package/dist/skills/workflow/skill-deploy.js.map +0 -1
- package/dist/skills/workflow/skill-git-workflow.d.ts +0 -2
- package/dist/skills/workflow/skill-git-workflow.d.ts.map +0 -1
- package/dist/skills/workflow/skill-git-workflow.js +0 -2
- package/dist/skills/workflow/skill-git-workflow.js.map +0 -1
- package/dist/skills/workflow/skill-rollback.d.ts +0 -2
- package/dist/skills/workflow/skill-rollback.d.ts.map +0 -1
- package/dist/skills/workflow/skill-rollback.js +0 -2
- package/dist/skills/workflow/skill-rollback.js.map +0 -1
- package/dist/skills/workflow/skill-task-breakdown.d.ts +0 -2
- package/dist/skills/workflow/skill-task-breakdown.d.ts.map +0 -1
- package/dist/skills/workflow/skill-task-breakdown.js +0 -2
- package/dist/skills/workflow/skill-task-breakdown.js.map +0 -1
|
@@ -6,66 +6,66 @@ import { validateAgentPlan, validateAgentAnalysis } from './validate.js';
|
|
|
6
6
|
import { log, errMsg } from '../log.js';
|
|
7
7
|
// ─── System prompt builders ───────────────────────────────────────────────────
|
|
8
8
|
function buildPlanPrompt(agent, role) {
|
|
9
|
-
return `You are the ${agent} specialist in an AI-assisted software engineering system.
|
|
10
|
-
|
|
11
|
-
ROLE: ${role}
|
|
12
|
-
|
|
13
|
-
Your job: given a task description and optional code/context, produce a concrete implementation plan.
|
|
14
|
-
|
|
15
|
-
Return ONLY valid JSON (no markdown, no prose):
|
|
16
|
-
{
|
|
17
|
-
"agent": "${agent}",
|
|
18
|
-
"task": "<task echoed back>",
|
|
19
|
-
"tier": 1|2|3,
|
|
20
|
-
"approach": "<2-3 sentence strategy — the WHY and HOW, not step list>",
|
|
21
|
-
"steps": ["<ordered action step>", ...],
|
|
22
|
-
"checklist": ["[ ] <verification item>", ...],
|
|
23
|
-
"pitfalls": ["<gotcha or common mistake>", ...],
|
|
24
|
-
"patterns": ["<design pattern or principle to apply>", ...],
|
|
25
|
-
"duration_estimate": "<e.g. 1-2 hours>"
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
Rules:
|
|
29
|
-
- tier: 1 = simple (<1h), 2 = medium (1-4h), 3 = complex (>4h)
|
|
30
|
-
- steps: 6-12 concrete, ordered actions
|
|
31
|
-
- checklist: 6-10 testable done-criteria prefixed with "[ ] "
|
|
32
|
-
- pitfalls: 3-5 non-obvious mistakes specific to this task
|
|
33
|
-
- patterns: 3-5 relevant design patterns or engineering principles
|
|
9
|
+
return `You are the ${agent} specialist in an AI-assisted software engineering system.
|
|
10
|
+
|
|
11
|
+
ROLE: ${role}
|
|
12
|
+
|
|
13
|
+
Your job: given a task description and optional code/context, produce a concrete implementation plan.
|
|
14
|
+
|
|
15
|
+
Return ONLY valid JSON (no markdown, no prose):
|
|
16
|
+
{
|
|
17
|
+
"agent": "${agent}",
|
|
18
|
+
"task": "<task echoed back>",
|
|
19
|
+
"tier": 1|2|3,
|
|
20
|
+
"approach": "<2-3 sentence strategy — the WHY and HOW, not step list>",
|
|
21
|
+
"steps": ["<ordered action step>", ...],
|
|
22
|
+
"checklist": ["[ ] <verification item>", ...],
|
|
23
|
+
"pitfalls": ["<gotcha or common mistake>", ...],
|
|
24
|
+
"patterns": ["<design pattern or principle to apply>", ...],
|
|
25
|
+
"duration_estimate": "<e.g. 1-2 hours>"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Rules:
|
|
29
|
+
- tier: 1 = simple (<1h), 2 = medium (1-4h), 3 = complex (>4h)
|
|
30
|
+
- steps: 6-12 concrete, ordered actions
|
|
31
|
+
- checklist: 6-10 testable done-criteria prefixed with "[ ] "
|
|
32
|
+
- pitfalls: 3-5 non-obvious mistakes specific to this task
|
|
33
|
+
- patterns: 3-5 relevant design patterns or engineering principles
|
|
34
34
|
- Keep total JSON under 800 tokens`;
|
|
35
35
|
}
|
|
36
36
|
function buildAnalysisPrompt(agent, role) {
|
|
37
|
-
return `You are the ${agent} specialist in an AI-assisted software engineering system.
|
|
38
|
-
|
|
39
|
-
ROLE: ${role}
|
|
40
|
-
|
|
41
|
-
Your job: given code and optional context, produce a scored analysis with actionable findings.
|
|
42
|
-
|
|
43
|
-
Return ONLY valid JSON (no markdown, no prose):
|
|
44
|
-
{
|
|
45
|
-
"agent": "${agent}",
|
|
46
|
-
"subject": "<one-line description of what was analyzed>",
|
|
47
|
-
"findings": [
|
|
48
|
-
{
|
|
49
|
-
"severity": "critical|high|medium|low|info",
|
|
50
|
-
"category": "<category name>",
|
|
51
|
-
"description": "<what is wrong and why it matters>",
|
|
52
|
-
"fix": "<specific, actionable remediation>",
|
|
53
|
-
"location": "<file:line if applicable>",
|
|
54
|
-
"cwe": "<CWE-NNN if applicable>"
|
|
55
|
-
}
|
|
56
|
-
],
|
|
57
|
-
"score": <0-100, 100 = perfect>,
|
|
58
|
-
"verdict": "approved|approved_with_warnings|needs_revision|rejected",
|
|
59
|
-
"summary": "<one sentence overall assessment>",
|
|
60
|
-
"critical_count": <integer>,
|
|
61
|
-
"high_count": <integer>
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
Rules:
|
|
65
|
-
- findings: list ALL issues found; empty array is valid for clean code
|
|
66
|
-
- score: 90-100 = clean, 70-89 = minor issues, 50-69 = needs work, <50 = reject
|
|
67
|
-
- verdict: approved (score≥90), approved_with_warnings (score 70-89), needs_revision (50-69), rejected (<50)
|
|
68
|
-
- critical_count and high_count MUST match findings array
|
|
37
|
+
return `You are the ${agent} specialist in an AI-assisted software engineering system.
|
|
38
|
+
|
|
39
|
+
ROLE: ${role}
|
|
40
|
+
|
|
41
|
+
Your job: given code and optional context, produce a scored analysis with actionable findings.
|
|
42
|
+
|
|
43
|
+
Return ONLY valid JSON (no markdown, no prose):
|
|
44
|
+
{
|
|
45
|
+
"agent": "${agent}",
|
|
46
|
+
"subject": "<one-line description of what was analyzed>",
|
|
47
|
+
"findings": [
|
|
48
|
+
{
|
|
49
|
+
"severity": "critical|high|medium|low|info",
|
|
50
|
+
"category": "<category name>",
|
|
51
|
+
"description": "<what is wrong and why it matters>",
|
|
52
|
+
"fix": "<specific, actionable remediation>",
|
|
53
|
+
"location": "<file:line if applicable>",
|
|
54
|
+
"cwe": "<CWE-NNN if applicable>"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"score": <0-100, 100 = perfect>,
|
|
58
|
+
"verdict": "approved|approved_with_warnings|needs_revision|rejected",
|
|
59
|
+
"summary": "<one sentence overall assessment>",
|
|
60
|
+
"critical_count": <integer>,
|
|
61
|
+
"high_count": <integer>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Rules:
|
|
65
|
+
- findings: list ALL issues found; empty array is valid for clean code
|
|
66
|
+
- score: 90-100 = clean, 70-89 = minor issues, 50-69 = needs work, <50 = reject
|
|
67
|
+
- verdict: approved (score≥90), approved_with_warnings (score 70-89), needs_revision (50-69), rejected (<50)
|
|
68
|
+
- critical_count and high_count MUST match findings array
|
|
69
69
|
- Keep total JSON under 1000 tokens`;
|
|
70
70
|
}
|
|
71
71
|
// ─── Response parsers ─────────────────────────────────────────────────────────
|
package/dist/cli/statusline.js
CHANGED
|
@@ -97,8 +97,8 @@ function queryStatusline(db, projectDir) {
|
|
|
97
97
|
try {
|
|
98
98
|
// Top confidence among learned patterns. Exclude router.* threshold rows and
|
|
99
99
|
// composed_agent:* definitions — those carry config/JSON, not a learning score.
|
|
100
|
-
const row = db.prepare(`SELECT confidence FROM patterns
|
|
101
|
-
WHERE pattern_key NOT LIKE 'router.%' AND pattern_key NOT LIKE 'composed_agent:%'
|
|
100
|
+
const row = db.prepare(`SELECT confidence FROM patterns
|
|
101
|
+
WHERE pattern_key NOT LIKE 'router.%' AND pattern_key NOT LIKE 'composed_agent:%'
|
|
102
102
|
ORDER BY confidence DESC, seen_count DESC LIMIT 1`).get();
|
|
103
103
|
if (typeof row?.confidence === 'number') {
|
|
104
104
|
data.routerPct = Math.max(0, Math.min(100, Math.round(row.confidence * 100)));
|
package/dist/cli.js
CHANGED
|
@@ -315,32 +315,32 @@ async function initCommand() {
|
|
|
315
315
|
// These are read at session start by each AI client — zero tool calls needed.
|
|
316
316
|
console.log(' Writing context guidance files...');
|
|
317
317
|
console.log('');
|
|
318
|
-
const VETO_GUIDE = `# Veto MCP Server
|
|
319
|
-
|
|
320
|
-
Veto is active. 93 tools across 6 categories:
|
|
321
|
-
|
|
322
|
-
**Session & Context** — veto_status · veto_session_save · veto_continue · veto_handoff
|
|
323
|
-
Save work at 60–70% context capacity. veto_status triggers auto-save above 70%.
|
|
324
|
-
|
|
325
|
-
**Code Intelligence** — veto_diff_review · veto_code_review · veto_security_scan · veto_secrets_scan · veto_ci_gate
|
|
326
|
-
Run veto_diff_review before any merge — it runs all three scans in parallel.
|
|
327
|
-
|
|
328
|
-
**Council & Routing** — veto_council_debate · veto_route_task · veto_execute_parallel
|
|
329
|
-
Council = 7 specialist agents (Lead Dev, PM, Architect, UX, Devil's Advocate, Legal, Security).
|
|
330
|
-
Verdicts: GREEN (proceed) · YELLOW (warnings) · RED (blocked) · DEADLOCK (human decision needed).
|
|
331
|
-
Two-phase LLM-backed flow: call with { task } → get debate_prompt → reason as all 7 agents → call again with { task, agent_responses }.
|
|
332
|
-
|
|
333
|
-
**Memory & Discovery** — veto_discover · veto_summarize · veto_memory_store · veto_memory_search
|
|
334
|
-
Run veto_discover on any unfamiliar repo before touching files.
|
|
335
|
-
|
|
336
|
-
**Observability** — veto_usage_status · veto_health · veto_audit_log · veto_learning_stats
|
|
337
|
-
|
|
338
|
-
Recommended start sequence:
|
|
339
|
-
1. veto_status — confirm running
|
|
340
|
-
2. veto_discover — map the project
|
|
341
|
-
3. veto_route_task — pick the right agent
|
|
342
|
-
4. veto_diff_review — validate before shipping
|
|
343
|
-
5. veto_session_save — checkpoint before context fills
|
|
318
|
+
const VETO_GUIDE = `# Veto MCP Server
|
|
319
|
+
|
|
320
|
+
Veto is active. 93 tools across 6 categories:
|
|
321
|
+
|
|
322
|
+
**Session & Context** — veto_status · veto_session_save · veto_continue · veto_handoff
|
|
323
|
+
Save work at 60–70% context capacity. veto_status triggers auto-save above 70%.
|
|
324
|
+
|
|
325
|
+
**Code Intelligence** — veto_diff_review · veto_code_review · veto_security_scan · veto_secrets_scan · veto_ci_gate
|
|
326
|
+
Run veto_diff_review before any merge — it runs all three scans in parallel.
|
|
327
|
+
|
|
328
|
+
**Council & Routing** — veto_council_debate · veto_route_task · veto_execute_parallel
|
|
329
|
+
Council = 7 specialist agents (Lead Dev, PM, Architect, UX, Devil's Advocate, Legal, Security).
|
|
330
|
+
Verdicts: GREEN (proceed) · YELLOW (warnings) · RED (blocked) · DEADLOCK (human decision needed).
|
|
331
|
+
Two-phase LLM-backed flow: call with { task } → get debate_prompt → reason as all 7 agents → call again with { task, agent_responses }.
|
|
332
|
+
|
|
333
|
+
**Memory & Discovery** — veto_discover · veto_summarize · veto_memory_store · veto_memory_search
|
|
334
|
+
Run veto_discover on any unfamiliar repo before touching files.
|
|
335
|
+
|
|
336
|
+
**Observability** — veto_usage_status · veto_health · veto_audit_log · veto_learning_stats
|
|
337
|
+
|
|
338
|
+
Recommended start sequence:
|
|
339
|
+
1. veto_status — confirm running
|
|
340
|
+
2. veto_discover — map the project
|
|
341
|
+
3. veto_route_task — pick the right agent
|
|
342
|
+
4. veto_diff_review — validate before shipping
|
|
343
|
+
5. veto_session_save — checkpoint before context fills
|
|
344
344
|
`;
|
|
345
345
|
let ctxWritten = 0;
|
|
346
346
|
// Gemini & Antigravity CLI: ~/.gemini/GEMINI.md
|
package/dist/memory/decisions.js
CHANGED
|
@@ -33,7 +33,7 @@ export function addConstraint(input) {
|
|
|
33
33
|
const db = getDb();
|
|
34
34
|
const id = randomUUID();
|
|
35
35
|
const created_at = new Date().toISOString();
|
|
36
|
-
db.prepare(`INSERT INTO decision_constraints (id, project_dir, rule, why, forbidden_patterns, file_scope, severity, active, created_at)
|
|
36
|
+
db.prepare(`INSERT INTO decision_constraints (id, project_dir, rule, why, forbidden_patterns, file_scope, severity, active, created_at)
|
|
37
37
|
VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?)`).run(id, normalizeDir(input.project_dir), input.rule, input.why ?? null, JSON.stringify(input.forbidden_patterns), input.file_scope ?? null, input.severity === 'warn' ? 'warn' : 'block', created_at);
|
|
38
38
|
return listConstraints().find(c => c.id === id);
|
|
39
39
|
}
|
package/dist/memory/local.js
CHANGED
|
@@ -143,18 +143,18 @@ function migrateProjectDirCase(db) {
|
|
|
143
143
|
}
|
|
144
144
|
// Creates tool_call_trace_log table for auditing and session replay (v1.8.0 migration)
|
|
145
145
|
function migrateToolTraceLog(db) {
|
|
146
|
-
db.exec(`
|
|
147
|
-
CREATE TABLE IF NOT EXISTS tool_call_trace_log (
|
|
148
|
-
id TEXT PRIMARY KEY,
|
|
149
|
-
session_id TEXT,
|
|
150
|
-
tool_name TEXT NOT NULL,
|
|
151
|
-
args_json TEXT,
|
|
152
|
-
result_status TEXT NOT NULL DEFAULT 'success',
|
|
153
|
-
error_message TEXT,
|
|
154
|
-
duration_ms INTEGER NOT NULL,
|
|
155
|
-
tokens_used INTEGER,
|
|
156
|
-
recorded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
157
|
-
)
|
|
146
|
+
db.exec(`
|
|
147
|
+
CREATE TABLE IF NOT EXISTS tool_call_trace_log (
|
|
148
|
+
id TEXT PRIMARY KEY,
|
|
149
|
+
session_id TEXT,
|
|
150
|
+
tool_name TEXT NOT NULL,
|
|
151
|
+
args_json TEXT,
|
|
152
|
+
result_status TEXT NOT NULL DEFAULT 'success',
|
|
153
|
+
error_message TEXT,
|
|
154
|
+
duration_ms INTEGER NOT NULL,
|
|
155
|
+
tokens_used INTEGER,
|
|
156
|
+
recorded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
157
|
+
)
|
|
158
158
|
`);
|
|
159
159
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_tool_trace_session ON tool_call_trace_log(session_id)`);
|
|
160
160
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_tool_trace_name ON tool_call_trace_log(tool_name)`);
|
|
@@ -167,44 +167,44 @@ export function getSessionReplay(sessionId) {
|
|
|
167
167
|
export function recordToolCall(opts) {
|
|
168
168
|
const db = getDb();
|
|
169
169
|
const id = randomUUID();
|
|
170
|
-
db.prepare(`
|
|
171
|
-
INSERT INTO tool_call_trace_log (id, session_id, tool_name, args_json, result_status, error_message, duration_ms, tokens_used)
|
|
172
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
170
|
+
db.prepare(`
|
|
171
|
+
INSERT INTO tool_call_trace_log (id, session_id, tool_name, args_json, result_status, error_message, duration_ms, tokens_used)
|
|
172
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
173
173
|
`).run(id, opts.session_id ?? null, opts.tool_name, opts.args ? JSON.stringify(opts.args) : null, opts.result_status, opts.error_message ?? null, opts.duration_ms, opts.tokens_used ?? null);
|
|
174
174
|
return id;
|
|
175
175
|
}
|
|
176
176
|
// Creates routing_feedback table for opt-in routing signal storage (v1.4.8 migration)
|
|
177
177
|
function migrateRoutingFeedback(db) {
|
|
178
|
-
db.exec(`
|
|
179
|
-
CREATE TABLE IF NOT EXISTS routing_feedback (
|
|
180
|
-
id TEXT PRIMARY KEY,
|
|
181
|
-
task_hash TEXT NOT NULL,
|
|
182
|
-
task_snippet TEXT NOT NULL,
|
|
183
|
-
complexity INTEGER NOT NULL,
|
|
184
|
-
model_tier INTEGER NOT NULL,
|
|
185
|
-
agent TEXT,
|
|
186
|
-
outcome TEXT NOT NULL DEFAULT 'pending',
|
|
187
|
-
quality INTEGER,
|
|
188
|
-
session_id TEXT,
|
|
189
|
-
recorded_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
190
|
-
expires_at TEXT NOT NULL
|
|
191
|
-
)
|
|
178
|
+
db.exec(`
|
|
179
|
+
CREATE TABLE IF NOT EXISTS routing_feedback (
|
|
180
|
+
id TEXT PRIMARY KEY,
|
|
181
|
+
task_hash TEXT NOT NULL,
|
|
182
|
+
task_snippet TEXT NOT NULL,
|
|
183
|
+
complexity INTEGER NOT NULL,
|
|
184
|
+
model_tier INTEGER NOT NULL,
|
|
185
|
+
agent TEXT,
|
|
186
|
+
outcome TEXT NOT NULL DEFAULT 'pending',
|
|
187
|
+
quality INTEGER,
|
|
188
|
+
session_id TEXT,
|
|
189
|
+
recorded_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
190
|
+
expires_at TEXT NOT NULL
|
|
191
|
+
)
|
|
192
192
|
`);
|
|
193
193
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_routing_fb_hash ON routing_feedback(task_hash)`);
|
|
194
194
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_routing_fb_exp ON routing_feedback(expires_at)`);
|
|
195
195
|
}
|
|
196
196
|
// Creates context_usage table for live VS Code extension polling (v1.4.4 migration)
|
|
197
197
|
function migrateContextUsage(db) {
|
|
198
|
-
db.exec(`
|
|
199
|
-
CREATE TABLE IF NOT EXISTS context_usage (
|
|
200
|
-
platform TEXT PRIMARY KEY,
|
|
201
|
-
model TEXT,
|
|
202
|
-
token_count INTEGER NOT NULL DEFAULT 0,
|
|
203
|
-
context_window INTEGER NOT NULL DEFAULT 200000,
|
|
204
|
-
usage_pct REAL NOT NULL DEFAULT 0,
|
|
205
|
-
session_id TEXT,
|
|
206
|
-
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
207
|
-
)
|
|
198
|
+
db.exec(`
|
|
199
|
+
CREATE TABLE IF NOT EXISTS context_usage (
|
|
200
|
+
platform TEXT PRIMARY KEY,
|
|
201
|
+
model TEXT,
|
|
202
|
+
token_count INTEGER NOT NULL DEFAULT 0,
|
|
203
|
+
context_window INTEGER NOT NULL DEFAULT 200000,
|
|
204
|
+
usage_pct REAL NOT NULL DEFAULT 0,
|
|
205
|
+
session_id TEXT,
|
|
206
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
207
|
+
)
|
|
208
208
|
`);
|
|
209
209
|
}
|
|
210
210
|
// Adds tags column to sessions (v1.3.1 migration)
|
|
@@ -216,17 +216,17 @@ function migrateSessionTags(db) {
|
|
|
216
216
|
}
|
|
217
217
|
// Creates scan_diagnostics table if it doesn't exist (v1.2.18 migration)
|
|
218
218
|
function migrateScanDiagnostics(db) {
|
|
219
|
-
db.exec(`
|
|
220
|
-
CREATE TABLE IF NOT EXISTS scan_diagnostics (
|
|
221
|
-
id TEXT PRIMARY KEY,
|
|
222
|
-
file_path TEXT NOT NULL,
|
|
223
|
-
line INTEGER NOT NULL DEFAULT 0,
|
|
224
|
-
col_start INTEGER NOT NULL DEFAULT 0,
|
|
225
|
-
message TEXT NOT NULL,
|
|
226
|
-
severity TEXT NOT NULL DEFAULT 'warning',
|
|
227
|
-
source TEXT NOT NULL DEFAULT 'veto',
|
|
228
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
229
|
-
)
|
|
219
|
+
db.exec(`
|
|
220
|
+
CREATE TABLE IF NOT EXISTS scan_diagnostics (
|
|
221
|
+
id TEXT PRIMARY KEY,
|
|
222
|
+
file_path TEXT NOT NULL,
|
|
223
|
+
line INTEGER NOT NULL DEFAULT 0,
|
|
224
|
+
col_start INTEGER NOT NULL DEFAULT 0,
|
|
225
|
+
message TEXT NOT NULL,
|
|
226
|
+
severity TEXT NOT NULL DEFAULT 'warning',
|
|
227
|
+
source TEXT NOT NULL DEFAULT 'veto',
|
|
228
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
229
|
+
)
|
|
230
230
|
`);
|
|
231
231
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_scan_diag_file ON scan_diagnostics(file_path)`);
|
|
232
232
|
}
|
|
@@ -248,16 +248,16 @@ function migrateRateUsageTokens(db) {
|
|
|
248
248
|
}
|
|
249
249
|
// Creates usage_log table if it doesn't exist (v1.2.14 migration)
|
|
250
250
|
function migrateUsageLog(db) {
|
|
251
|
-
db.exec(`
|
|
252
|
-
CREATE TABLE IF NOT EXISTS usage_log (
|
|
253
|
-
id TEXT PRIMARY KEY,
|
|
254
|
-
tool_name TEXT NOT NULL,
|
|
255
|
-
session_id TEXT,
|
|
256
|
-
max_tokens INTEGER NOT NULL,
|
|
257
|
-
estimated_tokens INTEGER NOT NULL,
|
|
258
|
-
exceeded INTEGER NOT NULL DEFAULT 0,
|
|
259
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
260
|
-
)
|
|
251
|
+
db.exec(`
|
|
252
|
+
CREATE TABLE IF NOT EXISTS usage_log (
|
|
253
|
+
id TEXT PRIMARY KEY,
|
|
254
|
+
tool_name TEXT NOT NULL,
|
|
255
|
+
session_id TEXT,
|
|
256
|
+
max_tokens INTEGER NOT NULL,
|
|
257
|
+
estimated_tokens INTEGER NOT NULL,
|
|
258
|
+
exceeded INTEGER NOT NULL DEFAULT 0,
|
|
259
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
260
|
+
)
|
|
261
261
|
`);
|
|
262
262
|
}
|
|
263
263
|
// Adds duration_ms column to council_outcomes if it doesn't exist (v1.2.3 migration)
|
|
@@ -277,12 +277,12 @@ function migrateCouncilProjectDir(db) {
|
|
|
277
277
|
const names = new Set(cols.map(c => c.name));
|
|
278
278
|
if (!names.has('project_dir'))
|
|
279
279
|
db.exec('ALTER TABLE council_outcomes ADD COLUMN project_dir TEXT');
|
|
280
|
-
db.exec(`
|
|
281
|
-
UPDATE council_outcomes
|
|
282
|
-
SET project_dir = (SELECT s.project_dir FROM sessions s WHERE s.id = council_outcomes.session_id)
|
|
283
|
-
WHERE project_dir IS NULL
|
|
284
|
-
AND session_id IS NOT NULL
|
|
285
|
-
AND EXISTS (SELECT 1 FROM sessions s WHERE s.id = council_outcomes.session_id AND s.project_dir IS NOT NULL)
|
|
280
|
+
db.exec(`
|
|
281
|
+
UPDATE council_outcomes
|
|
282
|
+
SET project_dir = (SELECT s.project_dir FROM sessions s WHERE s.id = council_outcomes.session_id)
|
|
283
|
+
WHERE project_dir IS NULL
|
|
284
|
+
AND session_id IS NOT NULL
|
|
285
|
+
AND EXISTS (SELECT 1 FROM sessions s WHERE s.id = council_outcomes.session_id AND s.project_dir IS NOT NULL)
|
|
286
286
|
`);
|
|
287
287
|
}
|
|
288
288
|
// Adds active_client, last_resumed_at, and connection_type columns if they don't exist
|
|
@@ -311,15 +311,15 @@ function migrateCouncilOutcomes(db) {
|
|
|
311
311
|
const col = cols.find(c => c.name === 'session_id');
|
|
312
312
|
if (!col || col.notnull !== 1)
|
|
313
313
|
return;
|
|
314
|
-
db.exec(`
|
|
315
|
-
CREATE TABLE IF NOT EXISTS _council_outcomes_new (
|
|
316
|
-
id TEXT PRIMARY KEY, session_id TEXT, task TEXT NOT NULL,
|
|
317
|
-
verdict TEXT NOT NULL, lead_dev TEXT, pm TEXT, architect TEXT,
|
|
318
|
-
ux TEXT, devil TEXT, recommended TEXT, debated_at TEXT NOT NULL
|
|
319
|
-
);
|
|
320
|
-
INSERT OR IGNORE INTO _council_outcomes_new SELECT * FROM council_outcomes;
|
|
321
|
-
DROP TABLE council_outcomes;
|
|
322
|
-
ALTER TABLE _council_outcomes_new RENAME TO council_outcomes;
|
|
314
|
+
db.exec(`
|
|
315
|
+
CREATE TABLE IF NOT EXISTS _council_outcomes_new (
|
|
316
|
+
id TEXT PRIMARY KEY, session_id TEXT, task TEXT NOT NULL,
|
|
317
|
+
verdict TEXT NOT NULL, lead_dev TEXT, pm TEXT, architect TEXT,
|
|
318
|
+
ux TEXT, devil TEXT, recommended TEXT, debated_at TEXT NOT NULL
|
|
319
|
+
);
|
|
320
|
+
INSERT OR IGNORE INTO _council_outcomes_new SELECT * FROM council_outcomes;
|
|
321
|
+
DROP TABLE council_outcomes;
|
|
322
|
+
ALTER TABLE _council_outcomes_new RENAME TO council_outcomes;
|
|
323
323
|
`);
|
|
324
324
|
}
|
|
325
325
|
// Canonicalize a project directory so writes and reads agree regardless of
|
|
@@ -342,14 +342,14 @@ export function saveSession(input) {
|
|
|
342
342
|
const connection_type = input.connection_type ?? 'subscription';
|
|
343
343
|
const token_count = input.token_count ?? 0;
|
|
344
344
|
const save_type = input.save_type ?? 'manual';
|
|
345
|
-
db.prepare(`
|
|
346
|
-
INSERT INTO sessions (id, started_at, platform, connection_type, project_dir, summary, context, task_state, token_count, save_type, tags)
|
|
347
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
345
|
+
db.prepare(`
|
|
346
|
+
INSERT INTO sessions (id, started_at, platform, connection_type, project_dir, summary, context, task_state, token_count, save_type, tags)
|
|
347
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
348
348
|
`).run(id, now, platform, connection_type, normalizeProjectDir(input.project_dir) ?? null, input.summary ?? null, input.context ? JSON.stringify(input.context) : null, input.task_state ? JSON.stringify(input.task_state) : null, token_count, save_type, input.tags ? JSON.stringify(input.tags) : null);
|
|
349
349
|
// Record usage event
|
|
350
|
-
db.prepare(`
|
|
351
|
-
INSERT INTO usage_events (id, session_id, platform, connection_type, tokens, event_type, recorded_at)
|
|
352
|
-
VALUES (?, ?, ?, ?, ?, 'session_save', ?)
|
|
350
|
+
db.prepare(`
|
|
351
|
+
INSERT INTO usage_events (id, session_id, platform, connection_type, tokens, event_type, recorded_at)
|
|
352
|
+
VALUES (?, ?, ?, ?, ?, 'session_save', ?)
|
|
353
353
|
`).run(randomUUID(), id, platform, connection_type, token_count, now);
|
|
354
354
|
// Context window guard — use model-specific window when available (Gemini 1M vs Claude 200k)
|
|
355
355
|
const window_size = resolveContextWindow(platform, input.model);
|
|
@@ -366,16 +366,16 @@ export function updateSession(session_id, input) {
|
|
|
366
366
|
if (!existing)
|
|
367
367
|
return null;
|
|
368
368
|
const now = new Date().toISOString();
|
|
369
|
-
db.prepare(`
|
|
370
|
-
UPDATE sessions SET
|
|
371
|
-
summary = ?,
|
|
372
|
-
context = ?,
|
|
373
|
-
task_state = ?,
|
|
374
|
-
token_count = ?,
|
|
375
|
-
save_type = 'manual',
|
|
376
|
-
tags = COALESCE(?, tags),
|
|
377
|
-
created_at = ?
|
|
378
|
-
WHERE id = ?
|
|
369
|
+
db.prepare(`
|
|
370
|
+
UPDATE sessions SET
|
|
371
|
+
summary = ?,
|
|
372
|
+
context = ?,
|
|
373
|
+
task_state = ?,
|
|
374
|
+
token_count = ?,
|
|
375
|
+
save_type = 'manual',
|
|
376
|
+
tags = COALESCE(?, tags),
|
|
377
|
+
created_at = ?
|
|
378
|
+
WHERE id = ?
|
|
379
379
|
`).run(input.summary ?? null, input.context ? JSON.stringify(input.context) : null, input.task_state ? JSON.stringify(input.task_state) : null, input.token_count ?? 0,
|
|
380
380
|
// Only overwrite tags when the caller supplies them; otherwise keep existing
|
|
381
381
|
// (COALESCE(NULL, tags) = tags). saveSession serializes tags the same way.
|
|
@@ -431,10 +431,10 @@ export function saveCouncilOutcome(input) {
|
|
|
431
431
|
const db = getDb();
|
|
432
432
|
const id = randomUUID();
|
|
433
433
|
const now = new Date().toISOString();
|
|
434
|
-
db.prepare(`
|
|
435
|
-
INSERT INTO council_outcomes
|
|
436
|
-
(id, session_id, task, verdict, lead_dev, pm, architect, ux, devil, legal, security, recommended, debated_at, duration_ms, project_dir)
|
|
437
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
434
|
+
db.prepare(`
|
|
435
|
+
INSERT INTO council_outcomes
|
|
436
|
+
(id, session_id, task, verdict, lead_dev, pm, architect, ux, devil, legal, security, recommended, debated_at, duration_ms, project_dir)
|
|
437
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
438
438
|
`).run(id, input.session_id ?? null, input.task, input.verdict, input.lead_dev, input.pm, input.architect, input.ux, input.devil, input.legal, input.security, input.recommended, now, input.duration_ms ?? 0, normalizeProjectDir(input.project_dir) ?? null);
|
|
439
439
|
return id;
|
|
440
440
|
}
|
|
@@ -442,9 +442,9 @@ export function storeKnowledge(input) {
|
|
|
442
442
|
const db = getDb();
|
|
443
443
|
const id = randomUUID();
|
|
444
444
|
const now = new Date().toISOString();
|
|
445
|
-
db.prepare(`
|
|
446
|
-
INSERT INTO knowledge_base (id, type, title, content, tags, project_dir, session_id, relevance, created_at, updated_at)
|
|
447
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
445
|
+
db.prepare(`
|
|
446
|
+
INSERT INTO knowledge_base (id, type, title, content, tags, project_dir, session_id, relevance, created_at, updated_at)
|
|
447
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
448
448
|
`).run(id, input.type ?? 'solution', input.title, input.content, input.tags ? JSON.stringify(input.tags) : null, normalizeProjectDir(input.project_dir) ?? null, input.session_id ?? null, input.relevance ?? 1.0, now, now);
|
|
449
449
|
return id;
|
|
450
450
|
}
|
|
@@ -489,16 +489,16 @@ export function updateProjectMap(input) {
|
|
|
489
489
|
const key_modules = input.key_modules ? JSON.stringify(input.key_modules) : null;
|
|
490
490
|
const tech_stack = input.tech_stack ? JSON.stringify(input.tech_stack) : null;
|
|
491
491
|
if (existing) {
|
|
492
|
-
db.prepare(`
|
|
493
|
-
UPDATE project_map SET structure = ?, key_modules = ?, tech_stack = ?, updated_at = ?
|
|
494
|
-
WHERE project_dir = ?
|
|
492
|
+
db.prepare(`
|
|
493
|
+
UPDATE project_map SET structure = ?, key_modules = ?, tech_stack = ?, updated_at = ?
|
|
494
|
+
WHERE project_dir = ?
|
|
495
495
|
`).run(structure, key_modules, tech_stack, now, project_dir);
|
|
496
496
|
return existing.id;
|
|
497
497
|
}
|
|
498
498
|
const id = randomUUID();
|
|
499
|
-
db.prepare(`
|
|
500
|
-
INSERT INTO project_map (id, project_dir, structure, key_modules, tech_stack, updated_at)
|
|
501
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
499
|
+
db.prepare(`
|
|
500
|
+
INSERT INTO project_map (id, project_dir, structure, key_modules, tech_stack, updated_at)
|
|
501
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
502
502
|
`).run(id, project_dir, structure, key_modules, tech_stack, now);
|
|
503
503
|
return id;
|
|
504
504
|
}
|
|
@@ -512,15 +512,15 @@ export function upsertPattern(input) {
|
|
|
512
512
|
const existing = db.prepare('SELECT id, seen_count, confidence FROM patterns WHERE pattern_key = ?').get(input.pattern_key);
|
|
513
513
|
if (existing) {
|
|
514
514
|
const newConfidence = Math.min(1.0, (existing.confidence + (input.confidence ?? 1.0)) / 2);
|
|
515
|
-
db.prepare(`
|
|
516
|
-
UPDATE patterns SET pattern_val = ?, confidence = ?, seen_count = seen_count + 1, updated_at = ?
|
|
517
|
-
WHERE pattern_key = ?
|
|
515
|
+
db.prepare(`
|
|
516
|
+
UPDATE patterns SET pattern_val = ?, confidence = ?, seen_count = seen_count + 1, updated_at = ?
|
|
517
|
+
WHERE pattern_key = ?
|
|
518
518
|
`).run(input.pattern_val, newConfidence, now, input.pattern_key);
|
|
519
519
|
}
|
|
520
520
|
else {
|
|
521
|
-
db.prepare(`
|
|
522
|
-
INSERT INTO patterns (id, pattern_key, pattern_val, confidence, seen_count, updated_at)
|
|
523
|
-
VALUES (?, ?, ?, ?, 1, ?)
|
|
521
|
+
db.prepare(`
|
|
522
|
+
INSERT INTO patterns (id, pattern_key, pattern_val, confidence, seen_count, updated_at)
|
|
523
|
+
VALUES (?, ?, ?, ?, 1, ?)
|
|
524
524
|
`).run(randomUUID(), input.pattern_key, input.pattern_val, input.confidence ?? 1.0, now);
|
|
525
525
|
}
|
|
526
526
|
}
|
|
@@ -589,9 +589,9 @@ export async function fetchAndCacheDocs(package_name, ecosystem, version, max_ch
|
|
|
589
589
|
content = `# ${package_name}@${resolved_version}\n${json.crate.description}\nDocs: ${json.crate.documentation}`;
|
|
590
590
|
}
|
|
591
591
|
const now = new Date().toISOString();
|
|
592
|
-
db.prepare(`
|
|
593
|
-
INSERT OR REPLACE INTO docs_cache (id, package_name, ecosystem, version, content, fetched_at)
|
|
594
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
592
|
+
db.prepare(`
|
|
593
|
+
INSERT OR REPLACE INTO docs_cache (id, package_name, ecosystem, version, content, fetched_at)
|
|
594
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
595
595
|
`).run(randomUUID(), package_name, ecosystem, resolved_version, content, now);
|
|
596
596
|
return { package_name, version: resolved_version, ecosystem, content: content.slice(0, max_chars), cached: false, fetched_at: now };
|
|
597
597
|
}
|
|
@@ -606,20 +606,20 @@ export async function fetchAndCacheDocs(package_name, ecosystem, version, max_ch
|
|
|
606
606
|
export function saveTaskPlan(plan_json, description_hash, project_dir) {
|
|
607
607
|
const db = getDb();
|
|
608
608
|
const id = randomUUID();
|
|
609
|
-
db.prepare(`
|
|
610
|
-
INSERT INTO task_plans (id, description_hash, plan_json, project_dir, created_at)
|
|
611
|
-
VALUES (?, ?, ?, ?, datetime('now'))
|
|
609
|
+
db.prepare(`
|
|
610
|
+
INSERT INTO task_plans (id, description_hash, plan_json, project_dir, created_at)
|
|
611
|
+
VALUES (?, ?, ?, ?, datetime('now'))
|
|
612
612
|
`).run(id, description_hash, plan_json, project_dir ?? null);
|
|
613
613
|
return id;
|
|
614
614
|
}
|
|
615
615
|
export function getTaskPlan(description_hash) {
|
|
616
616
|
const db = getDb();
|
|
617
|
-
const row = db.prepare(`
|
|
618
|
-
SELECT id, plan_json FROM task_plans
|
|
619
|
-
WHERE description_hash = ?
|
|
620
|
-
AND created_at > datetime('now', '-7 days')
|
|
621
|
-
ORDER BY created_at DESC
|
|
622
|
-
LIMIT 1
|
|
617
|
+
const row = db.prepare(`
|
|
618
|
+
SELECT id, plan_json FROM task_plans
|
|
619
|
+
WHERE description_hash = ?
|
|
620
|
+
AND created_at > datetime('now', '-7 days')
|
|
621
|
+
ORDER BY created_at DESC
|
|
622
|
+
LIMIT 1
|
|
623
623
|
`).get(description_hash);
|
|
624
624
|
return row ?? null;
|
|
625
625
|
}
|
|
@@ -660,11 +660,11 @@ export function getUsageStatus() {
|
|
|
660
660
|
// Today's requests from rate_usage
|
|
661
661
|
const rateRows = db.prepare('SELECT platform, request_count FROM rate_usage WHERE date_key = ?').all(today);
|
|
662
662
|
// Today's tokens + connection_type breakdown from usage_events
|
|
663
|
-
const eventRows = db.prepare(`
|
|
664
|
-
SELECT platform, connection_type, SUM(tokens) as total_tokens, COUNT(*) as cnt
|
|
665
|
-
FROM usage_events
|
|
666
|
-
WHERE DATE(recorded_at) = ?
|
|
667
|
-
GROUP BY platform, connection_type
|
|
663
|
+
const eventRows = db.prepare(`
|
|
664
|
+
SELECT platform, connection_type, SUM(tokens) as total_tokens, COUNT(*) as cnt
|
|
665
|
+
FROM usage_events
|
|
666
|
+
WHERE DATE(recorded_at) = ?
|
|
667
|
+
GROUP BY platform, connection_type
|
|
668
668
|
`).all(today);
|
|
669
669
|
const platforms = ['claude', 'gemini', 'codex'];
|
|
670
670
|
const by_platform = platforms.map(p => {
|
|
@@ -683,12 +683,12 @@ export function getUsageStatus() {
|
|
|
683
683
|
};
|
|
684
684
|
});
|
|
685
685
|
// Last 7 days history
|
|
686
|
-
const history = db.prepare(`
|
|
687
|
-
SELECT DATE(recorded_at) as date, COUNT(*) as total_requests, SUM(tokens) as total_tokens
|
|
688
|
-
FROM usage_events
|
|
689
|
-
WHERE recorded_at >= date('now', '-7 days')
|
|
690
|
-
GROUP BY DATE(recorded_at)
|
|
691
|
-
ORDER BY date DESC
|
|
686
|
+
const history = db.prepare(`
|
|
687
|
+
SELECT DATE(recorded_at) as date, COUNT(*) as total_requests, SUM(tokens) as total_tokens
|
|
688
|
+
FROM usage_events
|
|
689
|
+
WHERE recorded_at >= date('now', '-7 days')
|
|
690
|
+
GROUP BY DATE(recorded_at)
|
|
691
|
+
ORDER BY date DESC
|
|
692
692
|
`).all();
|
|
693
693
|
// Warnings
|
|
694
694
|
const warnings = [];
|
|
@@ -796,7 +796,7 @@ export function logUsage(entry) {
|
|
|
796
796
|
const db = getDb();
|
|
797
797
|
const estimated_tokens = Math.ceil(entry.output.length / 4);
|
|
798
798
|
const exceeded = estimated_tokens > entry.max_tokens ? 1 : 0;
|
|
799
|
-
db.prepare(`INSERT INTO usage_log (id, tool_name, session_id, max_tokens, estimated_tokens, exceeded, created_at)
|
|
799
|
+
db.prepare(`INSERT INTO usage_log (id, tool_name, session_id, max_tokens, estimated_tokens, exceeded, created_at)
|
|
800
800
|
VALUES (?, ?, ?, ?, ?, ?, datetime('now'))`).run(randomUUID(), entry.tool_name, entry.session_id ?? null, entry.max_tokens, estimated_tokens, exceeded);
|
|
801
801
|
return { exceeded: exceeded === 1, estimated_tokens };
|
|
802
802
|
}
|
|
@@ -814,16 +814,16 @@ export function upsertContextUsage(opts) {
|
|
|
814
814
|
const db = getDb();
|
|
815
815
|
const usage_pct = Math.round((opts.token_count / opts.context_window) * 100 * 10) / 10;
|
|
816
816
|
const now = new Date().toISOString();
|
|
817
|
-
db.prepare(`
|
|
818
|
-
INSERT INTO context_usage (platform, model, token_count, context_window, usage_pct, session_id, updated_at)
|
|
819
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
820
|
-
ON CONFLICT(platform) DO UPDATE SET
|
|
821
|
-
model = excluded.model,
|
|
822
|
-
token_count = excluded.token_count,
|
|
823
|
-
context_window = excluded.context_window,
|
|
824
|
-
usage_pct = excluded.usage_pct,
|
|
825
|
-
session_id = excluded.session_id,
|
|
826
|
-
updated_at = excluded.updated_at
|
|
817
|
+
db.prepare(`
|
|
818
|
+
INSERT INTO context_usage (platform, model, token_count, context_window, usage_pct, session_id, updated_at)
|
|
819
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
820
|
+
ON CONFLICT(platform) DO UPDATE SET
|
|
821
|
+
model = excluded.model,
|
|
822
|
+
token_count = excluded.token_count,
|
|
823
|
+
context_window = excluded.context_window,
|
|
824
|
+
usage_pct = excluded.usage_pct,
|
|
825
|
+
session_id = excluded.session_id,
|
|
826
|
+
updated_at = excluded.updated_at
|
|
827
827
|
`).run(opts.platform, opts.model ?? null, opts.token_count, opts.context_window, usage_pct, opts.session_id ?? null, now);
|
|
828
828
|
}
|
|
829
829
|
export function getContextUsage(platform) {
|