vibedrift-shared 0.1.3

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.
@@ -0,0 +1,30 @@
1
+ import { SessionStats } from "./types";
2
+ /**
3
+ * Encode a filesystem path to match Claude's project directory naming.
4
+ * e.g. /Users/foo/Dev -> -Users-foo-Dev
5
+ */
6
+ export declare function encodeProjectPath(projectPath: string): string;
7
+ /**
8
+ * Find all Claude project directories that could match the given project path.
9
+ */
10
+ export declare function findClaudeProjectDirs(projectPath: string): string[];
11
+ /**
12
+ * Get sessions from the index that overlap with the given time window.
13
+ */
14
+ export declare function getSessionsInWindow(projectDirs: string[], since: Date, until: Date): Array<{
15
+ sessionId: string;
16
+ fullPath: string;
17
+ }>;
18
+ /**
19
+ * Parse a single JSONL session file and count interactions within a time window.
20
+ */
21
+ export declare function parseSessionFile(filePath: string, since: Date, until: Date): SessionStats | null;
22
+ /**
23
+ * Main entry point: parse all Claude sessions for a project within a time window.
24
+ * Returns aggregated stats and individual session details.
25
+ */
26
+ export declare function parseClaudeSessions(projectPath: string, since: Date, until: Date): {
27
+ aggregate: SessionStats;
28
+ sessions: SessionStats[];
29
+ };
30
+ //# sourceMappingURL=claude-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-parser.d.ts","sourceRoot":"","sources":["../src/claude-parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAgB,MAAM,SAAS,CAAC;AAsErD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBnE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EAAE,EACrB,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI,GACV,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgDhD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI,GACV,YAAY,GAAG,IAAI,CA8ErB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,IAAI,EACX,KAAK,EAAE,IAAI,GACV;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAkCvD"}
@@ -0,0 +1,222 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ function isCommand(content) {
4
+ const text = typeof content === "string" ? content : content.map((c) => c.text || "").join("");
5
+ return text.includes("<command-name>") || text.includes("<local-command");
6
+ }
7
+ function isSystemGenerated(content) {
8
+ const text = typeof content === "string"
9
+ ? content
10
+ : content.map((c) => c.text || "").join("");
11
+ const trimmed = text.trim();
12
+ if (trimmed === "[Request interrupted by user]")
13
+ return true;
14
+ if (trimmed.startsWith("[Request interrupted by user for tool use]"))
15
+ return true;
16
+ if (trimmed.startsWith("Implement the following plan:"))
17
+ return true;
18
+ if (trimmed.startsWith("<task-notification>"))
19
+ return true;
20
+ return false;
21
+ }
22
+ /**
23
+ * Strip the "[Request interrupted by user]" prefix from a message
24
+ * that also contains real user text (mid-processing interruption).
25
+ */
26
+ function stripInterruptPrefix(text) {
27
+ const prefix = "[Request interrupted by user]";
28
+ if (text.startsWith(prefix)) {
29
+ return text.slice(prefix.length).trim();
30
+ }
31
+ return text;
32
+ }
33
+ function countToolUses(content) {
34
+ if (typeof content === "string")
35
+ return 0;
36
+ return content.filter((c) => c.type === "tool_use").length;
37
+ }
38
+ /**
39
+ * Encode a filesystem path to match Claude's project directory naming.
40
+ * e.g. /Users/foo/Dev -> -Users-foo-Dev
41
+ */
42
+ export function encodeProjectPath(projectPath) {
43
+ return projectPath.replace(/\//g, "-");
44
+ }
45
+ /**
46
+ * Find all Claude project directories that could match the given project path.
47
+ */
48
+ export function findClaudeProjectDirs(projectPath) {
49
+ const claudeDir = path.join(process.env.HOME || process.env.USERPROFILE || "", ".claude", "projects");
50
+ if (!fs.existsSync(claudeDir))
51
+ return [];
52
+ const encoded = encodeProjectPath(projectPath);
53
+ const dirs = fs.readdirSync(claudeDir);
54
+ // Match exact or parent paths
55
+ return dirs
56
+ .filter((d) => encoded.startsWith(d) || d.startsWith(encoded))
57
+ .map((d) => path.join(claudeDir, d));
58
+ }
59
+ /**
60
+ * Get sessions from the index that overlap with the given time window.
61
+ */
62
+ export function getSessionsInWindow(projectDirs, since, until) {
63
+ const sessions = [];
64
+ for (const dir of projectDirs) {
65
+ const indexPath = path.join(dir, "sessions-index.json");
66
+ if (fs.existsSync(indexPath)) {
67
+ // Use the index for fast lookup
68
+ try {
69
+ const index = JSON.parse(fs.readFileSync(indexPath, "utf-8"));
70
+ for (const entry of index.entries) {
71
+ const created = new Date(entry.created);
72
+ const modified = new Date(entry.modified);
73
+ if (modified >= since && created <= until) {
74
+ const jsonlPath = entry.fullPath || path.join(dir, `${entry.sessionId}.jsonl`);
75
+ if (fs.existsSync(jsonlPath)) {
76
+ sessions.push({ sessionId: entry.sessionId, fullPath: jsonlPath });
77
+ }
78
+ }
79
+ }
80
+ }
81
+ catch {
82
+ // Skip malformed index files
83
+ }
84
+ }
85
+ else {
86
+ // Fallback: scan .jsonl files directly when index is missing
87
+ try {
88
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
89
+ for (const file of files) {
90
+ const fullPath = path.join(dir, file);
91
+ const stat = fs.statSync(fullPath);
92
+ if (stat.mtimeMs >= since.getTime() && stat.birthtimeMs <= until.getTime()) {
93
+ const sessionId = file.replace(".jsonl", "");
94
+ sessions.push({ sessionId, fullPath });
95
+ }
96
+ }
97
+ }
98
+ catch {
99
+ // Skip unreadable directories
100
+ }
101
+ }
102
+ }
103
+ return sessions;
104
+ }
105
+ /**
106
+ * Parse a single JSONL session file and count interactions within a time window.
107
+ */
108
+ export function parseSessionFile(filePath, since, until) {
109
+ if (!fs.existsSync(filePath))
110
+ return null;
111
+ const content = fs.readFileSync(filePath, "utf-8");
112
+ const lines = content.split("\n").filter((l) => l.trim());
113
+ let aiResponses = 0;
114
+ let toolCalls = 0;
115
+ let startTime;
116
+ let endTime;
117
+ let sessionId = "";
118
+ const prompts = [];
119
+ for (const line of lines) {
120
+ let msg;
121
+ try {
122
+ msg = JSON.parse(line);
123
+ }
124
+ catch {
125
+ continue;
126
+ }
127
+ // Skip non-message entries (file-history-snapshot, summary, etc.)
128
+ if (!msg.type || msg.type === "file-history-snapshot" || msg.type === "summary") {
129
+ continue;
130
+ }
131
+ if (msg.sessionId)
132
+ sessionId = msg.sessionId;
133
+ // Filter by time window
134
+ if (msg.timestamp) {
135
+ const ts = new Date(msg.timestamp);
136
+ if (ts < since || ts > until)
137
+ continue;
138
+ if (!startTime || ts.toISOString() < startTime)
139
+ startTime = ts.toISOString();
140
+ if (!endTime || ts.toISOString() > endTime)
141
+ endTime = ts.toISOString();
142
+ }
143
+ // Count user prompts: type=user, role=user, not meta, not commands
144
+ if (msg.type === "user" && msg.message?.role === "user") {
145
+ if (msg.isMeta)
146
+ continue;
147
+ if (msg.isSidechain)
148
+ continue;
149
+ if (msg.message.content && isCommand(msg.message.content))
150
+ continue;
151
+ if (msg.message.content && isSystemGenerated(msg.message.content))
152
+ continue;
153
+ const raw = typeof msg.message.content === "string"
154
+ ? msg.message.content
155
+ : msg.message.content?.map((c) => c.text || "").join("") ?? "";
156
+ const trimmed = stripInterruptPrefix(raw.trim());
157
+ if (trimmed.length > 0) {
158
+ prompts.push({
159
+ text: trimmed.slice(0, 500),
160
+ timestamp: msg.timestamp || "",
161
+ sessionId,
162
+ });
163
+ }
164
+ }
165
+ // Count AI responses
166
+ if (msg.message?.role === "assistant") {
167
+ aiResponses++;
168
+ if (msg.message.content) {
169
+ toolCalls += countToolUses(msg.message.content);
170
+ }
171
+ }
172
+ }
173
+ const userPrompts = prompts.length;
174
+ if (userPrompts === 0 && aiResponses === 0)
175
+ return null;
176
+ return {
177
+ sessionId,
178
+ userPrompts,
179
+ aiResponses,
180
+ toolCalls,
181
+ totalInteractions: userPrompts + aiResponses,
182
+ startTime,
183
+ endTime,
184
+ prompts,
185
+ };
186
+ }
187
+ /**
188
+ * Main entry point: parse all Claude sessions for a project within a time window.
189
+ * Returns aggregated stats and individual session details.
190
+ */
191
+ export function parseClaudeSessions(projectPath, since, until) {
192
+ const projectDirs = findClaudeProjectDirs(projectPath);
193
+ const sessionFiles = getSessionsInWindow(projectDirs, since, until);
194
+ const sessions = [];
195
+ let totalUserPrompts = 0;
196
+ let totalAiResponses = 0;
197
+ let totalToolCalls = 0;
198
+ for (const { fullPath } of sessionFiles) {
199
+ const stats = parseSessionFile(fullPath, since, until);
200
+ if (stats) {
201
+ sessions.push(stats);
202
+ totalUserPrompts += stats.userPrompts;
203
+ totalAiResponses += stats.aiResponses;
204
+ totalToolCalls += stats.toolCalls;
205
+ }
206
+ }
207
+ const allPrompts = sessions
208
+ .flatMap((s) => s.prompts ?? [])
209
+ .sort((a, b) => a.timestamp.localeCompare(b.timestamp));
210
+ return {
211
+ aggregate: {
212
+ sessionId: "aggregate",
213
+ userPrompts: totalUserPrompts,
214
+ aiResponses: totalAiResponses,
215
+ toolCalls: totalToolCalls,
216
+ totalInteractions: totalUserPrompts + totalAiResponses,
217
+ prompts: allPrompts,
218
+ },
219
+ sessions,
220
+ };
221
+ }
222
+ //# sourceMappingURL=claude-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-parser.js","sourceRoot":"","sources":["../src/claude-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { type CommitPayload, type FileChangePayload, type PromptDetail, type SessionStats, type SessionIndexEntry, type VibeDriftLevel, computeVibeDriftScore, getVibeDriftLevel, getVibeDriftColor, } from "./types";
2
+ export { encodeProjectPath, findClaudeProjectDirs, getSessionsInWindow, parseSessionFile, parseClaudeSessions, } from "./claude-parser";
3
+ export { buildCommitPayload, buildLivePayload } from "./payload-builder";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { computeVibeDriftScore, getVibeDriftLevel, getVibeDriftColor, } from "./types";
2
+ export { encodeProjectPath, findClaudeProjectDirs, getSessionsInWindow, parseSessionFile, parseClaudeSessions, } from "./claude-parser";
3
+ export { buildCommitPayload, buildLivePayload } from "./payload-builder";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { CommitPayload } from "./types";
2
+ /**
3
+ * Build a live (uncommitted) payload for the current working tree.
4
+ * Uses git diff HEAD for line changes and parses Claude sessions since the last commit.
5
+ */
6
+ export declare function buildLivePayload(repoPath: string): Promise<CommitPayload>;
7
+ export declare function buildCommitPayload(repoPath: string, commitHash: string, source: CommitPayload["source"]): Promise<CommitPayload>;
8
+ //# sourceMappingURL=payload-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-builder.d.ts","sourceRoot":"","sources":["../src/payload-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAqB,MAAM,SAAS,CAAC;AAuD3D;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAqExB;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC9B,OAAO,CAAC,aAAa,CAAC,CAgFxB"}
@@ -0,0 +1,182 @@
1
+ import { execSync } from "child_process";
2
+ import { parseClaudeSessions } from "./claude-parser";
3
+ function exec(cmd, cwd) {
4
+ return execSync(cmd, { cwd, encoding: "utf-8" }).trim();
5
+ }
6
+ function parseFileChanges(diffStat) {
7
+ const changes = [];
8
+ for (const line of diffStat.split("\n")) {
9
+ if (!line.trim())
10
+ continue;
11
+ // Format: "added\tdeleted\tfilepath" or for binary: "-\t-\tfilepath"
12
+ const parts = line.split("\t");
13
+ if (parts.length < 3)
14
+ continue;
15
+ const added = parseInt(parts[0], 10) || 0;
16
+ const deleted = parseInt(parts[1], 10) || 0;
17
+ const filePath = parts.slice(2).join("\t");
18
+ changes.push({ filePath, linesAdded: added, linesDeleted: deleted, status: "modified" });
19
+ }
20
+ return changes;
21
+ }
22
+ function detectFileStatus(fileChanges, statusOutput) {
23
+ const statusMap = new Map();
24
+ for (const line of statusOutput.split("\n")) {
25
+ if (!line.trim())
26
+ continue;
27
+ const code = line.charAt(0);
28
+ const file = line.substring(2).trim();
29
+ switch (code) {
30
+ case "A":
31
+ statusMap.set(file, "added");
32
+ break;
33
+ case "D":
34
+ statusMap.set(file, "deleted");
35
+ break;
36
+ case "R":
37
+ statusMap.set(file, "renamed");
38
+ break;
39
+ case "C":
40
+ statusMap.set(file, "copied");
41
+ break;
42
+ default:
43
+ statusMap.set(file, "modified");
44
+ }
45
+ }
46
+ return fileChanges.map((fc) => ({
47
+ ...fc,
48
+ status: statusMap.get(fc.filePath) ?? fc.status,
49
+ }));
50
+ }
51
+ /**
52
+ * Build a live (uncommitted) payload for the current working tree.
53
+ * Uses git diff HEAD for line changes and parses Claude sessions since the last commit.
54
+ */
55
+ export async function buildLivePayload(repoPath) {
56
+ const branch = exec("git rev-parse --abbrev-ref HEAD", repoPath);
57
+ const projectName = repoPath.split("/").pop() || "unknown";
58
+ let author = "unknown";
59
+ try {
60
+ author = exec("git config user.name", repoPath);
61
+ }
62
+ catch {
63
+ // ignore
64
+ }
65
+ let remoteUrl;
66
+ try {
67
+ remoteUrl = exec("git remote get-url origin", repoPath) || undefined;
68
+ }
69
+ catch {
70
+ remoteUrl = undefined;
71
+ }
72
+ // Uncommitted diff stats (staged + unstaged vs HEAD)
73
+ let numstat = "";
74
+ try {
75
+ numstat = exec("git diff HEAD --numstat", repoPath);
76
+ }
77
+ catch {
78
+ // No commits yet or other error
79
+ }
80
+ const fileChanges = parseFileChanges(numstat);
81
+ const linesAdded = fileChanges.reduce((s, f) => s + f.linesAdded, 0);
82
+ const linesDeleted = fileChanges.reduce((s, f) => s + f.linesDeleted, 0);
83
+ // Time window: last commit timestamp -> now
84
+ let sinceDate;
85
+ let commitHash = "HEAD";
86
+ try {
87
+ commitHash = exec("git rev-parse HEAD", repoPath);
88
+ const lastCommitTime = exec("git log -1 --format=%aI HEAD", repoPath);
89
+ sinceDate = new Date(lastCommitTime);
90
+ }
91
+ catch {
92
+ // No commits yet
93
+ sinceDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
94
+ }
95
+ const untilDate = new Date();
96
+ // Parse Claude sessions in this time window
97
+ const { aggregate, sessions } = parseClaudeSessions(repoPath, sinceDate, untilDate);
98
+ return {
99
+ commitHash: `live-${projectName}`,
100
+ message: "Live session (uncommitted)",
101
+ author,
102
+ branch,
103
+ committedAt: new Date().toISOString(),
104
+ projectName,
105
+ remoteUrl,
106
+ userPrompts: aggregate.userPrompts,
107
+ aiResponses: aggregate.aiResponses,
108
+ totalInteractions: aggregate.totalInteractions,
109
+ toolCalls: aggregate.toolCalls,
110
+ filesChanged: fileChanges.length,
111
+ linesAdded,
112
+ linesDeleted,
113
+ source: "live",
114
+ sessionIds: sessions.map((s) => s.sessionId),
115
+ fileChanges,
116
+ prompts: aggregate.prompts ?? [],
117
+ };
118
+ }
119
+ export async function buildCommitPayload(repoPath, commitHash, source) {
120
+ // Get commit metadata
121
+ const message = exec(`git log -1 --format=%s ${commitHash}`, repoPath);
122
+ const author = exec(`git log -1 --format=%an ${commitHash}`, repoPath);
123
+ const committedAt = exec(`git log -1 --format=%aI ${commitHash}`, repoPath);
124
+ const branch = exec("git rev-parse --abbrev-ref HEAD", repoPath);
125
+ // Project name from directory
126
+ const projectName = repoPath.split("/").pop() || "unknown";
127
+ // Remote URL (optional)
128
+ let remoteUrl;
129
+ try {
130
+ remoteUrl = exec("git remote get-url origin", repoPath) || undefined;
131
+ }
132
+ catch {
133
+ remoteUrl = undefined;
134
+ }
135
+ // Diff stats for this commit
136
+ const numstat = exec(`git diff --numstat ${commitHash}~1 ${commitHash} 2>/dev/null || git diff --numstat --root ${commitHash}`, repoPath);
137
+ let fileChanges = parseFileChanges(numstat);
138
+ // Detect file statuses (A/D/M/R/C)
139
+ try {
140
+ const nameStatus = exec(`git diff --name-status ${commitHash}~1 ${commitHash} 2>/dev/null || git diff --name-status --root ${commitHash}`, repoPath);
141
+ fileChanges = detectFileStatus(fileChanges, nameStatus);
142
+ }
143
+ catch {
144
+ // Keep default "modified" status
145
+ }
146
+ const linesAdded = fileChanges.reduce((s, f) => s + f.linesAdded, 0);
147
+ const linesDeleted = fileChanges.reduce((s, f) => s + f.linesDeleted, 0);
148
+ // Time window: previous commit timestamp -> this commit timestamp
149
+ let sinceDate;
150
+ try {
151
+ const prevTimestamp = exec(`git log -1 --format=%aI ${commitHash}~1`, repoPath);
152
+ sinceDate = new Date(prevTimestamp);
153
+ }
154
+ catch {
155
+ // First commit — use 24h before
156
+ sinceDate = new Date(new Date(committedAt).getTime() - 24 * 60 * 60 * 1000);
157
+ }
158
+ const untilDate = new Date(committedAt);
159
+ // Parse Claude sessions in this time window
160
+ const { aggregate, sessions } = parseClaudeSessions(repoPath, sinceDate, untilDate);
161
+ return {
162
+ commitHash,
163
+ message,
164
+ author,
165
+ branch,
166
+ committedAt,
167
+ projectName,
168
+ remoteUrl,
169
+ userPrompts: aggregate.userPrompts,
170
+ aiResponses: aggregate.aiResponses,
171
+ totalInteractions: aggregate.totalInteractions,
172
+ toolCalls: aggregate.toolCalls,
173
+ filesChanged: fileChanges.length,
174
+ linesAdded,
175
+ linesDeleted,
176
+ source,
177
+ sessionIds: sessions.map((s) => s.sessionId),
178
+ fileChanges,
179
+ prompts: aggregate.prompts ?? [],
180
+ };
181
+ }
182
+ //# sourceMappingURL=payload-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-builder.js","sourceRoot":"","sources":["../src/payload-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export interface PromptDetail {
2
+ text: string;
3
+ timestamp: string;
4
+ sessionId: string;
5
+ }
6
+ export interface FileChangePayload {
7
+ filePath: string;
8
+ linesAdded: number;
9
+ linesDeleted: number;
10
+ status: "added" | "modified" | "deleted" | "renamed" | "copied";
11
+ }
12
+ export interface CommitPayload {
13
+ commitHash: string;
14
+ message: string;
15
+ author: string;
16
+ branch: string;
17
+ committedAt: string;
18
+ projectName: string;
19
+ remoteUrl?: string;
20
+ userPrompts: number;
21
+ aiResponses: number;
22
+ totalInteractions: number;
23
+ toolCalls: number;
24
+ filesChanged: number;
25
+ linesAdded: number;
26
+ linesDeleted: number;
27
+ source: "vscode" | "hook" | "manual" | "live";
28
+ sessionIds: string[];
29
+ fileChanges?: FileChangePayload[];
30
+ prompts?: PromptDetail[];
31
+ }
32
+ export interface SessionStats {
33
+ sessionId: string;
34
+ userPrompts: number;
35
+ aiResponses: number;
36
+ toolCalls: number;
37
+ totalInteractions: number;
38
+ startTime?: string;
39
+ endTime?: string;
40
+ prompts?: PromptDetail[];
41
+ }
42
+ export interface SessionIndexEntry {
43
+ sessionId: string;
44
+ path: string;
45
+ lastModified: number;
46
+ }
47
+ export declare function computeVibeDriftScore(userPrompts: number, linesAdded?: number, linesDeleted?: number): number;
48
+ export type VibeDriftLevel = "low" | "moderate" | "high" | "vibe-drift";
49
+ export declare function getVibeDriftLevel(score: number): VibeDriftLevel;
50
+ export declare function getVibeDriftColor(level: VibeDriftLevel): string;
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;CACjE;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,UAAU,GAAE,MAAU,EACtB,YAAY,GAAE,MAAU,GACvB,MAAM,CAYR;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;AAExE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAK/D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAW/D"}
package/dist/types.js ADDED
@@ -0,0 +1,33 @@
1
+ export function computeVibeDriftScore(userPrompts, linesAdded = 0, linesDeleted = 0) {
2
+ const P = userPrompts;
3
+ const L = linesAdded + linesDeleted;
4
+ const linesPerPrompt = L / Math.max(1, P);
5
+ // Efficiency factor: lpp >= 50 → 0.7 (productive), lpp = 20 → 1.0, lpp <= 5 → 1.5 (spinning)
6
+ let factor = Math.min(1.5, Math.max(0.7, 1.5 - linesPerPrompt / 40));
7
+ // 1 prompt should never be penalised
8
+ if (P <= 1)
9
+ factor = Math.min(factor, 1.0);
10
+ return P * factor;
11
+ }
12
+ export function getVibeDriftLevel(score) {
13
+ if (score <= 1)
14
+ return "low";
15
+ if (score <= 3)
16
+ return "moderate";
17
+ if (score <= 6)
18
+ return "high";
19
+ return "vibe-drift";
20
+ }
21
+ export function getVibeDriftColor(level) {
22
+ switch (level) {
23
+ case "low":
24
+ return "#22c55e"; // green
25
+ case "moderate":
26
+ return "#eab308"; // yellow
27
+ case "high":
28
+ return "#f97316"; // orange
29
+ case "vibe-drift":
30
+ return "#ef4444"; // red
31
+ }
32
+ }
33
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAmDA,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,aAAqB,CAAC,EACtB,eAAuB,CAAC;IAExB,MAAM,CAAC,GAAG,WAAW,CAAC;IACtB,MAAM,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC;IACpC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE1C,6FAA6F;IAC7F,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc,GAAG,EAAE,CAAC,CAAC,CAAC;IAErE,qCAAqC;IACrC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3C,OAAO,CAAC,GAAG,MAAM,CAAC;AACpB,CAAC;AAID,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7B,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC;IAClC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9B,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAqB;IACrD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,KAAK;YACR,OAAO,SAAS,CAAC,CAAC,QAAQ;QAC5B,KAAK,UAAU;YACb,OAAO,SAAS,CAAC,CAAC,SAAS;QAC7B,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,CAAC,SAAS;QAC7B,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,CAAC,MAAM;IAC5B,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "vibedrift-shared",
3
+ "version": "0.1.3",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "devDependencies": {
13
+ "@types/node": "^25.2.1",
14
+ "typescript": "^5.6.3"
15
+ },
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "clean": "rm -rf dist"
19
+ }
20
+ }