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.
Files changed (82) hide show
  1. package/README.md +301 -0
  2. package/dist/cli/commands/compacts.d.ts +11 -0
  3. package/dist/cli/commands/compacts.d.ts.map +1 -0
  4. package/dist/cli/commands/compacts.js +68 -0
  5. package/dist/cli/commands/compacts.js.map +1 -0
  6. package/dist/cli/commands/context.d.ts +8 -0
  7. package/dist/cli/commands/context.d.ts.map +1 -0
  8. package/dist/cli/commands/context.js +78 -0
  9. package/dist/cli/commands/context.js.map +1 -0
  10. package/dist/cli/commands/cost.d.ts +12 -0
  11. package/dist/cli/commands/cost.d.ts.map +1 -0
  12. package/dist/cli/commands/cost.js +52 -0
  13. package/dist/cli/commands/cost.js.map +1 -0
  14. package/dist/cli/commands/memory.d.ts +36 -0
  15. package/dist/cli/commands/memory.d.ts.map +1 -0
  16. package/dist/cli/commands/memory.js +139 -0
  17. package/dist/cli/commands/memory.js.map +1 -0
  18. package/dist/cli/commands/session.d.ts +10 -0
  19. package/dist/cli/commands/session.d.ts.map +1 -0
  20. package/dist/cli/commands/session.js +95 -0
  21. package/dist/cli/commands/session.js.map +1 -0
  22. package/dist/cli/commands/status.d.ts +9 -0
  23. package/dist/cli/commands/status.d.ts.map +1 -0
  24. package/dist/cli/commands/status.js +68 -0
  25. package/dist/cli/commands/status.js.map +1 -0
  26. package/dist/cli/commands/suggest.d.ts +11 -0
  27. package/dist/cli/commands/suggest.d.ts.map +1 -0
  28. package/dist/cli/commands/suggest.js +68 -0
  29. package/dist/cli/commands/suggest.js.map +1 -0
  30. package/dist/cli/format.d.ts +29 -0
  31. package/dist/cli/format.d.ts.map +1 -0
  32. package/dist/cli/format.js +125 -0
  33. package/dist/cli/format.js.map +1 -0
  34. package/dist/core/config.d.ts +63 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +92 -0
  37. package/dist/core/config.js.map +1 -0
  38. package/dist/core/db.d.ts +87 -0
  39. package/dist/core/db.d.ts.map +1 -0
  40. package/dist/core/db.js +263 -0
  41. package/dist/core/db.js.map +1 -0
  42. package/dist/core/jsonl-parser.d.ts +55 -0
  43. package/dist/core/jsonl-parser.d.ts.map +1 -0
  44. package/dist/core/jsonl-parser.js +79 -0
  45. package/dist/core/jsonl-parser.js.map +1 -0
  46. package/dist/core/memory-editor.d.ts +18 -0
  47. package/dist/core/memory-editor.d.ts.map +1 -0
  48. package/dist/core/memory-editor.js +125 -0
  49. package/dist/core/memory-editor.js.map +1 -0
  50. package/dist/core/session-store.d.ts +35 -0
  51. package/dist/core/session-store.d.ts.map +1 -0
  52. package/dist/core/session-store.js +66 -0
  53. package/dist/core/session-store.js.map +1 -0
  54. package/dist/core/watcher.d.ts +19 -0
  55. package/dist/core/watcher.d.ts.map +1 -0
  56. package/dist/core/watcher.js +83 -0
  57. package/dist/core/watcher.js.map +1 -0
  58. package/dist/daemon.d.ts +3 -0
  59. package/dist/daemon.d.ts.map +1 -0
  60. package/dist/daemon.js +147 -0
  61. package/dist/daemon.js.map +1 -0
  62. package/dist/engines/compact-diff.d.ts +19 -0
  63. package/dist/engines/compact-diff.d.ts.map +1 -0
  64. package/dist/engines/compact-diff.js +124 -0
  65. package/dist/engines/compact-diff.js.map +1 -0
  66. package/dist/engines/cost.d.ts +73 -0
  67. package/dist/engines/cost.d.ts.map +1 -0
  68. package/dist/engines/cost.js +149 -0
  69. package/dist/engines/cost.js.map +1 -0
  70. package/dist/engines/file-analyzer.d.ts +28 -0
  71. package/dist/engines/file-analyzer.d.ts.map +1 -0
  72. package/dist/engines/file-analyzer.js +139 -0
  73. package/dist/engines/file-analyzer.js.map +1 -0
  74. package/dist/engines/rule-engine.d.ts +25 -0
  75. package/dist/engines/rule-engine.d.ts.map +1 -0
  76. package/dist/engines/rule-engine.js +209 -0
  77. package/dist/engines/rule-engine.js.map +1 -0
  78. package/dist/index.d.ts +3 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +207 -0
  81. package/dist/index.js.map +1 -0
  82. 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"}