@yhong91/vibetime 0.1.44 → 0.1.46
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/bin/vibetime.mjs +344 -230
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -1719,6 +1719,69 @@ import { promisify } from "node:util";
|
|
|
1719
1719
|
// src/lib/activity.ts
|
|
1720
1720
|
import path2 from "node:path";
|
|
1721
1721
|
|
|
1722
|
+
// src/lib/fields.ts
|
|
1723
|
+
function stringField(object, key) {
|
|
1724
|
+
if (!isPlainObject(object)) {
|
|
1725
|
+
return void 0;
|
|
1726
|
+
}
|
|
1727
|
+
const value = object[key];
|
|
1728
|
+
return typeof value === "string" ? value : void 0;
|
|
1729
|
+
}
|
|
1730
|
+
function numberField(object, key) {
|
|
1731
|
+
const value = object[key];
|
|
1732
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1733
|
+
}
|
|
1734
|
+
function objectField(object, key) {
|
|
1735
|
+
if (!isPlainObject(object) || !isPlainObject(object[key])) {
|
|
1736
|
+
return {};
|
|
1737
|
+
}
|
|
1738
|
+
return object[key];
|
|
1739
|
+
}
|
|
1740
|
+
function arrayField(object, key) {
|
|
1741
|
+
if (!isPlainObject(object) || !Array.isArray(object[key])) {
|
|
1742
|
+
return [];
|
|
1743
|
+
}
|
|
1744
|
+
return object[key];
|
|
1745
|
+
}
|
|
1746
|
+
function isPlainObject(value) {
|
|
1747
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1748
|
+
}
|
|
1749
|
+
function stringRefs(value) {
|
|
1750
|
+
const refs2 = {};
|
|
1751
|
+
for (const [key, item] of Object.entries(value || {})) {
|
|
1752
|
+
if (typeof item === "string" && item.length > 0) {
|
|
1753
|
+
refs2[key] = item;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
return refs2;
|
|
1757
|
+
}
|
|
1758
|
+
function stringOption(value) {
|
|
1759
|
+
if (Array.isArray(value)) {
|
|
1760
|
+
return value.at(-1);
|
|
1761
|
+
}
|
|
1762
|
+
return typeof value === "string" ? value : void 0;
|
|
1763
|
+
}
|
|
1764
|
+
function valuesOption(value) {
|
|
1765
|
+
if (Array.isArray(value)) {
|
|
1766
|
+
return value;
|
|
1767
|
+
}
|
|
1768
|
+
return typeof value === "string" ? [value] : [];
|
|
1769
|
+
}
|
|
1770
|
+
function numberOption(value) {
|
|
1771
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1772
|
+
return value;
|
|
1773
|
+
}
|
|
1774
|
+
if (Array.isArray(value)) {
|
|
1775
|
+
return numberOption(value.at(-1));
|
|
1776
|
+
}
|
|
1777
|
+
const text = stringOption(value);
|
|
1778
|
+
if (!text) {
|
|
1779
|
+
return void 0;
|
|
1780
|
+
}
|
|
1781
|
+
const parsed = Number(text);
|
|
1782
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1722
1785
|
// src/lib/shell.ts
|
|
1723
1786
|
import path from "node:path";
|
|
1724
1787
|
function fileActivitiesFromShellCommand(command, ts, rootCwd, initialCwd) {
|
|
@@ -1926,78 +1989,71 @@ function countTextLines(text) {
|
|
|
1926
1989
|
}
|
|
1927
1990
|
return text.split(/\r\n|\r|\n/).length;
|
|
1928
1991
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
// src/lib/fields.ts
|
|
1939
|
-
function stringField(object, key) {
|
|
1940
|
-
if (!isPlainObject(object)) {
|
|
1941
|
-
return void 0;
|
|
1942
|
-
}
|
|
1943
|
-
const value = object[key];
|
|
1944
|
-
return typeof value === "string" ? value : void 0;
|
|
1945
|
-
}
|
|
1946
|
-
function numberField(object, key) {
|
|
1947
|
-
const value = object[key];
|
|
1948
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1949
|
-
}
|
|
1950
|
-
function objectField(object, key) {
|
|
1951
|
-
if (!isPlainObject(object) || !isPlainObject(object[key])) {
|
|
1952
|
-
return {};
|
|
1953
|
-
}
|
|
1954
|
-
return object[key];
|
|
1955
|
-
}
|
|
1956
|
-
function arrayField(object, key) {
|
|
1957
|
-
if (!isPlainObject(object) || !Array.isArray(object[key])) {
|
|
1958
|
-
return [];
|
|
1959
|
-
}
|
|
1960
|
-
return object[key];
|
|
1961
|
-
}
|
|
1962
|
-
function isPlainObject(value) {
|
|
1963
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1964
|
-
}
|
|
1965
|
-
function stringRefs(value) {
|
|
1966
|
-
const refs2 = {};
|
|
1967
|
-
for (const [key, item] of Object.entries(value || {})) {
|
|
1968
|
-
if (typeof item === "string" && item.length > 0) {
|
|
1969
|
-
refs2[key] = item;
|
|
1992
|
+
function claudeStyleToolFileActivities(tool, input, ts, cwd) {
|
|
1993
|
+
const changes = /* @__PURE__ */ new Map();
|
|
1994
|
+
const operation = operationForTool(tool);
|
|
1995
|
+
const workdir = stringField(input, "cwd") || cwd;
|
|
1996
|
+
for (const key of ["file_path", "path", "notebook_path"]) {
|
|
1997
|
+
const filePath = stringField(input, key);
|
|
1998
|
+
if (!filePath) {
|
|
1999
|
+
continue;
|
|
1970
2000
|
}
|
|
2001
|
+
const metrics = claudeStyleFileMetrics(tool, input);
|
|
2002
|
+
addResolvedPathActivity(changes, filePath, operation, ts, cwd, workdir, metrics);
|
|
1971
2003
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2004
|
+
for (const edit of [...arrayField(input, "edits"), ...arrayField(input, "replacements")]) {
|
|
2005
|
+
if (!isPlainObject(edit)) {
|
|
2006
|
+
continue;
|
|
2007
|
+
}
|
|
2008
|
+
const filePath = stringField(input, "file_path") || stringField(input, "path");
|
|
2009
|
+
if (!filePath) {
|
|
2010
|
+
continue;
|
|
2011
|
+
}
|
|
2012
|
+
addResolvedPathActivity(changes, filePath, "edit", ts, cwd, workdir, {
|
|
2013
|
+
linesAdded: countTextLines(stringField(edit, "new_string") || stringField(edit, "new_text")),
|
|
2014
|
+
linesRemoved: countTextLines(stringField(edit, "old_string") || stringField(edit, "original_text"))
|
|
2015
|
+
});
|
|
1977
2016
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
2017
|
+
const command = stringField(input, "command");
|
|
2018
|
+
if (command) {
|
|
2019
|
+
for (const item of fileActivitiesFromShellCommand(command, ts, cwd, workdir)) {
|
|
2020
|
+
changes.set(item.path, mergeFileActivity(changes.get(item.path), item));
|
|
2021
|
+
}
|
|
1983
2022
|
}
|
|
1984
|
-
return
|
|
2023
|
+
return [...changes.values()];
|
|
1985
2024
|
}
|
|
1986
|
-
function
|
|
1987
|
-
|
|
1988
|
-
|
|
2025
|
+
function claudeStyleFileMetrics(tool, input) {
|
|
2026
|
+
const normalized = tool.toLowerCase();
|
|
2027
|
+
if (normalized === "read") {
|
|
2028
|
+
return { linesRead: numberField(input, "limit") };
|
|
1989
2029
|
}
|
|
1990
|
-
if (
|
|
1991
|
-
|
|
2030
|
+
if (normalized === "write") {
|
|
2031
|
+
const content = stringField(input, "content") || stringField(input, "file_content");
|
|
2032
|
+
return {
|
|
2033
|
+
linesAdded: countTextLines(content),
|
|
2034
|
+
charsWritten: content?.length
|
|
2035
|
+
};
|
|
1992
2036
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2037
|
+
if (normalized === "edit" || normalized === "multiedit" || normalized === "searchreplace") {
|
|
2038
|
+
const oldString = stringField(input, "old_string");
|
|
2039
|
+
const newString = stringField(input, "new_string");
|
|
2040
|
+
return {
|
|
2041
|
+
linesAdded: countTextLines(newString),
|
|
2042
|
+
linesRemoved: countTextLines(oldString),
|
|
2043
|
+
charsWritten: newString?.length
|
|
2044
|
+
};
|
|
1996
2045
|
}
|
|
1997
|
-
|
|
1998
|
-
return Number.isFinite(parsed) ? parsed : void 0;
|
|
2046
|
+
return {};
|
|
1999
2047
|
}
|
|
2000
2048
|
|
|
2049
|
+
// src/lib/constants.ts
|
|
2050
|
+
var PACKAGE_VERSION = true ? "0.1.46" : "0.1.1";
|
|
2051
|
+
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
2052
|
+
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
2053
|
+
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
2054
|
+
var ROLLUP_BUCKET_MS = 15 * 60 * 1e3;
|
|
2055
|
+
var DEFAULT_HOOK_SYNC_MIN_INTERVAL_SECONDS = 60;
|
|
2056
|
+
|
|
2001
2057
|
// src/lib/jsonl.ts
|
|
2002
2058
|
function parseJsonLine(line) {
|
|
2003
2059
|
try {
|
|
@@ -3868,14 +3924,14 @@ function claudeProjectRootFromCwds(projectDir, cwds) {
|
|
|
3868
3924
|
return void 0;
|
|
3869
3925
|
}
|
|
3870
3926
|
function encodeClaudeProjectPath(value) {
|
|
3871
|
-
return path7.resolve(value).split(path7.sep).join("-").
|
|
3927
|
+
return path7.resolve(value).split(path7.sep).join("-").replaceAll("_", "-");
|
|
3872
3928
|
}
|
|
3873
3929
|
function rawClaudeProjectPath(value) {
|
|
3874
3930
|
return path7.resolve(value).split(path7.sep).join("-");
|
|
3875
3931
|
}
|
|
3876
3932
|
function claudeEncodedVariants(value) {
|
|
3877
3933
|
const raw = rawClaudeProjectPath(value);
|
|
3878
|
-
const normalized = raw.
|
|
3934
|
+
const normalized = raw.replaceAll("_", "-");
|
|
3879
3935
|
return raw === normalized ? [raw] : [raw, normalized];
|
|
3880
3936
|
}
|
|
3881
3937
|
function claudeEncodedProjectSuffix(projectDir, home) {
|
|
@@ -4129,7 +4185,7 @@ async function discoverCoworkTranscripts(root) {
|
|
|
4129
4185
|
function coworkMetaPathForTranscript(transcriptPath) {
|
|
4130
4186
|
const marker = `${path8.sep}.claude${path8.sep}projects${path8.sep}`;
|
|
4131
4187
|
const index = transcriptPath.indexOf(marker);
|
|
4132
|
-
if (index
|
|
4188
|
+
if (index === -1) {
|
|
4133
4189
|
return void 0;
|
|
4134
4190
|
}
|
|
4135
4191
|
return `${transcriptPath.slice(0, index)}.json`;
|
|
@@ -4144,7 +4200,7 @@ function projectFromMeta(meta) {
|
|
|
4144
4200
|
}
|
|
4145
4201
|
const resolved = path8.resolve(folder);
|
|
4146
4202
|
return {
|
|
4147
|
-
project: path8.basename(resolved).
|
|
4203
|
+
project: path8.basename(resolved).replaceAll("-", "_") || "cowork",
|
|
4148
4204
|
cwd: resolved
|
|
4149
4205
|
};
|
|
4150
4206
|
}
|
|
@@ -4269,7 +4325,7 @@ function createClaudeCoworkAdapter() {
|
|
|
4269
4325
|
}
|
|
4270
4326
|
|
|
4271
4327
|
// src/adapters/codebuddy.ts
|
|
4272
|
-
import {
|
|
4328
|
+
import { readdir as readdir4, readFile as readFile5 } from "node:fs/promises";
|
|
4273
4329
|
import path9 from "node:path";
|
|
4274
4330
|
var ENDPOINT_MODEL_ID_RE = /^(?:ep|endpoint)-/i;
|
|
4275
4331
|
async function parseCodebuddyTraceFile(filePath, options) {
|
|
@@ -4504,6 +4560,28 @@ async function parseCodebuddyTraceFile(filePath, options) {
|
|
|
4504
4560
|
sourceId: span.spanId
|
|
4505
4561
|
})
|
|
4506
4562
|
}), index, "function");
|
|
4563
|
+
const toolInput = parseEmbeddedJson(span.toolInput);
|
|
4564
|
+
if (isPlainObject(toolInput)) {
|
|
4565
|
+
const fileActivities = claudeStyleToolFileActivities(tool, toolInput, ts, cwd);
|
|
4566
|
+
if (fileActivities.length > 0) {
|
|
4567
|
+
push(baseEvent({
|
|
4568
|
+
ts,
|
|
4569
|
+
type: eventTypeFromFileActivities(fileActivities),
|
|
4570
|
+
operation: `${tool} file activity`,
|
|
4571
|
+
sessionId,
|
|
4572
|
+
cwd,
|
|
4573
|
+
project,
|
|
4574
|
+
model,
|
|
4575
|
+
tool,
|
|
4576
|
+
confidence: "derived",
|
|
4577
|
+
fileActivities,
|
|
4578
|
+
metrics: summarizeFileActivities(fileActivities),
|
|
4579
|
+
refs: stringRefs({
|
|
4580
|
+
sourceId: span.spanId
|
|
4581
|
+
})
|
|
4582
|
+
}), index, "function");
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4507
4585
|
if (span.endedAt) {
|
|
4508
4586
|
const durationMs = span.duration ?? void 0;
|
|
4509
4587
|
push(baseEvent({
|
|
@@ -4527,30 +4605,28 @@ async function parseCodebuddyTraceFile(filePath, options) {
|
|
|
4527
4605
|
})
|
|
4528
4606
|
}), index, "function");
|
|
4529
4607
|
}
|
|
4530
|
-
if (tool === "Bash") {
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
}), index, "function");
|
|
4553
|
-
}
|
|
4608
|
+
if (tool === "Bash" && span.endedAt) {
|
|
4609
|
+
const durationMs = span.duration ?? void 0;
|
|
4610
|
+
push(baseEvent({
|
|
4611
|
+
ts: span.endedAt,
|
|
4612
|
+
type: toolSuccess ? "command.completed" : "command.failed",
|
|
4613
|
+
operation: "Bash completed",
|
|
4614
|
+
sessionId,
|
|
4615
|
+
cwd,
|
|
4616
|
+
project,
|
|
4617
|
+
model,
|
|
4618
|
+
tool,
|
|
4619
|
+
success: toolSuccess,
|
|
4620
|
+
confidence: "derived",
|
|
4621
|
+
metrics: {
|
|
4622
|
+
commandCalls: 1,
|
|
4623
|
+
commandDurationMs: durationMs,
|
|
4624
|
+
durationMs
|
|
4625
|
+
},
|
|
4626
|
+
refs: stringRefs({
|
|
4627
|
+
sourceId: span.spanId
|
|
4628
|
+
})
|
|
4629
|
+
}), index, "function");
|
|
4554
4630
|
}
|
|
4555
4631
|
continue;
|
|
4556
4632
|
}
|
|
@@ -4755,7 +4831,6 @@ async function resolveSessionIdFromSiblingTraces(filePath) {
|
|
|
4755
4831
|
}
|
|
4756
4832
|
} catch {
|
|
4757
4833
|
}
|
|
4758
|
-
return void 0;
|
|
4759
4834
|
})();
|
|
4760
4835
|
siblingSessionIdByDir.set(dir, cached);
|
|
4761
4836
|
}
|
|
@@ -4949,6 +5024,33 @@ import { readFile as readFile6 } from "node:fs/promises";
|
|
|
4949
5024
|
import path11 from "node:path";
|
|
4950
5025
|
|
|
4951
5026
|
// src/lib/diff.ts
|
|
5027
|
+
function parseApplyPatch(patch, ts) {
|
|
5028
|
+
const changes = [];
|
|
5029
|
+
let current;
|
|
5030
|
+
for (const line of patch.split("\n")) {
|
|
5031
|
+
const fileMatch = line.match(/^\*\*\* (Add|Update|Delete) File: (.+)$/);
|
|
5032
|
+
if (fileMatch) {
|
|
5033
|
+
current = {
|
|
5034
|
+
ts,
|
|
5035
|
+
path: fileMatch[2].trim(),
|
|
5036
|
+
operation: fileMatch[1] === "Add" ? "create" : fileMatch[1] === "Delete" ? "delete" : "edit",
|
|
5037
|
+
linesAdded: 0,
|
|
5038
|
+
linesRemoved: 0
|
|
5039
|
+
};
|
|
5040
|
+
changes.push(current);
|
|
5041
|
+
continue;
|
|
5042
|
+
}
|
|
5043
|
+
if (!current) {
|
|
5044
|
+
continue;
|
|
5045
|
+
}
|
|
5046
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
5047
|
+
current.linesAdded = (current.linesAdded || 0) + 1;
|
|
5048
|
+
} else if (line.startsWith("-") && !line.startsWith("---")) {
|
|
5049
|
+
current.linesRemoved = (current.linesRemoved || 0) + 1;
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
return changes;
|
|
5053
|
+
}
|
|
4952
5054
|
function diffStats(diff) {
|
|
4953
5055
|
let linesAdded = 0;
|
|
4954
5056
|
let linesRemoved = 0;
|
|
@@ -4992,10 +5094,10 @@ function fileActivitiesFromPatchChanges(changes, ts, cwd, displayFilePath3) {
|
|
|
4992
5094
|
}
|
|
4993
5095
|
|
|
4994
5096
|
// src/lib/session-context.ts
|
|
4995
|
-
init_fs();
|
|
4996
5097
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
4997
5098
|
import os4 from "node:os";
|
|
4998
5099
|
import path10 from "node:path";
|
|
5100
|
+
init_fs();
|
|
4999
5101
|
var SESSION_CONTEXT_VERSION = 1;
|
|
5000
5102
|
function sessionContextDir(home) {
|
|
5001
5103
|
return path10.join(home, ".vibetime", "session-context");
|
|
@@ -5814,7 +5916,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5814
5916
|
model = msgModel;
|
|
5815
5917
|
}
|
|
5816
5918
|
const msgTurnId = stringField(data, "turnId");
|
|
5817
|
-
const turnId = msgTurnId
|
|
5919
|
+
const turnId = msgTurnId === void 0 ? currentTurnId : `turn_${createStableHash([sessionId, msgTurnId]).slice(0, 24)}`;
|
|
5818
5920
|
events.push(baseCopilotEvent({
|
|
5819
5921
|
ts,
|
|
5820
5922
|
type: "agent.operation",
|
|
@@ -5841,7 +5943,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5841
5943
|
const toolCallId = stringField(data, "toolCallId");
|
|
5842
5944
|
const toolName = stringField(data, "toolName") || "tool";
|
|
5843
5945
|
const toolTurnId = stringField(data, "turnId");
|
|
5844
|
-
const turnId = toolTurnId
|
|
5946
|
+
const turnId = toolTurnId === void 0 ? currentTurnId : `turn_${createStableHash([sessionId, toolTurnId]).slice(0, 24)}`;
|
|
5845
5947
|
if (toolCallId) {
|
|
5846
5948
|
pendingTools.set(toolCallId, { tool: toolName, startedAt: ts, turnId });
|
|
5847
5949
|
}
|
|
@@ -5859,6 +5961,24 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5859
5961
|
metrics: { toolCalls: 1 },
|
|
5860
5962
|
refs: stringRefs({ sourceId: toolCallId })
|
|
5861
5963
|
}));
|
|
5964
|
+
const fileActivities = copilotFileActivities(toolName, data.arguments, ts, cwd);
|
|
5965
|
+
if (fileActivities.length > 0) {
|
|
5966
|
+
events.push(baseCopilotEvent({
|
|
5967
|
+
ts,
|
|
5968
|
+
type: eventTypeFromFileActivities(fileActivities),
|
|
5969
|
+
operation: `${toolName} file activity`,
|
|
5970
|
+
sessionId,
|
|
5971
|
+
turnId,
|
|
5972
|
+
cwd,
|
|
5973
|
+
project,
|
|
5974
|
+
model,
|
|
5975
|
+
tool: toolName,
|
|
5976
|
+
confidence: "derived",
|
|
5977
|
+
fileActivities,
|
|
5978
|
+
metrics: summarizeFileActivities(fileActivities),
|
|
5979
|
+
refs: stringRefs({ sourceId: toolCallId })
|
|
5980
|
+
}));
|
|
5981
|
+
}
|
|
5862
5982
|
break;
|
|
5863
5983
|
}
|
|
5864
5984
|
case "tool.execution_complete": {
|
|
@@ -5881,7 +6001,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5881
6001
|
tool: pending?.tool,
|
|
5882
6002
|
success,
|
|
5883
6003
|
confidence: "exact",
|
|
5884
|
-
metrics: durationMs
|
|
6004
|
+
metrics: durationMs === void 0 ? void 0 : { toolDurationMs: durationMs, durationMs },
|
|
5885
6005
|
refs: stringRefs({ sourceId: toolCallId })
|
|
5886
6006
|
}));
|
|
5887
6007
|
const toolLower = (pending?.tool || "").toLowerCase();
|
|
@@ -5910,7 +6030,7 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5910
6030
|
}
|
|
5911
6031
|
case "assistant.turn_end": {
|
|
5912
6032
|
const endTurnId = stringField(data, "turnId");
|
|
5913
|
-
const turnId = endTurnId
|
|
6033
|
+
const turnId = endTurnId === void 0 ? currentTurnId : `turn_${createStableHash([sessionId, endTurnId]).slice(0, 24)}`;
|
|
5914
6034
|
const accum = turnId ? turnTokenAccum.get(turnId) : void 0;
|
|
5915
6035
|
if (accum && accum.tokensOutput && accum.tokensOutput > 0) {
|
|
5916
6036
|
accum.reasoningEffort = reasoningEffort;
|
|
@@ -5997,6 +6117,29 @@ async function parseCopilotSessionFile(filePath, options) {
|
|
|
5997
6117
|
}
|
|
5998
6118
|
return events.filter((event) => validateCanonicalEvent(event).valid);
|
|
5999
6119
|
}
|
|
6120
|
+
function copilotFileActivities(tool, args, ts, cwd) {
|
|
6121
|
+
const normalized = tool.toLowerCase();
|
|
6122
|
+
if (normalized === "apply_patch" && typeof args === "string") {
|
|
6123
|
+
return parseApplyPatch(args, ts);
|
|
6124
|
+
}
|
|
6125
|
+
if (!isPlainObject(args)) {
|
|
6126
|
+
return [];
|
|
6127
|
+
}
|
|
6128
|
+
const changes = /* @__PURE__ */ new Map();
|
|
6129
|
+
const filePath = stringField(args, "path") || stringField(args, "file_path");
|
|
6130
|
+
if (filePath) {
|
|
6131
|
+
const metrics = {};
|
|
6132
|
+
if (normalized === "edit") {
|
|
6133
|
+
const oldStr = stringField(args, "old_str");
|
|
6134
|
+
const newStr = stringField(args, "new_str");
|
|
6135
|
+
metrics.linesAdded = countTextLines(newStr);
|
|
6136
|
+
metrics.linesRemoved = countTextLines(oldStr);
|
|
6137
|
+
metrics.charsWritten = newStr?.length;
|
|
6138
|
+
}
|
|
6139
|
+
addResolvedPathActivity(changes, filePath, operationForTool(normalized === "view" ? "read" : tool), ts, cwd, cwd, metrics);
|
|
6140
|
+
}
|
|
6141
|
+
return [...changes.values()];
|
|
6142
|
+
}
|
|
6000
6143
|
function baseCopilotEvent(event) {
|
|
6001
6144
|
return {
|
|
6002
6145
|
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
@@ -6205,7 +6348,7 @@ async function parseGrokSessionFile(filePath, options) {
|
|
|
6205
6348
|
}
|
|
6206
6349
|
if (type === "turn_started") {
|
|
6207
6350
|
const turnNumber = numberField(raw, "turn_number");
|
|
6208
|
-
currentTurnId = turnNumber
|
|
6351
|
+
currentTurnId = turnNumber === void 0 ? `turn_${createStableHash([sessionId, lineNumber]).slice(0, 24)}` : `turn_${turnNumber}`;
|
|
6209
6352
|
currentTurnStartedAt = ts;
|
|
6210
6353
|
const turnModel = stringField(raw, "model_id") || model;
|
|
6211
6354
|
push(base({
|
|
@@ -6229,7 +6372,7 @@ async function parseGrokSessionFile(filePath, options) {
|
|
|
6229
6372
|
turnId,
|
|
6230
6373
|
success,
|
|
6231
6374
|
confidence: "exact",
|
|
6232
|
-
metrics: durationMs
|
|
6375
|
+
metrics: durationMs === void 0 ? void 0 : { durationMs },
|
|
6233
6376
|
refs: stringRefs({
|
|
6234
6377
|
sourceId: `${sessionId}:${turnId || "turn"}:ended`,
|
|
6235
6378
|
outcome
|
|
@@ -6374,7 +6517,7 @@ function resolveSessionDir(filePath) {
|
|
|
6374
6517
|
if (base === "summary.json" || base === "events.jsonl" || base === "signals.json") {
|
|
6375
6518
|
return path13.dirname(filePath);
|
|
6376
6519
|
}
|
|
6377
|
-
if (
|
|
6520
|
+
if (/^[0-9a-f]{8}-[0-9a-f-]{27,}$/i.test(base)) {
|
|
6378
6521
|
return filePath;
|
|
6379
6522
|
}
|
|
6380
6523
|
return void 0;
|
|
@@ -6806,6 +6949,7 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
6806
6949
|
}
|
|
6807
6950
|
const filePath = stringField(stateInput, "file_path") || stringField(stateInput, "filePath");
|
|
6808
6951
|
if (filePath) {
|
|
6952
|
+
const lineStats = opencodeLineStats(tool, state, stateInput);
|
|
6809
6953
|
events.push(baseOpenCodeEvent({
|
|
6810
6954
|
ts: msToIso(endMs || completedTs || createdTs),
|
|
6811
6955
|
type: toolFileActivityType(tool),
|
|
@@ -6820,8 +6964,10 @@ async function parseOpenCodeSessionFile(dbPath, options) {
|
|
|
6820
6964
|
fileActivities: [{
|
|
6821
6965
|
ts: msToIso(endMs || completedTs || createdTs),
|
|
6822
6966
|
path: filePath,
|
|
6823
|
-
operation: operationForTool(tool)
|
|
6967
|
+
operation: operationForTool(tool),
|
|
6968
|
+
...lineStats
|
|
6824
6969
|
}],
|
|
6970
|
+
metrics: lineStats.linesAdded || lineStats.linesRemoved ? lineStats : void 0,
|
|
6825
6971
|
refs: stringRefs({ sourceId: callId })
|
|
6826
6972
|
}, assistantAgent));
|
|
6827
6973
|
}
|
|
@@ -6944,6 +7090,25 @@ function baseOpenCodeEvent(event, agentName) {
|
|
|
6944
7090
|
...event
|
|
6945
7091
|
};
|
|
6946
7092
|
}
|
|
7093
|
+
function opencodeLineStats(tool, state, input) {
|
|
7094
|
+
const diff = stringField(objectField(state, "metadata"), "diff");
|
|
7095
|
+
if (diff) {
|
|
7096
|
+
return diffStats(diff);
|
|
7097
|
+
}
|
|
7098
|
+
const normalized = tool.toLowerCase();
|
|
7099
|
+
if (normalized === "write") {
|
|
7100
|
+
return { linesAdded: countTextLines(stringField(input, "content")) };
|
|
7101
|
+
}
|
|
7102
|
+
if (normalized === "edit" || normalized === "multiedit" || normalized === "patch") {
|
|
7103
|
+
const newString = stringField(input, "newString") || stringField(input, "new_string");
|
|
7104
|
+
const oldString = stringField(input, "oldString") || stringField(input, "old_string");
|
|
7105
|
+
return {
|
|
7106
|
+
linesAdded: countTextLines(newString),
|
|
7107
|
+
linesRemoved: countTextLines(oldString)
|
|
7108
|
+
};
|
|
7109
|
+
}
|
|
7110
|
+
return {};
|
|
7111
|
+
}
|
|
6947
7112
|
function opencodeUsageFromInfo(info) {
|
|
6948
7113
|
const tokensObj = objectField(info, "tokens");
|
|
6949
7114
|
if (!tokensObj) {
|
|
@@ -7381,6 +7546,18 @@ function piFileActivitiesFromToolCall(tool, input, ts, cwd) {
|
|
|
7381
7546
|
addResolvedPathActivity(changes, filePath, operation, ts, cwd, cwd, piToolFileMetrics(normalized, input));
|
|
7382
7547
|
}
|
|
7383
7548
|
}
|
|
7549
|
+
if (normalized === "edit") {
|
|
7550
|
+
const filePath = stringField(input, "path") || stringField(input, "file_path") || stringField(input, "filePath");
|
|
7551
|
+
for (const edit of Array.isArray(input.edits) ? input.edits : []) {
|
|
7552
|
+
if (!isPlainObject(edit) || !filePath) {
|
|
7553
|
+
continue;
|
|
7554
|
+
}
|
|
7555
|
+
addResolvedPathActivity(changes, filePath, "edit", ts, cwd, cwd, {
|
|
7556
|
+
linesAdded: countTextLines(stringField(edit, "newText") || stringField(edit, "new_text")),
|
|
7557
|
+
linesRemoved: countTextLines(stringField(edit, "oldText") || stringField(edit, "old_text"))
|
|
7558
|
+
});
|
|
7559
|
+
}
|
|
7560
|
+
}
|
|
7384
7561
|
if (normalized === "bash" || normalized === "run") {
|
|
7385
7562
|
const command = stringField(input, "command");
|
|
7386
7563
|
if (command) {
|
|
@@ -8069,7 +8246,7 @@ async function parseQoderCnSessionFile(filePath, options) {
|
|
|
8069
8246
|
const toolUseId = stringField(toolUse, "id") || `tool_${createStableHash([filePath, lineNumber, tool]).slice(0, 24)}`;
|
|
8070
8247
|
const input = objectField(toolUse, "input");
|
|
8071
8248
|
const command = stringField(input, "command");
|
|
8072
|
-
const fileActivities =
|
|
8249
|
+
const fileActivities = claudeStyleToolFileActivities(tool, input, ts, cwd);
|
|
8073
8250
|
const agentInstanceId = tool === "Agent" ? `agent_${createStableHash([sessionId, toolUseId]).slice(0, 24)}` : void 0;
|
|
8074
8251
|
pendingTools.set(toolUseId, {
|
|
8075
8252
|
id: toolUseId,
|
|
@@ -8206,62 +8383,6 @@ function qoderCnSubagentMetrics(toolResult, fallbackDurationMs) {
|
|
|
8206
8383
|
tokensTotal: numberField(toolResult, "totalTokens") || totalInputTokens + outputTokens || void 0
|
|
8207
8384
|
};
|
|
8208
8385
|
}
|
|
8209
|
-
function fileActivitiesFromQoderCnToolUse(tool, input, ts, cwd) {
|
|
8210
|
-
const changes = /* @__PURE__ */ new Map();
|
|
8211
|
-
const operation = operationForTool(tool);
|
|
8212
|
-
const workdir = stringField(input, "cwd") || cwd;
|
|
8213
|
-
for (const key of ["file_path", "path", "notebook_path"]) {
|
|
8214
|
-
const filePath = stringField(input, key);
|
|
8215
|
-
if (!filePath) {
|
|
8216
|
-
continue;
|
|
8217
|
-
}
|
|
8218
|
-
const metrics = fileMetricsFromQoderCnToolInput(tool, input);
|
|
8219
|
-
addResolvedPathActivity(changes, filePath, operation, ts, cwd, workdir, metrics);
|
|
8220
|
-
}
|
|
8221
|
-
for (const edit of [...arrayField4(input, "edits"), ...arrayField4(input, "replacements")]) {
|
|
8222
|
-
if (!isPlainObject(edit)) {
|
|
8223
|
-
continue;
|
|
8224
|
-
}
|
|
8225
|
-
const filePath = stringField(input, "file_path") || stringField(input, "path");
|
|
8226
|
-
if (!filePath) {
|
|
8227
|
-
continue;
|
|
8228
|
-
}
|
|
8229
|
-
addResolvedPathActivity(changes, filePath, "edit", ts, cwd, workdir, {
|
|
8230
|
-
linesAdded: countTextLines(stringField(edit, "new_string") || stringField(edit, "new_text")),
|
|
8231
|
-
linesRemoved: countTextLines(stringField(edit, "old_string") || stringField(edit, "original_text"))
|
|
8232
|
-
});
|
|
8233
|
-
}
|
|
8234
|
-
const command = stringField(input, "command");
|
|
8235
|
-
if (command) {
|
|
8236
|
-
for (const item of fileActivitiesFromShellCommand(command, ts, cwd, workdir)) {
|
|
8237
|
-
changes.set(item.path, mergeFileActivity(changes.get(item.path), item));
|
|
8238
|
-
}
|
|
8239
|
-
}
|
|
8240
|
-
return [...changes.values()];
|
|
8241
|
-
}
|
|
8242
|
-
function fileMetricsFromQoderCnToolInput(tool, input) {
|
|
8243
|
-
const normalized = tool.toLowerCase();
|
|
8244
|
-
if (normalized === "read") {
|
|
8245
|
-
return { linesRead: numberField(input, "limit") };
|
|
8246
|
-
}
|
|
8247
|
-
if (normalized === "write") {
|
|
8248
|
-
const content = stringField(input, "content") || stringField(input, "file_content");
|
|
8249
|
-
return {
|
|
8250
|
-
linesAdded: countTextLines(content),
|
|
8251
|
-
charsWritten: content?.length
|
|
8252
|
-
};
|
|
8253
|
-
}
|
|
8254
|
-
if (normalized === "edit" || normalized === "multiedit" || normalized === "searchreplace") {
|
|
8255
|
-
const oldString = stringField(input, "old_string");
|
|
8256
|
-
const newString = stringField(input, "new_string");
|
|
8257
|
-
return {
|
|
8258
|
-
linesAdded: countTextLines(newString),
|
|
8259
|
-
linesRemoved: countTextLines(oldString),
|
|
8260
|
-
charsWritten: newString?.length
|
|
8261
|
-
};
|
|
8262
|
-
}
|
|
8263
|
-
return {};
|
|
8264
|
-
}
|
|
8265
8386
|
function arrayField4(object, key) {
|
|
8266
8387
|
if (!isPlainObject(object) || !Array.isArray(object[key])) {
|
|
8267
8388
|
return [];
|
|
@@ -8422,7 +8543,7 @@ function qoderCnProjectRootFromCwds(projectDir, cwds) {
|
|
|
8422
8543
|
return void 0;
|
|
8423
8544
|
}
|
|
8424
8545
|
function encodeQoderCnProjectPath(value) {
|
|
8425
|
-
return path17.resolve(value).split(path17.sep).join("-").
|
|
8546
|
+
return path17.resolve(value).split(path17.sep).join("-").replaceAll("_", "-");
|
|
8426
8547
|
}
|
|
8427
8548
|
async function qoderCnProjectFromFilePath(filePath, options) {
|
|
8428
8549
|
const projectDir = path17.basename(path17.dirname(filePath));
|
|
@@ -8903,7 +9024,7 @@ async function parseQoderSessionFile(filePath, options) {
|
|
|
8903
9024
|
const toolUseId = stringField(toolUse, "id") || `tool_${createStableHash([filePath, lineNumber, tool]).slice(0, 24)}`;
|
|
8904
9025
|
const input = objectField(toolUse, "input");
|
|
8905
9026
|
const command = stringField(input, "command");
|
|
8906
|
-
const fileActivities =
|
|
9027
|
+
const fileActivities = claudeStyleToolFileActivities(tool, input, ts, cwd);
|
|
8907
9028
|
const agentInstanceId = tool === "Agent" ? `agent_${createStableHash([sessionId, toolUseId]).slice(0, 24)}` : void 0;
|
|
8908
9029
|
pendingTools.set(toolUseId, {
|
|
8909
9030
|
id: toolUseId,
|
|
@@ -9040,62 +9161,6 @@ function qoderSubagentMetrics(toolResult, fallbackDurationMs) {
|
|
|
9040
9161
|
tokensTotal: numberField(toolResult, "totalTokens") || totalInputTokens + outputTokens || void 0
|
|
9041
9162
|
};
|
|
9042
9163
|
}
|
|
9043
|
-
function fileActivitiesFromQoderToolUse(tool, input, ts, cwd) {
|
|
9044
|
-
const changes = /* @__PURE__ */ new Map();
|
|
9045
|
-
const operation = operationForTool(tool);
|
|
9046
|
-
const workdir = stringField(input, "cwd") || cwd;
|
|
9047
|
-
for (const key of ["file_path", "path", "notebook_path"]) {
|
|
9048
|
-
const filePath = stringField(input, key);
|
|
9049
|
-
if (!filePath) {
|
|
9050
|
-
continue;
|
|
9051
|
-
}
|
|
9052
|
-
const metrics = fileMetricsFromQoderToolInput(tool, input);
|
|
9053
|
-
addResolvedPathActivity(changes, filePath, operation, ts, cwd, workdir, metrics);
|
|
9054
|
-
}
|
|
9055
|
-
for (const edit of [...arrayField5(input, "edits"), ...arrayField5(input, "replacements")]) {
|
|
9056
|
-
if (!isPlainObject(edit)) {
|
|
9057
|
-
continue;
|
|
9058
|
-
}
|
|
9059
|
-
const filePath = stringField(input, "file_path") || stringField(input, "path");
|
|
9060
|
-
if (!filePath) {
|
|
9061
|
-
continue;
|
|
9062
|
-
}
|
|
9063
|
-
addResolvedPathActivity(changes, filePath, "edit", ts, cwd, workdir, {
|
|
9064
|
-
linesAdded: countTextLines(stringField(edit, "new_string") || stringField(edit, "new_text")),
|
|
9065
|
-
linesRemoved: countTextLines(stringField(edit, "old_string") || stringField(edit, "original_text"))
|
|
9066
|
-
});
|
|
9067
|
-
}
|
|
9068
|
-
const command = stringField(input, "command");
|
|
9069
|
-
if (command) {
|
|
9070
|
-
for (const item of fileActivitiesFromShellCommand(command, ts, cwd, workdir)) {
|
|
9071
|
-
changes.set(item.path, mergeFileActivity(changes.get(item.path), item));
|
|
9072
|
-
}
|
|
9073
|
-
}
|
|
9074
|
-
return [...changes.values()];
|
|
9075
|
-
}
|
|
9076
|
-
function fileMetricsFromQoderToolInput(tool, input) {
|
|
9077
|
-
const normalized = tool.toLowerCase();
|
|
9078
|
-
if (normalized === "read") {
|
|
9079
|
-
return { linesRead: numberField(input, "limit") };
|
|
9080
|
-
}
|
|
9081
|
-
if (normalized === "write") {
|
|
9082
|
-
const content = stringField(input, "content") || stringField(input, "file_content");
|
|
9083
|
-
return {
|
|
9084
|
-
linesAdded: countTextLines(content),
|
|
9085
|
-
charsWritten: content?.length
|
|
9086
|
-
};
|
|
9087
|
-
}
|
|
9088
|
-
if (normalized === "edit" || normalized === "multiedit" || normalized === "searchreplace") {
|
|
9089
|
-
const oldString = stringField(input, "old_string");
|
|
9090
|
-
const newString = stringField(input, "new_string");
|
|
9091
|
-
return {
|
|
9092
|
-
linesAdded: countTextLines(newString),
|
|
9093
|
-
linesRemoved: countTextLines(oldString),
|
|
9094
|
-
charsWritten: newString?.length
|
|
9095
|
-
};
|
|
9096
|
-
}
|
|
9097
|
-
return {};
|
|
9098
|
-
}
|
|
9099
9164
|
function arrayField5(object, key) {
|
|
9100
9165
|
if (!isPlainObject(object) || !Array.isArray(object[key])) {
|
|
9101
9166
|
return [];
|
|
@@ -9222,14 +9287,14 @@ function qoderProjectRootFromCwds(projectDir, cwds) {
|
|
|
9222
9287
|
return void 0;
|
|
9223
9288
|
}
|
|
9224
9289
|
function encodeQoderProjectPath(value) {
|
|
9225
|
-
return path18.resolve(value).split(path18.sep).join("-").
|
|
9290
|
+
return path18.resolve(value).split(path18.sep).join("-").replaceAll("_", "-");
|
|
9226
9291
|
}
|
|
9227
9292
|
function rawQoderProjectPath(value) {
|
|
9228
9293
|
return path18.resolve(value).split(path18.sep).join("-");
|
|
9229
9294
|
}
|
|
9230
9295
|
function qoderEncodedVariants(value) {
|
|
9231
9296
|
const raw = rawQoderProjectPath(value);
|
|
9232
|
-
const normalized = raw.
|
|
9297
|
+
const normalized = raw.replaceAll("_", "-");
|
|
9233
9298
|
return raw === normalized ? [raw] : [raw, normalized];
|
|
9234
9299
|
}
|
|
9235
9300
|
function qoderEncodedProjectSuffix(projectDir, home) {
|
|
@@ -9385,7 +9450,7 @@ function normalizeId(id) {
|
|
|
9385
9450
|
}
|
|
9386
9451
|
|
|
9387
9452
|
// src/adapters/workbuddy.ts
|
|
9388
|
-
import {
|
|
9453
|
+
import { readdir as readdir9, readFile as readFile12, stat as stat10 } from "node:fs/promises";
|
|
9389
9454
|
import path19 from "node:path";
|
|
9390
9455
|
function workbuddyProjectsDir(home, env) {
|
|
9391
9456
|
const override = env?.WORKBUDDY_PROJECTS_DIR || env?.WORKBUDDY_HOME;
|
|
@@ -9591,7 +9656,9 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9591
9656
|
confidence: "derived",
|
|
9592
9657
|
refs: { sourceId: `${sessionPrefix}:session`, ...subagentRefs }
|
|
9593
9658
|
}, lines[0], filePath, options);
|
|
9594
|
-
if (event)
|
|
9659
|
+
if (event) {
|
|
9660
|
+
events.push(event);
|
|
9661
|
+
}
|
|
9595
9662
|
}
|
|
9596
9663
|
for (const line of lines) {
|
|
9597
9664
|
const record = line.record;
|
|
@@ -9606,7 +9673,9 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9606
9673
|
continue;
|
|
9607
9674
|
}
|
|
9608
9675
|
const ended = closeTurn(line);
|
|
9609
|
-
if (ended)
|
|
9676
|
+
if (ended) {
|
|
9677
|
+
events.push(ended);
|
|
9678
|
+
}
|
|
9610
9679
|
turnIndex += 1;
|
|
9611
9680
|
currentTurnId = `${sessionPrefix}:turn:${turnIndex}`;
|
|
9612
9681
|
turnLastTs = ts;
|
|
@@ -9644,7 +9713,9 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9644
9713
|
refs: { sourceId: `${sourceId}:prompt` }
|
|
9645
9714
|
}, line, filePath, options)
|
|
9646
9715
|
]) {
|
|
9647
|
-
if (event)
|
|
9716
|
+
if (event) {
|
|
9717
|
+
events.push(event);
|
|
9718
|
+
}
|
|
9648
9719
|
}
|
|
9649
9720
|
continue;
|
|
9650
9721
|
}
|
|
@@ -9671,7 +9742,9 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9671
9742
|
confidence: "partial",
|
|
9672
9743
|
refs: { sourceId: `${sourceId}:usage` }
|
|
9673
9744
|
}, line, filePath, options);
|
|
9674
|
-
if (usage)
|
|
9745
|
+
if (usage) {
|
|
9746
|
+
events.push(usage);
|
|
9747
|
+
}
|
|
9675
9748
|
}
|
|
9676
9749
|
continue;
|
|
9677
9750
|
}
|
|
@@ -9698,7 +9771,40 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9698
9771
|
confidence: "exact",
|
|
9699
9772
|
refs: { sourceId: `${callId}:start` }
|
|
9700
9773
|
}, line, filePath, options);
|
|
9701
|
-
if (started)
|
|
9774
|
+
if (started) {
|
|
9775
|
+
events.push(started);
|
|
9776
|
+
}
|
|
9777
|
+
let toolInput;
|
|
9778
|
+
try {
|
|
9779
|
+
toolInput = JSON.parse(stringField(record, "arguments") || "");
|
|
9780
|
+
} catch {
|
|
9781
|
+
toolInput = void 0;
|
|
9782
|
+
}
|
|
9783
|
+
if (isPlainObject(toolInput)) {
|
|
9784
|
+
const fileActivities = claudeStyleToolFileActivities(tool, toolInput, ts, cwd);
|
|
9785
|
+
if (fileActivities.length > 0) {
|
|
9786
|
+
const fileEvent = makeEvent({
|
|
9787
|
+
schemaVersion: AGENT_TIME_SCHEMA_VERSION,
|
|
9788
|
+
ts,
|
|
9789
|
+
type: eventTypeFromFileActivities(fileActivities),
|
|
9790
|
+
source: "workbuddy",
|
|
9791
|
+
workspaceId,
|
|
9792
|
+
project,
|
|
9793
|
+
cwd,
|
|
9794
|
+
sessionId: sessionPrefix,
|
|
9795
|
+
turnId: currentTurnId,
|
|
9796
|
+
agent: "workbuddy",
|
|
9797
|
+
tool,
|
|
9798
|
+
confidence: "derived",
|
|
9799
|
+
fileActivities,
|
|
9800
|
+
metrics: summarizeFileActivities(fileActivities),
|
|
9801
|
+
refs: { sourceId: `${callId}:files` }
|
|
9802
|
+
}, line, filePath, options);
|
|
9803
|
+
if (fileEvent) {
|
|
9804
|
+
events.push(fileEvent);
|
|
9805
|
+
}
|
|
9806
|
+
}
|
|
9807
|
+
}
|
|
9702
9808
|
}
|
|
9703
9809
|
const metrics = workbuddyUsageMetrics(record);
|
|
9704
9810
|
const model = stringField(objectField(record, "providerData"), "model");
|
|
@@ -9719,7 +9825,9 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9719
9825
|
confidence: metrics ? "partial" : "derived",
|
|
9720
9826
|
refs: { sourceId: `${sourceId}:usage:${callId || line.lineNumber}` }
|
|
9721
9827
|
}, line, filePath, options);
|
|
9722
|
-
if (usage)
|
|
9828
|
+
if (usage) {
|
|
9829
|
+
events.push(usage);
|
|
9830
|
+
}
|
|
9723
9831
|
}
|
|
9724
9832
|
continue;
|
|
9725
9833
|
}
|
|
@@ -9748,13 +9856,17 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9748
9856
|
confidence: start ? "derived" : "partial",
|
|
9749
9857
|
refs: { sourceId: `${callId}:result` }
|
|
9750
9858
|
}, line, filePath, options);
|
|
9751
|
-
if (completed)
|
|
9859
|
+
if (completed) {
|
|
9860
|
+
events.push(completed);
|
|
9861
|
+
}
|
|
9752
9862
|
}
|
|
9753
9863
|
}
|
|
9754
9864
|
const lastLine = lines.at(-1);
|
|
9755
9865
|
if (lastLine) {
|
|
9756
9866
|
const ended = closeTurn(lastLine);
|
|
9757
|
-
if (ended)
|
|
9867
|
+
if (ended) {
|
|
9868
|
+
events.push(ended);
|
|
9869
|
+
}
|
|
9758
9870
|
}
|
|
9759
9871
|
const lastTs = lastLine ? timestampFrom(numberField(lastLine.record, "timestamp")) : void 0;
|
|
9760
9872
|
if (lastLine && lastTs) {
|
|
@@ -9771,7 +9883,9 @@ async function parseWorkbuddySessionFile(filePath, options) {
|
|
|
9771
9883
|
confidence: "derived",
|
|
9772
9884
|
refs: { sourceId: `${sessionPrefix}:ended` }
|
|
9773
9885
|
}, lastLine, filePath, options);
|
|
9774
|
-
if (event)
|
|
9886
|
+
if (event) {
|
|
9887
|
+
events.push(event);
|
|
9888
|
+
}
|
|
9775
9889
|
}
|
|
9776
9890
|
return events;
|
|
9777
9891
|
}
|
|
@@ -12425,8 +12539,8 @@ function selectBackfillFilesForImport(files, watermarkTs) {
|
|
|
12425
12539
|
}
|
|
12426
12540
|
}
|
|
12427
12541
|
const order = /* @__PURE__ */ new Map();
|
|
12428
|
-
for (
|
|
12429
|
-
order.set(
|
|
12542
|
+
for (const [i, file] of files.entries()) {
|
|
12543
|
+
order.set(file.path, i);
|
|
12430
12544
|
}
|
|
12431
12545
|
picked.sort((a, b) => (order.get(a.path) ?? 0) - (order.get(b.path) ?? 0));
|
|
12432
12546
|
return picked;
|
package/package.json
CHANGED