clawprobe 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +301 -0
- package/dist/cli/commands/compacts.d.ts +11 -0
- package/dist/cli/commands/compacts.d.ts.map +1 -0
- package/dist/cli/commands/compacts.js +68 -0
- package/dist/cli/commands/compacts.js.map +1 -0
- package/dist/cli/commands/context.d.ts +8 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +78 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/cost.d.ts +12 -0
- package/dist/cli/commands/cost.d.ts.map +1 -0
- package/dist/cli/commands/cost.js +52 -0
- package/dist/cli/commands/cost.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +36 -0
- package/dist/cli/commands/memory.d.ts.map +1 -0
- package/dist/cli/commands/memory.js +139 -0
- package/dist/cli/commands/memory.js.map +1 -0
- package/dist/cli/commands/session.d.ts +10 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +95 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/status.d.ts +9 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +68 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/suggest.d.ts +11 -0
- package/dist/cli/commands/suggest.d.ts.map +1 -0
- package/dist/cli/commands/suggest.js +68 -0
- package/dist/cli/commands/suggest.js.map +1 -0
- package/dist/cli/format.d.ts +29 -0
- package/dist/cli/format.d.ts.map +1 -0
- package/dist/cli/format.js +125 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/core/config.d.ts +63 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +92 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/db.d.ts +87 -0
- package/dist/core/db.d.ts.map +1 -0
- package/dist/core/db.js +263 -0
- package/dist/core/db.js.map +1 -0
- package/dist/core/jsonl-parser.d.ts +55 -0
- package/dist/core/jsonl-parser.d.ts.map +1 -0
- package/dist/core/jsonl-parser.js +79 -0
- package/dist/core/jsonl-parser.js.map +1 -0
- package/dist/core/memory-editor.d.ts +18 -0
- package/dist/core/memory-editor.d.ts.map +1 -0
- package/dist/core/memory-editor.js +125 -0
- package/dist/core/memory-editor.js.map +1 -0
- package/dist/core/session-store.d.ts +35 -0
- package/dist/core/session-store.d.ts.map +1 -0
- package/dist/core/session-store.js +66 -0
- package/dist/core/session-store.js.map +1 -0
- package/dist/core/watcher.d.ts +19 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +83 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +147 -0
- package/dist/daemon.js.map +1 -0
- package/dist/engines/compact-diff.d.ts +19 -0
- package/dist/engines/compact-diff.d.ts.map +1 -0
- package/dist/engines/compact-diff.js +124 -0
- package/dist/engines/compact-diff.js.map +1 -0
- package/dist/engines/cost.d.ts +73 -0
- package/dist/engines/cost.d.ts.map +1 -0
- package/dist/engines/cost.js +149 -0
- package/dist/engines/cost.js.map +1 -0
- package/dist/engines/file-analyzer.d.ts +28 -0
- package/dist/engines/file-analyzer.d.ts.map +1 -0
- package/dist/engines/file-analyzer.js +139 -0
- package/dist/engines/file-analyzer.js.map +1 -0
- package/dist/engines/rule-engine.d.ts +25 -0
- package/dist/engines/rule-engine.d.ts.map +1 -0
- package/dist/engines/rule-engine.js +209 -0
- package/dist/engines/rule-engine.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +207 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { getCompactedMessages } from "../core/jsonl-parser.js";
|
|
2
|
+
// Patterns that signal important content
|
|
3
|
+
const PREFERENCE_PATTERNS = [
|
|
4
|
+
/\b(use|prefer|always|never|don'?t|avoid|must|should|require|need)\b/i,
|
|
5
|
+
/\bnot\s+(use|do|allow|want)\b/i,
|
|
6
|
+
/\binstead\s+of\b/i,
|
|
7
|
+
];
|
|
8
|
+
const TECHNICAL_PATTERNS = [
|
|
9
|
+
/[./\\][a-zA-Z0-9_-]+\.[a-zA-Z]{1,10}/, // file paths
|
|
10
|
+
/\b[A-Z_]{2,}\b/, // CONSTANTS / env vars
|
|
11
|
+
/`[^`]+`/, // inline code
|
|
12
|
+
/```[\s\S]+?```/, // code blocks
|
|
13
|
+
/\b(port|host|url|api|key|token|secret|password|config|env)\b/i,
|
|
14
|
+
/https?:\/\//, // URLs
|
|
15
|
+
];
|
|
16
|
+
const ENTITY_PATTERNS = [
|
|
17
|
+
/\b[A-Z][a-z]+(?:[A-Z][a-z]+)+\b/, // CamelCase names
|
|
18
|
+
/\b(project|repo|database|service|component|module|package)\s+\w+/i,
|
|
19
|
+
];
|
|
20
|
+
const DECISION_PATTERNS = [
|
|
21
|
+
/\b(decided|agreed|confirmed|settled on|going with|chose|selected)\b/i,
|
|
22
|
+
/\b(the plan is|we will|I will|let's)\b/i,
|
|
23
|
+
];
|
|
24
|
+
export function scoreLoss(message, summaryText) {
|
|
25
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
26
|
+
return { score: 0, reasons: [] };
|
|
27
|
+
}
|
|
28
|
+
const content = message.content;
|
|
29
|
+
const lowerContent = content.toLowerCase();
|
|
30
|
+
const lowerSummary = summaryText.toLowerCase();
|
|
31
|
+
const reasons = [];
|
|
32
|
+
let score = 0;
|
|
33
|
+
// Check preference patterns
|
|
34
|
+
for (const pattern of PREFERENCE_PATTERNS) {
|
|
35
|
+
const match = pattern.exec(content);
|
|
36
|
+
if (match) {
|
|
37
|
+
// Only flag if the surrounding phrase doesn't appear in summary
|
|
38
|
+
const phrase = extractPhrase(content, match.index, 40);
|
|
39
|
+
if (phrase && !lowerSummary.includes(phrase.toLowerCase().slice(0, 20))) {
|
|
40
|
+
score += 0.3;
|
|
41
|
+
reasons.push("Preference or constraint statement");
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Check technical content
|
|
47
|
+
for (const pattern of TECHNICAL_PATTERNS) {
|
|
48
|
+
const match = pattern.exec(content);
|
|
49
|
+
if (match) {
|
|
50
|
+
const val = match[0].slice(0, 30);
|
|
51
|
+
if (!lowerSummary.includes(val.toLowerCase())) {
|
|
52
|
+
score += 0.25;
|
|
53
|
+
reasons.push("Technical detail (code, path, config)");
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Check entity mentions
|
|
59
|
+
for (const pattern of ENTITY_PATTERNS) {
|
|
60
|
+
const match = pattern.exec(content);
|
|
61
|
+
if (match) {
|
|
62
|
+
const val = match[0].toLowerCase();
|
|
63
|
+
if (!lowerSummary.includes(val)) {
|
|
64
|
+
score += 0.2;
|
|
65
|
+
reasons.push("Named entity or project reference");
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Check decision language
|
|
71
|
+
for (const pattern of DECISION_PATTERNS) {
|
|
72
|
+
if (pattern.test(content)) {
|
|
73
|
+
score += 0.25;
|
|
74
|
+
reasons.push("Decision or agreement statement");
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// User messages are generally more important (explicit instructions)
|
|
79
|
+
if (message.role === "user" && score > 0) {
|
|
80
|
+
score = Math.min(score * 1.2, 1.0);
|
|
81
|
+
}
|
|
82
|
+
// Long messages with no keywords — probably just conversation
|
|
83
|
+
if (score === 0 && lowerContent.length > 200) {
|
|
84
|
+
score = 0.05;
|
|
85
|
+
reasons.push("Long message (may contain context)");
|
|
86
|
+
}
|
|
87
|
+
return { score: Math.min(score, 1.0), reasons };
|
|
88
|
+
}
|
|
89
|
+
export function analyzeCompaction(event, allEntries, previousFirstKeptId) {
|
|
90
|
+
const compactedMessages = getCompactedMessages(allEntries, event, previousFirstKeptId);
|
|
91
|
+
const losses = [];
|
|
92
|
+
for (const msg of compactedMessages) {
|
|
93
|
+
const { score, reasons } = scoreLoss(msg, event.summaryText);
|
|
94
|
+
if (score >= 0.2) {
|
|
95
|
+
losses.push({ message: msg, score, reasons });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Sort by score descending
|
|
99
|
+
losses.sort((a, b) => b.score - a.score);
|
|
100
|
+
const quality = determineQuality(losses, compactedMessages.length);
|
|
101
|
+
return {
|
|
102
|
+
event,
|
|
103
|
+
compactedMessages,
|
|
104
|
+
importantLosses: losses,
|
|
105
|
+
summaryQuality: quality,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function determineQuality(losses, totalMessages) {
|
|
109
|
+
const criticalLosses = losses.filter((l) => l.score >= 0.5).length;
|
|
110
|
+
const moderateLosses = losses.filter((l) => l.score >= 0.2).length;
|
|
111
|
+
if (criticalLosses >= 2 || (totalMessages > 5 && criticalLosses >= 1)) {
|
|
112
|
+
return "poor";
|
|
113
|
+
}
|
|
114
|
+
if (moderateLosses >= 2) {
|
|
115
|
+
return "partial";
|
|
116
|
+
}
|
|
117
|
+
return "good";
|
|
118
|
+
}
|
|
119
|
+
function extractPhrase(text, index, maxLen) {
|
|
120
|
+
const start = Math.max(0, index - 10);
|
|
121
|
+
const end = Math.min(text.length, index + maxLen);
|
|
122
|
+
return text.slice(start, end).replace(/\s+/g, " ").trim();
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=compact-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-diff.js","sourceRoot":"","sources":["../../src/engines/compact-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
export declare const MODEL_PRICES: Record<string, {
|
|
3
|
+
input: number;
|
|
4
|
+
output: number;
|
|
5
|
+
}>;
|
|
6
|
+
export interface TokenCount {
|
|
7
|
+
input: number;
|
|
8
|
+
output: number;
|
|
9
|
+
}
|
|
10
|
+
export interface DailyCost {
|
|
11
|
+
date: string;
|
|
12
|
+
usd: number;
|
|
13
|
+
inputTokens: number;
|
|
14
|
+
outputTokens: number;
|
|
15
|
+
}
|
|
16
|
+
export interface PeriodCostSummary {
|
|
17
|
+
period: string;
|
|
18
|
+
startDate: string;
|
|
19
|
+
endDate: string;
|
|
20
|
+
totalUsd: number;
|
|
21
|
+
inputTokens: number;
|
|
22
|
+
outputTokens: number;
|
|
23
|
+
dailyAvg: number;
|
|
24
|
+
monthEstimate: number;
|
|
25
|
+
daily: DailyCost[];
|
|
26
|
+
model?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SessionCost {
|
|
29
|
+
sessionKey: string;
|
|
30
|
+
model: string | null;
|
|
31
|
+
provider: string | null;
|
|
32
|
+
inputTokens: number;
|
|
33
|
+
outputTokens: number;
|
|
34
|
+
totalTokens: number;
|
|
35
|
+
estimatedUsd: number;
|
|
36
|
+
startedAt: number;
|
|
37
|
+
lastActiveAt: number;
|
|
38
|
+
durationMin: number;
|
|
39
|
+
compactionCount: number;
|
|
40
|
+
costAccurate: boolean;
|
|
41
|
+
turns: TurnCost[];
|
|
42
|
+
}
|
|
43
|
+
export interface TurnCost {
|
|
44
|
+
turnIndex: number;
|
|
45
|
+
timestamp: number;
|
|
46
|
+
inputTokensDelta: number;
|
|
47
|
+
outputTokensDelta: number;
|
|
48
|
+
estimatedUsd: number;
|
|
49
|
+
compactOccurred: boolean;
|
|
50
|
+
}
|
|
51
|
+
export declare function estimateCost(tokens: TokenCount, model: string | null, customPrices?: Record<string, {
|
|
52
|
+
input: number;
|
|
53
|
+
output: number;
|
|
54
|
+
}>): number;
|
|
55
|
+
export declare function getSessionCost(db: DatabaseSync, agent: string, sessionKey: string, customPrices?: Record<string, {
|
|
56
|
+
input: number;
|
|
57
|
+
output: number;
|
|
58
|
+
}>): SessionCost | null;
|
|
59
|
+
export declare function getAllSessionCosts(db: DatabaseSync, agent: string, customPrices?: Record<string, {
|
|
60
|
+
input: number;
|
|
61
|
+
output: number;
|
|
62
|
+
}>): SessionCost[];
|
|
63
|
+
export declare function getPeriodCost(db: DatabaseSync, agent: string, period: "day" | "week" | "month" | "all", customPrices?: Record<string, {
|
|
64
|
+
input: number;
|
|
65
|
+
output: number;
|
|
66
|
+
}>): PeriodCostSummary;
|
|
67
|
+
export declare function recordDailyCost(db: DatabaseSync, agent: string, sessionKey: string, date: string, inputDelta: number, outputDelta: number, model: string | null, customPrices?: Record<string, {
|
|
68
|
+
input: number;
|
|
69
|
+
output: number;
|
|
70
|
+
}>): void;
|
|
71
|
+
export declare function formatDate(d: Date): string;
|
|
72
|
+
export declare function todayString(): string;
|
|
73
|
+
//# sourceMappingURL=cost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/engines/cost.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { getDailyCostSummary, getAllSessionKeys, getAllSnapshots, upsertCostRecord, } from "../core/db.js";
|
|
2
|
+
// USD per 1M tokens
|
|
3
|
+
export const MODEL_PRICES = {
|
|
4
|
+
// Anthropic
|
|
5
|
+
"anthropic/claude-opus-4": { input: 15.00, output: 75.00 },
|
|
6
|
+
"anthropic/claude-sonnet-4.5": { input: 3.00, output: 15.00 },
|
|
7
|
+
"anthropic/claude-haiku-3.5": { input: 0.80, output: 4.00 },
|
|
8
|
+
// OpenAI
|
|
9
|
+
"openai/gpt-5.4": { input: 5.00, output: 20.00 },
|
|
10
|
+
"openai/gpt-5.4-mini": { input: 0.30, output: 1.20 },
|
|
11
|
+
"openai/o4-mini": { input: 1.10, output: 4.40 },
|
|
12
|
+
// Google
|
|
13
|
+
"google/gemini-3.1-flash": { input: 0.075, output: 0.30 },
|
|
14
|
+
"google/gemini-3.1-pro": { input: 1.25, output: 5.00 },
|
|
15
|
+
// DeepSeek
|
|
16
|
+
"deepseek/deepseek-v3": { input: 0.27, output: 1.10 },
|
|
17
|
+
"deepseek/deepseek-r2": { input: 0.55, output: 2.19 },
|
|
18
|
+
};
|
|
19
|
+
export function estimateCost(tokens, model, customPrices = {}) {
|
|
20
|
+
if (!model)
|
|
21
|
+
return 0;
|
|
22
|
+
const prices = { ...MODEL_PRICES, ...customPrices };
|
|
23
|
+
// Try exact match first, then prefix-match (e.g. "claude-sonnet" → anthropic/claude-sonnet-*)
|
|
24
|
+
const price = prices[model] ??
|
|
25
|
+
Object.entries(prices).find(([key]) => model.includes(key.split("/")[1] ?? key))?.[1];
|
|
26
|
+
if (!price)
|
|
27
|
+
return 0;
|
|
28
|
+
return (tokens.input / 1_000_000) * price.input +
|
|
29
|
+
(tokens.output / 1_000_000) * price.output;
|
|
30
|
+
}
|
|
31
|
+
export function getSessionCost(db, agent, sessionKey, customPrices = {}) {
|
|
32
|
+
const snapshots = getAllSnapshots(db, agent, sessionKey);
|
|
33
|
+
if (snapshots.length === 0)
|
|
34
|
+
return null;
|
|
35
|
+
const first = snapshots[0];
|
|
36
|
+
const last = snapshots[snapshots.length - 1];
|
|
37
|
+
const inputDelta = last.input_tokens - first.input_tokens;
|
|
38
|
+
const outputDelta = last.output_tokens - first.output_tokens;
|
|
39
|
+
const model = last.model ?? first.model;
|
|
40
|
+
const turns = [];
|
|
41
|
+
for (let i = 1; i < snapshots.length; i++) {
|
|
42
|
+
const prev = snapshots[i - 1];
|
|
43
|
+
const curr = snapshots[i];
|
|
44
|
+
const inDelta = curr.input_tokens - prev.input_tokens;
|
|
45
|
+
const outDelta = curr.output_tokens - prev.output_tokens;
|
|
46
|
+
const compactOccurred = curr.compaction_count > prev.compaction_count;
|
|
47
|
+
turns.push({
|
|
48
|
+
turnIndex: i,
|
|
49
|
+
timestamp: curr.sampled_at,
|
|
50
|
+
inputTokensDelta: inDelta,
|
|
51
|
+
outputTokensDelta: outDelta,
|
|
52
|
+
estimatedUsd: estimateCost({ input: inDelta, output: outDelta }, model, customPrices),
|
|
53
|
+
compactOccurred,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
sessionKey,
|
|
58
|
+
model,
|
|
59
|
+
provider: last.provider ?? first.provider,
|
|
60
|
+
inputTokens: Math.max(0, inputDelta),
|
|
61
|
+
outputTokens: Math.max(0, outputDelta),
|
|
62
|
+
totalTokens: Math.max(0, inputDelta + outputDelta),
|
|
63
|
+
estimatedUsd: estimateCost({ input: Math.max(0, inputDelta), output: Math.max(0, outputDelta) }, model, customPrices),
|
|
64
|
+
startedAt: first.sampled_at,
|
|
65
|
+
lastActiveAt: last.sampled_at,
|
|
66
|
+
durationMin: Math.round((last.sampled_at - first.sampled_at) / 60),
|
|
67
|
+
compactionCount: last.compaction_count,
|
|
68
|
+
costAccurate: snapshots.length > 1,
|
|
69
|
+
turns,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function getAllSessionCosts(db, agent, customPrices = {}) {
|
|
73
|
+
const keys = getAllSessionKeys(db, agent);
|
|
74
|
+
return keys
|
|
75
|
+
.map(({ session_key }) => getSessionCost(db, agent, session_key, customPrices))
|
|
76
|
+
.filter((s) => s !== null);
|
|
77
|
+
}
|
|
78
|
+
export function getPeriodCost(db, agent, period, customPrices = {}) {
|
|
79
|
+
const now = new Date();
|
|
80
|
+
const today = formatDate(now);
|
|
81
|
+
let days;
|
|
82
|
+
let startDate;
|
|
83
|
+
let periodLabel;
|
|
84
|
+
switch (period) {
|
|
85
|
+
case "day":
|
|
86
|
+
days = 1;
|
|
87
|
+
startDate = today;
|
|
88
|
+
periodLabel = `Today (${today})`;
|
|
89
|
+
break;
|
|
90
|
+
case "week":
|
|
91
|
+
days = 7;
|
|
92
|
+
startDate = formatDate(new Date(now.getTime() - 6 * 86400_000));
|
|
93
|
+
periodLabel = `${startDate} – ${today}`;
|
|
94
|
+
break;
|
|
95
|
+
case "month":
|
|
96
|
+
days = 30;
|
|
97
|
+
startDate = formatDate(new Date(now.getTime() - 29 * 86400_000));
|
|
98
|
+
periodLabel = `${startDate} – ${today}`;
|
|
99
|
+
break;
|
|
100
|
+
case "all":
|
|
101
|
+
days = 3650;
|
|
102
|
+
startDate = "2020-01-01";
|
|
103
|
+
periodLabel = "All time";
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
const rows = getDailyCostSummary(db, agent, days);
|
|
107
|
+
const daily = rows.map((r) => ({
|
|
108
|
+
date: r.date,
|
|
109
|
+
usd: r.total_usd,
|
|
110
|
+
inputTokens: r.input_tokens,
|
|
111
|
+
outputTokens: r.output_tokens,
|
|
112
|
+
}));
|
|
113
|
+
const totalUsd = daily.reduce((s, d) => s + d.usd, 0);
|
|
114
|
+
const totalInput = daily.reduce((s, d) => s + d.inputTokens, 0);
|
|
115
|
+
const totalOutput = daily.reduce((s, d) => s + d.outputTokens, 0);
|
|
116
|
+
const activeDays = Math.max(daily.length, 1);
|
|
117
|
+
const dailyAvg = totalUsd / activeDays;
|
|
118
|
+
return {
|
|
119
|
+
period: periodLabel,
|
|
120
|
+
startDate,
|
|
121
|
+
endDate: today,
|
|
122
|
+
totalUsd,
|
|
123
|
+
inputTokens: totalInput,
|
|
124
|
+
outputTokens: totalOutput,
|
|
125
|
+
dailyAvg,
|
|
126
|
+
monthEstimate: dailyAvg * 30,
|
|
127
|
+
daily,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export function recordDailyCost(db, agent, sessionKey, date, inputDelta, outputDelta, model, customPrices = {}) {
|
|
131
|
+
const usd = estimateCost({ input: inputDelta, output: outputDelta }, model, customPrices);
|
|
132
|
+
upsertCostRecord(db, {
|
|
133
|
+
agent,
|
|
134
|
+
session_key: sessionKey,
|
|
135
|
+
date,
|
|
136
|
+
input_tokens: inputDelta,
|
|
137
|
+
output_tokens: outputDelta,
|
|
138
|
+
model,
|
|
139
|
+
estimated_usd: usd,
|
|
140
|
+
recorded_at: Math.floor(Date.now() / 1000),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
export function formatDate(d) {
|
|
144
|
+
return d.toISOString().slice(0, 10);
|
|
145
|
+
}
|
|
146
|
+
export function todayString() {
|
|
147
|
+
return formatDate(new Date());
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=cost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/engines/cost.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
export interface WorkspaceFile {
|
|
3
|
+
name: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
rawChars: number;
|
|
6
|
+
injectedChars: number;
|
|
7
|
+
wasTruncated: boolean;
|
|
8
|
+
lostChars: number;
|
|
9
|
+
lostPercent: number;
|
|
10
|
+
estTokens: number;
|
|
11
|
+
injectedEstTokens: number;
|
|
12
|
+
exists: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface WorkspaceAnalysis {
|
|
15
|
+
files: WorkspaceFile[];
|
|
16
|
+
totalRawChars: number;
|
|
17
|
+
totalInjectedChars: number;
|
|
18
|
+
truncatedFiles: WorkspaceFile[];
|
|
19
|
+
bootstrapMaxChars: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function analyzeWorkspaceFiles(workspaceDir: string, bootstrapMaxChars: number): WorkspaceAnalysis;
|
|
22
|
+
export declare function snapshotWorkspaceFiles(db: DatabaseSync, agent: string, workspaceDir: string, bootstrapMaxChars: number): void;
|
|
23
|
+
export declare function getLatestWorkspaceAnalysis(db: DatabaseSync, agent: string, workspaceDir: string, bootstrapMaxChars: number): WorkspaceAnalysis;
|
|
24
|
+
export declare function getFileStaleness(workspaceDir: string): {
|
|
25
|
+
name: string;
|
|
26
|
+
daysSinceModified: number;
|
|
27
|
+
}[];
|
|
28
|
+
//# sourceMappingURL=file-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-analyzer.d.ts","sourceRoot":"","sources":["../../src/engines/file-analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAaD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GACxB,iBAAiB,CAuCnB;AA2CD,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GACxB,IAAI,CAcN;AAED,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GACxB,iBAAiB,CAiCnB;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,EAAE,CAapG"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { insertFileSnapshot, getLatestFileSnapshots } from "../core/db.js";
|
|
4
|
+
const WORKSPACE_FILES = [
|
|
5
|
+
"SOUL.md",
|
|
6
|
+
"AGENTS.md",
|
|
7
|
+
"TOOLS.md",
|
|
8
|
+
"USER.md",
|
|
9
|
+
"IDENTITY.md",
|
|
10
|
+
"MEMORY.md",
|
|
11
|
+
"HEARTBEAT.md",
|
|
12
|
+
"GLOBAL_AGENTS.md",
|
|
13
|
+
];
|
|
14
|
+
export function analyzeWorkspaceFiles(workspaceDir, bootstrapMaxChars) {
|
|
15
|
+
const files = [];
|
|
16
|
+
for (const name of WORKSPACE_FILES) {
|
|
17
|
+
const filePath = path.join(workspaceDir, name);
|
|
18
|
+
const wf = analyzeFile(name, filePath, bootstrapMaxChars);
|
|
19
|
+
files.push(wf);
|
|
20
|
+
}
|
|
21
|
+
// Also scan any extra .md files in the workspace root
|
|
22
|
+
if (fs.existsSync(workspaceDir)) {
|
|
23
|
+
const extra = fs
|
|
24
|
+
.readdirSync(workspaceDir)
|
|
25
|
+
.filter((f) => f.endsWith(".md") &&
|
|
26
|
+
!WORKSPACE_FILES.includes(f) &&
|
|
27
|
+
!f.startsWith("."));
|
|
28
|
+
for (const name of extra) {
|
|
29
|
+
const filePath = path.join(workspaceDir, name);
|
|
30
|
+
if (fs.statSync(filePath).isFile()) {
|
|
31
|
+
files.push(analyzeFile(name, filePath, bootstrapMaxChars));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const existing = files.filter((f) => f.exists);
|
|
36
|
+
const totalRawChars = existing.reduce((s, f) => s + f.rawChars, 0);
|
|
37
|
+
const totalInjectedChars = existing.reduce((s, f) => s + f.injectedChars, 0);
|
|
38
|
+
const truncatedFiles = existing.filter((f) => f.wasTruncated);
|
|
39
|
+
return {
|
|
40
|
+
files: existing.sort((a, b) => b.rawChars - a.rawChars),
|
|
41
|
+
totalRawChars,
|
|
42
|
+
totalInjectedChars,
|
|
43
|
+
truncatedFiles,
|
|
44
|
+
bootstrapMaxChars,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function analyzeFile(name, filePath, bootstrapMaxChars) {
|
|
48
|
+
if (!fs.existsSync(filePath)) {
|
|
49
|
+
return {
|
|
50
|
+
name,
|
|
51
|
+
filePath,
|
|
52
|
+
rawChars: 0,
|
|
53
|
+
injectedChars: 0,
|
|
54
|
+
wasTruncated: false,
|
|
55
|
+
lostChars: 0,
|
|
56
|
+
lostPercent: 0,
|
|
57
|
+
estTokens: 0,
|
|
58
|
+
injectedEstTokens: 0,
|
|
59
|
+
exists: false,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
63
|
+
const rawChars = content.length;
|
|
64
|
+
const injectedChars = Math.min(rawChars, bootstrapMaxChars);
|
|
65
|
+
const wasTruncated = rawChars > bootstrapMaxChars;
|
|
66
|
+
const lostChars = rawChars - injectedChars;
|
|
67
|
+
const lostPercent = rawChars > 0 ? (lostChars / rawChars) * 100 : 0;
|
|
68
|
+
return {
|
|
69
|
+
name,
|
|
70
|
+
filePath,
|
|
71
|
+
rawChars,
|
|
72
|
+
injectedChars,
|
|
73
|
+
wasTruncated,
|
|
74
|
+
lostChars,
|
|
75
|
+
lostPercent,
|
|
76
|
+
estTokens: Math.ceil(rawChars / 4),
|
|
77
|
+
injectedEstTokens: Math.ceil(injectedChars / 4),
|
|
78
|
+
exists: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export function snapshotWorkspaceFiles(db, agent, workspaceDir, bootstrapMaxChars) {
|
|
82
|
+
const analysis = analyzeWorkspaceFiles(workspaceDir, bootstrapMaxChars);
|
|
83
|
+
const now = Math.floor(Date.now() / 1000);
|
|
84
|
+
for (const f of analysis.files) {
|
|
85
|
+
insertFileSnapshot(db, {
|
|
86
|
+
agent,
|
|
87
|
+
file_path: f.filePath,
|
|
88
|
+
raw_chars: f.rawChars,
|
|
89
|
+
injected_chars: f.injectedChars,
|
|
90
|
+
was_truncated: f.wasTruncated ? 1 : 0,
|
|
91
|
+
sampled_at: now,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export function getLatestWorkspaceAnalysis(db, agent, workspaceDir, bootstrapMaxChars) {
|
|
96
|
+
const rows = getLatestFileSnapshots(db, agent);
|
|
97
|
+
if (rows.length === 0) {
|
|
98
|
+
// Fallback: read directly from disk
|
|
99
|
+
return analyzeWorkspaceFiles(workspaceDir, bootstrapMaxChars);
|
|
100
|
+
}
|
|
101
|
+
const files = rows.map((r) => {
|
|
102
|
+
const name = path.basename(r.file_path);
|
|
103
|
+
const lostChars = r.raw_chars - r.injected_chars;
|
|
104
|
+
const lostPercent = r.raw_chars > 0 ? (lostChars / r.raw_chars) * 100 : 0;
|
|
105
|
+
return {
|
|
106
|
+
name,
|
|
107
|
+
filePath: r.file_path,
|
|
108
|
+
rawChars: r.raw_chars,
|
|
109
|
+
injectedChars: r.injected_chars,
|
|
110
|
+
wasTruncated: r.was_truncated === 1,
|
|
111
|
+
lostChars,
|
|
112
|
+
lostPercent,
|
|
113
|
+
estTokens: Math.ceil(r.raw_chars / 4),
|
|
114
|
+
injectedEstTokens: Math.ceil(r.injected_chars / 4),
|
|
115
|
+
exists: true,
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
return {
|
|
119
|
+
files,
|
|
120
|
+
totalRawChars: files.reduce((s, f) => s + f.rawChars, 0),
|
|
121
|
+
totalInjectedChars: files.reduce((s, f) => s + f.injectedChars, 0),
|
|
122
|
+
truncatedFiles: files.filter((f) => f.wasTruncated),
|
|
123
|
+
bootstrapMaxChars,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function getFileStaleness(workspaceDir) {
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
const results = [];
|
|
129
|
+
for (const name of WORKSPACE_FILES) {
|
|
130
|
+
const filePath = path.join(workspaceDir, name);
|
|
131
|
+
if (!fs.existsSync(filePath))
|
|
132
|
+
continue;
|
|
133
|
+
const stat = fs.statSync(filePath);
|
|
134
|
+
const daysSince = (now - stat.mtimeMs) / 86400_000;
|
|
135
|
+
results.push({ name, daysSinceModified: Math.floor(daysSince) });
|
|
136
|
+
}
|
|
137
|
+
return results.sort((a, b) => b.daysSinceModified - a.daysSinceModified);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=file-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-analyzer.js","sourceRoot":"","sources":["../../src/engines/file-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import { ProbeConfig } from "../core/config.js";
|
|
3
|
+
export interface Suggestion {
|
|
4
|
+
ruleId: string;
|
|
5
|
+
severity: "critical" | "warning" | "info";
|
|
6
|
+
title: string;
|
|
7
|
+
detail: string;
|
|
8
|
+
action?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ProbeState {
|
|
11
|
+
db: DatabaseSync;
|
|
12
|
+
agent: string;
|
|
13
|
+
workspaceDir: string;
|
|
14
|
+
sessionsDir: string;
|
|
15
|
+
bootstrapMaxChars: number;
|
|
16
|
+
config: ProbeConfig;
|
|
17
|
+
}
|
|
18
|
+
export interface Rule {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
check(state: ProbeState): Suggestion | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function runRules(state: ProbeState, customRules?: Rule[]): Suggestion[];
|
|
24
|
+
export declare function persistSuggestions(db: DatabaseSync, agent: string, suggestions: Suggestion[]): void;
|
|
25
|
+
//# sourceMappingURL=rule-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-engine.d.ts","sourceRoot":"","sources":["../../src/engines/rule-engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,YAAY,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC;CAC7C;AAuMD,wBAAgB,QAAQ,CACtB,KAAK,EAAE,UAAU,EACjB,WAAW,GAAE,IAAI,EAAO,GACvB,UAAU,EAAE,CAiBd;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,UAAU,EAAE,GACxB,IAAI,CAwBN"}
|