modelstat 0.0.46 → 0.0.47
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/dist/cli.mjs +638 -55
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -78,7 +78,7 @@ var init_git = __esm({
|
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
// ../../packages/core/src/enums.ts
|
|
81
|
-
var TOOLS, PROVIDERS, IDENTITY_OWNER_SCOPES, INSTALL_METHODS, OS_FAMILIES, EVENT_KINDS, COMPANION_PHASES, CLASSIFICATION_CONFIDENCE;
|
|
81
|
+
var TOOLS, PROVIDERS, IDENTITY_OWNER_SCOPES, INSTALL_METHODS, OS_FAMILIES, EVENT_KINDS, TOOL_CALL_STATUSES, COMPANION_PHASES, CLASSIFICATION_CONFIDENCE;
|
|
82
82
|
var init_enums = __esm({
|
|
83
83
|
"../../packages/core/src/enums.ts"() {
|
|
84
84
|
"use strict";
|
|
@@ -162,6 +162,13 @@ var init_enums = __esm({
|
|
|
162
162
|
"tool_result",
|
|
163
163
|
"summary"
|
|
164
164
|
];
|
|
165
|
+
TOOL_CALL_STATUSES = [
|
|
166
|
+
"success",
|
|
167
|
+
"error",
|
|
168
|
+
"denied",
|
|
169
|
+
"timeout",
|
|
170
|
+
"unknown"
|
|
171
|
+
];
|
|
165
172
|
COMPANION_PHASES = [
|
|
166
173
|
"starting",
|
|
167
174
|
"discovering",
|
|
@@ -4304,7 +4311,7 @@ var init_zod = __esm({
|
|
|
4304
4311
|
});
|
|
4305
4312
|
|
|
4306
4313
|
// ../../packages/core/src/schemas.ts
|
|
4307
|
-
var TokenUsage, GitContext, RawEvent, RedactionReport, TaxonomyHintRooted, Segment, IngestBatch, HeartbeatPayload, DeviceEnrollment, DeviceSelfRegister, DeviceClaimRequest, ProcessingMetadata, RedactionPolicy, DetectedInstallation, DetectedIdentity, DiscoveryReport, ClassificationConfidenceEnum;
|
|
4314
|
+
var TokenUsage, GitContext, RawEvent, RedactionReport, TaxonomyHintRooted, Segment, ToolCallWire, IngestBatch, HeartbeatPayload, DeviceEnrollment, DeviceSelfRegister, DeviceClaimRequest, ProcessingMetadata, RedactionPolicy, DetectedInstallation, DetectedIdentity, DiscoveryReport, ClassificationConfidenceEnum;
|
|
4308
4315
|
var init_schemas = __esm({
|
|
4309
4316
|
"../../packages/core/src/schemas.ts"() {
|
|
4310
4317
|
"use strict";
|
|
@@ -4409,6 +4416,49 @@ var init_schemas = __esm({
|
|
|
4409
4416
|
* Reserved for server-side similarity / clustering. */
|
|
4410
4417
|
abstract_embedding: external_exports.array(external_exports.number()).length(384).optional()
|
|
4411
4418
|
});
|
|
4419
|
+
ToolCallWire = external_exports.object({
|
|
4420
|
+
/** tool_use block `id` / codex `call_id`; parsers fall back to a
|
|
4421
|
+
* deterministic `tc_<djb2-base36>` of `${source_event_id}|${call_index}`
|
|
4422
|
+
* when the source line carries no id. */
|
|
4423
|
+
external_call_id: external_exports.string().max(120),
|
|
4424
|
+
/** Tool-local session id — same id space as RawEvent.session_id. */
|
|
4425
|
+
session_id: external_exports.string().max(120),
|
|
4426
|
+
/** The RawEvent that contained the tool_use (dedupe/replay anchor). */
|
|
4427
|
+
source_event_id: external_exports.string(),
|
|
4428
|
+
/** Segment containing source_event_id — filled by the companion at
|
|
4429
|
+
* batch-build time when known, else null. */
|
|
4430
|
+
segment_id: external_exports.string().max(64).nullable().default(null),
|
|
4431
|
+
/** The agent that made the call (TOOLS enum — "tool" in legacy naming). */
|
|
4432
|
+
agent: external_exports.enum(TOOLS),
|
|
4433
|
+
/** `builtin` or `mcp:<server>`. */
|
|
4434
|
+
server: external_exports.string().max(120),
|
|
4435
|
+
/** Bare tool name (`Bash`, `create_pr`) — normalised vendor identifier. */
|
|
4436
|
+
name: external_exports.string().max(120),
|
|
4437
|
+
turn_index: external_exports.number().int().nonnegative().nullable(),
|
|
4438
|
+
/** Ordinal of the call within its source event (0-based). */
|
|
4439
|
+
call_index: external_exports.number().int().nonnegative(),
|
|
4440
|
+
/** ts of the line carrying the tool_use. */
|
|
4441
|
+
started_at: external_exports.string().datetime({ offset: true }),
|
|
4442
|
+
/** ts of the line carrying the matching tool_result; null if unmatched. */
|
|
4443
|
+
ended_at: external_exports.string().datetime({ offset: true }).nullable(),
|
|
4444
|
+
status: external_exports.enum(TOOL_CALL_STATUSES),
|
|
4445
|
+
/** Hex sha256 of JSON.stringify(input); `""` when the call had no input. */
|
|
4446
|
+
args_hash: external_exports.string().max(64),
|
|
4447
|
+
/** Sha256 of the sorted top-level arg key names joined by `,`; the
|
|
4448
|
+
* literal `none` when input is not a non-empty object. */
|
|
4449
|
+
signature_hash: external_exports.string().max(64),
|
|
4450
|
+
/** UTF-8 byte length of JSON.stringify(input); 0 if none. */
|
|
4451
|
+
args_bytes: external_exports.number().int().nonnegative(),
|
|
4452
|
+
/** UTF-8 byte length of JSON.stringify(tool_result content); 0 if
|
|
4453
|
+
* unmatched/empty. */
|
|
4454
|
+
result_bytes: external_exports.number().int().nonnegative(),
|
|
4455
|
+
/** Model of the assistant message that issued the call. `<synthetic>`
|
|
4456
|
+
* kept verbatim per the PR #12 attribution rules. */
|
|
4457
|
+
model: external_exports.string().max(120).nullable(),
|
|
4458
|
+
/** ONLY for shell-ish tools: command verbs from the fixed allowlist
|
|
4459
|
+
* (@modelstat/parsers/shell-families). Never raw command text. */
|
|
4460
|
+
command_families: external_exports.array(external_exports.string().max(40)).max(3).default([])
|
|
4461
|
+
});
|
|
4412
4462
|
IngestBatch = external_exports.object({
|
|
4413
4463
|
batch_id: external_exports.string(),
|
|
4414
4464
|
// ULID
|
|
@@ -4416,6 +4466,10 @@ var init_schemas = __esm({
|
|
|
4416
4466
|
agent_version: external_exports.string().max(40),
|
|
4417
4467
|
events: external_exports.array(RawEvent).max(1e4),
|
|
4418
4468
|
segments: external_exports.array(Segment).max(2e3).default([]),
|
|
4469
|
+
/** Per-call tool invocations (additive — old agents omit it, old
|
|
4470
|
+
* servers ignore it). See ToolCallWire for the privacy contract:
|
|
4471
|
+
* hashes / byte sizes / allowlisted verbs only, never payloads. */
|
|
4472
|
+
tool_calls: external_exports.array(ToolCallWire).max(2e4).default([]),
|
|
4419
4473
|
/** Optional per-session metadata hint: which installation produced them, etc. */
|
|
4420
4474
|
session_installs: external_exports.record(
|
|
4421
4475
|
external_exports.string(),
|
|
@@ -4684,22 +4738,222 @@ var init_src = __esm({
|
|
|
4684
4738
|
}
|
|
4685
4739
|
});
|
|
4686
4740
|
|
|
4687
|
-
// ../../packages/parsers/src/
|
|
4741
|
+
// ../../packages/parsers/src/shell-families/index.ts
|
|
4742
|
+
function extractCommandFamilies(command) {
|
|
4743
|
+
const families = [];
|
|
4744
|
+
for (const part of splitCommandParts(command)) {
|
|
4745
|
+
const verb = leadingVerb(part);
|
|
4746
|
+
if (!verb || !ALLOWLIST.has(verb)) continue;
|
|
4747
|
+
if (!families.includes(verb)) families.push(verb);
|
|
4748
|
+
if (families.length >= MAX_COMMAND_FAMILIES) break;
|
|
4749
|
+
}
|
|
4750
|
+
return families;
|
|
4751
|
+
}
|
|
4752
|
+
function splitCommandParts(command) {
|
|
4753
|
+
const parts = [];
|
|
4754
|
+
let current = "";
|
|
4755
|
+
let inSingle = false;
|
|
4756
|
+
let inDouble = false;
|
|
4757
|
+
for (let i = 0; i < command.length; i++) {
|
|
4758
|
+
const ch = command[i];
|
|
4759
|
+
if (!inSingle && ch === "\\") {
|
|
4760
|
+
current += ch + (command[i + 1] ?? "");
|
|
4761
|
+
i++;
|
|
4762
|
+
continue;
|
|
4763
|
+
}
|
|
4764
|
+
if (ch === "'" && !inDouble) {
|
|
4765
|
+
inSingle = !inSingle;
|
|
4766
|
+
current += ch;
|
|
4767
|
+
continue;
|
|
4768
|
+
}
|
|
4769
|
+
if (ch === '"' && !inSingle) {
|
|
4770
|
+
inDouble = !inDouble;
|
|
4771
|
+
current += ch;
|
|
4772
|
+
continue;
|
|
4773
|
+
}
|
|
4774
|
+
if (!inSingle && !inDouble) {
|
|
4775
|
+
if (ch === ";" || ch === "|" || ch === "\n") {
|
|
4776
|
+
parts.push(current);
|
|
4777
|
+
current = "";
|
|
4778
|
+
continue;
|
|
4779
|
+
}
|
|
4780
|
+
if (ch === "&" && command[i + 1] === "&") {
|
|
4781
|
+
parts.push(current);
|
|
4782
|
+
current = "";
|
|
4783
|
+
i++;
|
|
4784
|
+
continue;
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4787
|
+
current += ch;
|
|
4788
|
+
}
|
|
4789
|
+
parts.push(current);
|
|
4790
|
+
return parts;
|
|
4791
|
+
}
|
|
4792
|
+
function leadingVerb(part) {
|
|
4793
|
+
const tokens = part.trim().split(/\s+/);
|
|
4794
|
+
let i = 0;
|
|
4795
|
+
while (i < tokens.length) {
|
|
4796
|
+
const tok = stripQuotes(tokens[i] ?? "");
|
|
4797
|
+
if (tok === "") {
|
|
4798
|
+
i++;
|
|
4799
|
+
continue;
|
|
4800
|
+
}
|
|
4801
|
+
if (VAR_ASSIGNMENT.test(tok)) {
|
|
4802
|
+
i++;
|
|
4803
|
+
continue;
|
|
4804
|
+
}
|
|
4805
|
+
if (WRAPPERS.has(tok)) {
|
|
4806
|
+
i++;
|
|
4807
|
+
while (i < tokens.length && (tokens[i] ?? "").startsWith("-")) i++;
|
|
4808
|
+
continue;
|
|
4809
|
+
}
|
|
4810
|
+
const base = tok.split("/").pop() ?? tok;
|
|
4811
|
+
return base === "" ? null : base;
|
|
4812
|
+
}
|
|
4813
|
+
return null;
|
|
4814
|
+
}
|
|
4815
|
+
function stripQuotes(token) {
|
|
4816
|
+
if (token.length >= 2) {
|
|
4817
|
+
const first = token[0];
|
|
4818
|
+
const last = token[token.length - 1];
|
|
4819
|
+
if (first === "'" && last === "'" || first === '"' && last === '"') {
|
|
4820
|
+
return token.slice(1, -1);
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
return token;
|
|
4824
|
+
}
|
|
4825
|
+
var SHELL_FAMILY_ALLOWLIST, MAX_COMMAND_FAMILIES, ALLOWLIST, WRAPPERS, VAR_ASSIGNMENT;
|
|
4826
|
+
var init_shell_families = __esm({
|
|
4827
|
+
"../../packages/parsers/src/shell-families/index.ts"() {
|
|
4828
|
+
"use strict";
|
|
4829
|
+
SHELL_FAMILY_ALLOWLIST = [
|
|
4830
|
+
"git",
|
|
4831
|
+
"npm",
|
|
4832
|
+
"pnpm",
|
|
4833
|
+
"npx",
|
|
4834
|
+
"yarn",
|
|
4835
|
+
"node",
|
|
4836
|
+
"python",
|
|
4837
|
+
"python3",
|
|
4838
|
+
"pytest",
|
|
4839
|
+
"pip",
|
|
4840
|
+
"pip3",
|
|
4841
|
+
"cargo",
|
|
4842
|
+
"rustc",
|
|
4843
|
+
"go",
|
|
4844
|
+
"make",
|
|
4845
|
+
"cmake",
|
|
4846
|
+
"docker",
|
|
4847
|
+
"docker-compose",
|
|
4848
|
+
"kubectl",
|
|
4849
|
+
"helm",
|
|
4850
|
+
"terraform",
|
|
4851
|
+
"gh",
|
|
4852
|
+
"aws",
|
|
4853
|
+
"gcloud",
|
|
4854
|
+
"az",
|
|
4855
|
+
"curl",
|
|
4856
|
+
"wget",
|
|
4857
|
+
"rg",
|
|
4858
|
+
"grep",
|
|
4859
|
+
"find",
|
|
4860
|
+
"sed",
|
|
4861
|
+
"awk",
|
|
4862
|
+
"jq",
|
|
4863
|
+
"psql",
|
|
4864
|
+
"mysql",
|
|
4865
|
+
"redis-cli",
|
|
4866
|
+
"brew",
|
|
4867
|
+
"apt",
|
|
4868
|
+
"tsx",
|
|
4869
|
+
"vitest",
|
|
4870
|
+
"jest",
|
|
4871
|
+
"playwright",
|
|
4872
|
+
"ruby",
|
|
4873
|
+
"bundle",
|
|
4874
|
+
"mvn",
|
|
4875
|
+
"gradle",
|
|
4876
|
+
"ls",
|
|
4877
|
+
"cat"
|
|
4878
|
+
];
|
|
4879
|
+
MAX_COMMAND_FAMILIES = 3;
|
|
4880
|
+
ALLOWLIST = new Set(SHELL_FAMILY_ALLOWLIST);
|
|
4881
|
+
WRAPPERS = /* @__PURE__ */ new Set(["sudo", "env", "time", "nice"]);
|
|
4882
|
+
VAR_ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
4883
|
+
}
|
|
4884
|
+
});
|
|
4885
|
+
|
|
4886
|
+
// ../../packages/parsers/src/tool-hash/index.ts
|
|
4688
4887
|
import { createHash } from "crypto";
|
|
4888
|
+
function hashArgs(input) {
|
|
4889
|
+
if (input === void 0 || input === null) {
|
|
4890
|
+
return { args_hash: "", signature_hash: SIGNATURE_NONE, args_bytes: 0 };
|
|
4891
|
+
}
|
|
4892
|
+
const json = JSON.stringify(input);
|
|
4893
|
+
if (json === void 0) {
|
|
4894
|
+
return { args_hash: "", signature_hash: SIGNATURE_NONE, args_bytes: 0 };
|
|
4895
|
+
}
|
|
4896
|
+
const argsHash = createHash("sha256").update(json).digest("hex");
|
|
4897
|
+
let signatureHash = SIGNATURE_NONE;
|
|
4898
|
+
if (typeof input === "object" && !Array.isArray(input)) {
|
|
4899
|
+
const keys = Object.keys(input).sort();
|
|
4900
|
+
if (keys.length > 0) {
|
|
4901
|
+
signatureHash = createHash("sha256").update(keys.join(",")).digest("hex");
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
return {
|
|
4905
|
+
args_hash: argsHash,
|
|
4906
|
+
signature_hash: signatureHash,
|
|
4907
|
+
args_bytes: Buffer.byteLength(json, "utf8")
|
|
4908
|
+
};
|
|
4909
|
+
}
|
|
4910
|
+
function jsonBytes(value) {
|
|
4911
|
+
if (value === void 0 || value === null || value === "") return 0;
|
|
4912
|
+
const json = JSON.stringify(value);
|
|
4913
|
+
return json === void 0 ? 0 : Buffer.byteLength(json, "utf8");
|
|
4914
|
+
}
|
|
4915
|
+
function normalizeToolName(raw) {
|
|
4916
|
+
const cleaned = raw.normalize("NFC").trim().replace(UUID_RE, "<dyn>").replace(HEX_TAIL_RE, "<dyn>");
|
|
4917
|
+
return cleaned.slice(0, 120);
|
|
4918
|
+
}
|
|
4919
|
+
function splitObservedToolName(observed) {
|
|
4920
|
+
const m = /^mcp__([^_].*?)__(.+)$/.exec(observed.trim());
|
|
4921
|
+
if (m?.[1] && m[2]) {
|
|
4922
|
+
return {
|
|
4923
|
+
server: `mcp:${normalizeToolName(m[1]).slice(0, 116)}`,
|
|
4924
|
+
name: normalizeToolName(m[2])
|
|
4925
|
+
};
|
|
4926
|
+
}
|
|
4927
|
+
return { server: "builtin", name: normalizeToolName(observed) };
|
|
4928
|
+
}
|
|
4929
|
+
function toolIdentity(server, name) {
|
|
4930
|
+
return server === "builtin" ? name : `${server}/${name}`;
|
|
4931
|
+
}
|
|
4932
|
+
function fallbackCallId(sourceEventId2, callIndex) {
|
|
4933
|
+
const s = `${sourceEventId2}|${callIndex}`;
|
|
4934
|
+
let h = 5381n;
|
|
4935
|
+
for (let i = 0; i < s.length; i++) {
|
|
4936
|
+
h = h * 33n ^ BigInt(s.charCodeAt(i));
|
|
4937
|
+
h &= 0xffffffffffffffffn;
|
|
4938
|
+
}
|
|
4939
|
+
return `tc_${h.toString(36)}`;
|
|
4940
|
+
}
|
|
4941
|
+
var SIGNATURE_NONE, UUID_RE, HEX_TAIL_RE;
|
|
4942
|
+
var init_tool_hash = __esm({
|
|
4943
|
+
"../../packages/parsers/src/tool-hash/index.ts"() {
|
|
4944
|
+
"use strict";
|
|
4945
|
+
SIGNATURE_NONE = "none";
|
|
4946
|
+
UUID_RE = /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g;
|
|
4947
|
+
HEX_TAIL_RE = /[0-9a-fA-F]{8,}(?=$|[^0-9a-zA-Z])/g;
|
|
4948
|
+
}
|
|
4949
|
+
});
|
|
4950
|
+
|
|
4951
|
+
// ../../packages/parsers/src/claude-code/index.ts
|
|
4952
|
+
import { createHash as createHash2 } from "crypto";
|
|
4689
4953
|
import { createReadStream, existsSync as existsSync2, readdirSync } from "fs";
|
|
4690
4954
|
import { stat } from "fs/promises";
|
|
4691
4955
|
import { dirname as dirname2, join } from "path";
|
|
4692
4956
|
import { createInterface } from "readline";
|
|
4693
|
-
function countToolCalls(content) {
|
|
4694
|
-
const counts = {};
|
|
4695
|
-
if (!Array.isArray(content)) return counts;
|
|
4696
|
-
for (const block of content) {
|
|
4697
|
-
if (block && block.type === "tool_use" && typeof block.name === "string" && block.name) {
|
|
4698
|
-
counts[block.name] = (counts[block.name] ?? 0) + 1;
|
|
4699
|
-
}
|
|
4700
|
-
}
|
|
4701
|
-
return counts;
|
|
4702
|
-
}
|
|
4703
4957
|
function extractExcerpt(content) {
|
|
4704
4958
|
if (!content) return void 0;
|
|
4705
4959
|
let text = "";
|
|
@@ -4722,8 +4976,41 @@ function extractExcerpt(content) {
|
|
|
4722
4976
|
const truncated = cleaned.slice(0, 320);
|
|
4723
4977
|
return truncated.length > 0 ? truncated : void 0;
|
|
4724
4978
|
}
|
|
4979
|
+
function commandFamiliesFor(server, name, input) {
|
|
4980
|
+
if (server !== "builtin" || !SHELL_TOOL_NAMES.has(name)) return [];
|
|
4981
|
+
if (typeof input !== "object" || input === null) return [];
|
|
4982
|
+
const command = input.command;
|
|
4983
|
+
return typeof command === "string" ? extractCommandFamilies(command) : [];
|
|
4984
|
+
}
|
|
4985
|
+
function buildToolCallDraft(opts) {
|
|
4986
|
+
const { server, name } = splitObservedToolName(opts.observedName);
|
|
4987
|
+
const hashes = hashArgs(opts.input);
|
|
4988
|
+
return {
|
|
4989
|
+
external_call_id: typeof opts.rawCallId === "string" && opts.rawCallId.trim() !== "" ? opts.rawCallId.trim().slice(0, 120) : fallbackCallId(opts.sourceEventId, opts.callIndex),
|
|
4990
|
+
session_id: opts.sessionId,
|
|
4991
|
+
source_event_id: opts.sourceEventId,
|
|
4992
|
+
agent: "claude_code",
|
|
4993
|
+
server,
|
|
4994
|
+
name,
|
|
4995
|
+
// This parser never derives a turn index (events above carry
|
|
4996
|
+
// turn_index: null too), so per-call records can't either.
|
|
4997
|
+
turn_index: null,
|
|
4998
|
+
call_index: opts.callIndex,
|
|
4999
|
+
started_at: opts.startedAt,
|
|
5000
|
+
ended_at: null,
|
|
5001
|
+
status: "unknown",
|
|
5002
|
+
args_hash: hashes.args_hash,
|
|
5003
|
+
signature_hash: hashes.signature_hash,
|
|
5004
|
+
args_bytes: hashes.args_bytes,
|
|
5005
|
+
result_bytes: 0,
|
|
5006
|
+
model: opts.model,
|
|
5007
|
+
command_families: commandFamiliesFor(server, name, opts.input)
|
|
5008
|
+
};
|
|
5009
|
+
}
|
|
4725
5010
|
async function parseClaudeCodeJsonl(ctx) {
|
|
4726
5011
|
const events = [];
|
|
5012
|
+
const toolCalls = [];
|
|
5013
|
+
const pendingByCallId = /* @__PURE__ */ new Map();
|
|
4727
5014
|
let chunk = [];
|
|
4728
5015
|
let emitted = 0;
|
|
4729
5016
|
const emit = async (e) => {
|
|
@@ -4826,6 +5113,32 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
4826
5113
|
}
|
|
4827
5114
|
const slug = guessRepoSlugFromPath(cwd);
|
|
4828
5115
|
const excerpt = extractExcerpt(a.message?.content);
|
|
5116
|
+
const aggregate = {};
|
|
5117
|
+
const blocks = Array.isArray(a.message?.content) ? a.message.content : [];
|
|
5118
|
+
let callIndex = 0;
|
|
5119
|
+
for (const block of blocks) {
|
|
5120
|
+
if (!block || block.type !== "tool_use") continue;
|
|
5121
|
+
const index = callIndex;
|
|
5122
|
+
callIndex += 1;
|
|
5123
|
+
const observed = typeof block.name === "string" ? block.name.trim() : "";
|
|
5124
|
+
if (!observed) continue;
|
|
5125
|
+
const draft = buildToolCallDraft({
|
|
5126
|
+
observedName: observed,
|
|
5127
|
+
rawCallId: block.id,
|
|
5128
|
+
input: block.input,
|
|
5129
|
+
sessionId,
|
|
5130
|
+
sourceEventId: eventId,
|
|
5131
|
+
callIndex: index,
|
|
5132
|
+
startedAt: a.timestamp,
|
|
5133
|
+
// Model verbatim from the issuing assistant message —
|
|
5134
|
+
// including "<synthetic>" (same rule as the event below).
|
|
5135
|
+
model: a.message?.model ?? null
|
|
5136
|
+
});
|
|
5137
|
+
const identity = toolIdentity(draft.server, draft.name);
|
|
5138
|
+
aggregate[identity] = (aggregate[identity] ?? 0) + 1;
|
|
5139
|
+
toolCalls.push(draft);
|
|
5140
|
+
if (typeof block.id === "string" && block.id) pendingByCallId.set(block.id, draft);
|
|
5141
|
+
}
|
|
4829
5142
|
await emit({
|
|
4830
5143
|
source_event_id: eventId,
|
|
4831
5144
|
ts: a.timestamp,
|
|
@@ -4852,7 +5165,7 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
4852
5165
|
reasoning: 0
|
|
4853
5166
|
},
|
|
4854
5167
|
duration_ms: null,
|
|
4855
|
-
tool_calls:
|
|
5168
|
+
tool_calls: aggregate,
|
|
4856
5169
|
files_touched: [],
|
|
4857
5170
|
...excerpt ? { content_excerpt: excerpt } : {},
|
|
4858
5171
|
source_file: ctx.sourceFile,
|
|
@@ -4865,6 +5178,20 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
4865
5178
|
});
|
|
4866
5179
|
} else if (obj.type === "user") {
|
|
4867
5180
|
const u = obj;
|
|
5181
|
+
const uContent = u.message?.content;
|
|
5182
|
+
if (Array.isArray(uContent)) {
|
|
5183
|
+
for (const block of uContent) {
|
|
5184
|
+
if (!block || block.type !== "tool_result") continue;
|
|
5185
|
+
const ref = block.tool_use_id;
|
|
5186
|
+
if (typeof ref !== "string") continue;
|
|
5187
|
+
const draft = pendingByCallId.get(ref);
|
|
5188
|
+
if (!draft) continue;
|
|
5189
|
+
pendingByCallId.delete(ref);
|
|
5190
|
+
draft.ended_at = u.timestamp;
|
|
5191
|
+
draft.status = block.is_error === true ? "error" : "success";
|
|
5192
|
+
draft.result_bytes = jsonBytes(block.content);
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
4868
5195
|
if (!u.uuid || !sessionId) {
|
|
4869
5196
|
skipped += 1;
|
|
4870
5197
|
continue;
|
|
@@ -4896,6 +5223,30 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
4896
5223
|
source_byte_offset: offsetAtLineStart,
|
|
4897
5224
|
billing: "subscription"
|
|
4898
5225
|
});
|
|
5226
|
+
} else if (obj.type === "tool_use") {
|
|
5227
|
+
const t = obj;
|
|
5228
|
+
const observed = typeof t.name === "string" ? t.name.trim() : "";
|
|
5229
|
+
const ts = typeof t.timestamp === "string" ? t.timestamp : null;
|
|
5230
|
+
const sid = (typeof t.sessionId === "string" ? t.sessionId : null) ?? sessionId;
|
|
5231
|
+
if (!observed || !ts || !sid) {
|
|
5232
|
+
skipped += 1;
|
|
5233
|
+
continue;
|
|
5234
|
+
}
|
|
5235
|
+
const draft = buildToolCallDraft({
|
|
5236
|
+
observedName: observed,
|
|
5237
|
+
rawCallId: t.id,
|
|
5238
|
+
input: t.input,
|
|
5239
|
+
sessionId: sid,
|
|
5240
|
+
sourceEventId: sourceEventId(ctx.deviceId, ctx.sourceFile, offsetAtLineStart),
|
|
5241
|
+
callIndex: 0,
|
|
5242
|
+
startedAt: ts,
|
|
5243
|
+
// No issuing assistant message on this line — attribute to the
|
|
5244
|
+
// session's last real model, same as user_message attribution
|
|
5245
|
+
// (lastModel never holds "<synthetic>", per the rule above).
|
|
5246
|
+
model: lastModel
|
|
5247
|
+
});
|
|
5248
|
+
toolCalls.push(draft);
|
|
5249
|
+
if (typeof t.id === "string" && t.id) pendingByCallId.set(t.id, draft);
|
|
4899
5250
|
} else {
|
|
4900
5251
|
skipped += 1;
|
|
4901
5252
|
}
|
|
@@ -4903,6 +5254,7 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
4903
5254
|
if (ctx.onEvents && chunk.length > 0) await ctx.onEvents(chunk);
|
|
4904
5255
|
return {
|
|
4905
5256
|
events,
|
|
5257
|
+
toolCalls,
|
|
4906
5258
|
stats: { rawLines, emittedEvents: emitted, skipped },
|
|
4907
5259
|
sourceFile: ctx.sourceFile
|
|
4908
5260
|
};
|
|
@@ -4917,16 +5269,26 @@ async function quickChecksum(path5) {
|
|
|
4917
5269
|
start: Math.max(0, st.size - 4096),
|
|
4918
5270
|
encoding: "utf8"
|
|
4919
5271
|
});
|
|
4920
|
-
const h =
|
|
5272
|
+
const h = createHash2("sha1");
|
|
4921
5273
|
for await (const chunk of stream) h.update(chunk);
|
|
4922
5274
|
return { size: st.size, mtime: st.mtimeMs, tailHash: h.digest("hex").slice(0, 16) };
|
|
4923
5275
|
}
|
|
5276
|
+
var SHELL_TOOL_NAMES;
|
|
4924
5277
|
var init_claude_code = __esm({
|
|
4925
5278
|
"../../packages/parsers/src/claude-code/index.ts"() {
|
|
4926
5279
|
"use strict";
|
|
4927
5280
|
init_src();
|
|
4928
|
-
init_types();
|
|
4929
5281
|
init_git();
|
|
5282
|
+
init_shell_families();
|
|
5283
|
+
init_tool_hash();
|
|
5284
|
+
init_types();
|
|
5285
|
+
SHELL_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
5286
|
+
"Bash",
|
|
5287
|
+
"shell",
|
|
5288
|
+
"local_shell_call",
|
|
5289
|
+
"exec_command",
|
|
5290
|
+
"run_terminal_cmd"
|
|
5291
|
+
]);
|
|
4930
5292
|
}
|
|
4931
5293
|
});
|
|
4932
5294
|
|
|
@@ -4939,8 +5301,90 @@ function deriveSessionIdFromRolloutPath(path5) {
|
|
|
4939
5301
|
);
|
|
4940
5302
|
return m ? m[1] ?? null : null;
|
|
4941
5303
|
}
|
|
5304
|
+
function commandFieldToString(cmd) {
|
|
5305
|
+
if (typeof cmd === "string") return cmd || null;
|
|
5306
|
+
if (Array.isArray(cmd)) {
|
|
5307
|
+
const parts = cmd.filter((p) => typeof p === "string");
|
|
5308
|
+
if (parts.length === 0) return null;
|
|
5309
|
+
const head = (parts[0] ?? "").split("/").pop() ?? "";
|
|
5310
|
+
const flag = parts[1] ?? "";
|
|
5311
|
+
if (parts.length >= 3 && SHELL_WRAPPER_BINARIES.has(head) && /^-[a-z]*c[a-z]*$/i.test(flag)) {
|
|
5312
|
+
return parts.slice(2).join("\n");
|
|
5313
|
+
}
|
|
5314
|
+
return parts.join(" ");
|
|
5315
|
+
}
|
|
5316
|
+
return null;
|
|
5317
|
+
}
|
|
5318
|
+
function firstString(...values) {
|
|
5319
|
+
for (const v of values) {
|
|
5320
|
+
if (typeof v === "string" && v) return v;
|
|
5321
|
+
}
|
|
5322
|
+
return null;
|
|
5323
|
+
}
|
|
5324
|
+
function extractToolCallPayload(pt, p) {
|
|
5325
|
+
const callId = firstString(p.call_id, p.id);
|
|
5326
|
+
const failed = p.status === "failed";
|
|
5327
|
+
if (pt === "local_shell_call") {
|
|
5328
|
+
const action = p.action && typeof p.action === "object" ? p.action : null;
|
|
5329
|
+
const command = commandFieldToString(action?.command);
|
|
5330
|
+
return {
|
|
5331
|
+
callId,
|
|
5332
|
+
server: "builtin",
|
|
5333
|
+
name: "shell",
|
|
5334
|
+
input: action,
|
|
5335
|
+
commandFamilies: command ? extractCommandFamilies(command) : [],
|
|
5336
|
+
failed
|
|
5337
|
+
};
|
|
5338
|
+
}
|
|
5339
|
+
const observed = firstString(p.name, p.tool);
|
|
5340
|
+
if (!observed) return null;
|
|
5341
|
+
let input = pt === "custom_tool_call" ? p.input : p.arguments ?? p.input;
|
|
5342
|
+
if (typeof input === "string" && !input.trim()) input = void 0;
|
|
5343
|
+
if (pt !== "custom_tool_call" && typeof input === "string") {
|
|
5344
|
+
try {
|
|
5345
|
+
input = JSON.parse(input);
|
|
5346
|
+
} catch {
|
|
5347
|
+
}
|
|
5348
|
+
}
|
|
5349
|
+
if (SHELL_TOOL_NAMES2.has(observed)) {
|
|
5350
|
+
const rec = input && typeof input === "object" && !Array.isArray(input) ? input : null;
|
|
5351
|
+
const command = commandFieldToString(
|
|
5352
|
+
rec?.command ?? rec?.cmd ?? (typeof input === "string" ? input : null)
|
|
5353
|
+
);
|
|
5354
|
+
return {
|
|
5355
|
+
callId,
|
|
5356
|
+
server: "builtin",
|
|
5357
|
+
name: "shell",
|
|
5358
|
+
input,
|
|
5359
|
+
commandFamilies: command ? extractCommandFamilies(command) : [],
|
|
5360
|
+
failed
|
|
5361
|
+
};
|
|
5362
|
+
}
|
|
5363
|
+
if (pt === "mcp_tool_call" && typeof p.server === "string" && p.server) {
|
|
5364
|
+
return {
|
|
5365
|
+
callId,
|
|
5366
|
+
// Mirror splitObservedToolName's cap: 116 + the `mcp:` prefix ≤ 120.
|
|
5367
|
+
server: `mcp:${normalizeToolName(p.server).slice(0, 116)}`,
|
|
5368
|
+
name: normalizeToolName(observed),
|
|
5369
|
+
input,
|
|
5370
|
+
commandFamilies: [],
|
|
5371
|
+
failed
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
const { server, name } = splitObservedToolName(observed);
|
|
5375
|
+
return { callId, server, name, input, commandFamilies: [], failed };
|
|
5376
|
+
}
|
|
5377
|
+
function outputIndicatesError(p) {
|
|
5378
|
+
const out = p.output ?? p.result;
|
|
5379
|
+
if (out && typeof out === "object" && !Array.isArray(out)) {
|
|
5380
|
+
const o = out;
|
|
5381
|
+
if (o.success === false || o.is_error === true) return true;
|
|
5382
|
+
}
|
|
5383
|
+
return false;
|
|
5384
|
+
}
|
|
4942
5385
|
async function parseCodexRollout(ctx) {
|
|
4943
5386
|
const events = [];
|
|
5387
|
+
const toolCalls = [];
|
|
4944
5388
|
let chunk = [];
|
|
4945
5389
|
let emitted = 0;
|
|
4946
5390
|
const emit = async (e) => {
|
|
@@ -4969,6 +5413,9 @@ async function parseCodexRollout(ctx) {
|
|
|
4969
5413
|
let cwd = null;
|
|
4970
5414
|
let model = null;
|
|
4971
5415
|
let turnIndex = 0;
|
|
5416
|
+
let lastTs = null;
|
|
5417
|
+
const openCalls = /* @__PURE__ */ new Map();
|
|
5418
|
+
let pendingToolAggregate = {};
|
|
4972
5419
|
for await (const line of rl) {
|
|
4973
5420
|
const byteLen = Buffer.byteLength(line, "utf8") + 1;
|
|
4974
5421
|
const offsetAtLineStart = startOffset + bytePos;
|
|
@@ -4985,22 +5432,91 @@ async function parseCodexRollout(ctx) {
|
|
|
4985
5432
|
skipped += 1;
|
|
4986
5433
|
continue;
|
|
4987
5434
|
}
|
|
5435
|
+
const lineTs = obj.timestamp;
|
|
5436
|
+
if (typeof lineTs === "string" && lineTs) lastTs = lineTs;
|
|
4988
5437
|
if (obj.type === "session_meta") {
|
|
4989
5438
|
const m = obj;
|
|
4990
|
-
|
|
5439
|
+
const id = m.id ?? m.payload?.id ?? null;
|
|
5440
|
+
if (id && id !== sessionId) {
|
|
5441
|
+
sessionId = id;
|
|
5442
|
+
pendingToolAggregate = {};
|
|
5443
|
+
openCalls.clear();
|
|
5444
|
+
}
|
|
4991
5445
|
continue;
|
|
4992
5446
|
}
|
|
4993
5447
|
if (obj.type === "turn_context") {
|
|
4994
5448
|
const t = obj;
|
|
4995
|
-
cwd = t.cwd ?? cwd;
|
|
4996
|
-
model = t.model ?? model;
|
|
5449
|
+
cwd = t.cwd ?? t.payload?.cwd ?? cwd;
|
|
5450
|
+
model = t.model ?? t.payload?.model ?? model;
|
|
5451
|
+
continue;
|
|
5452
|
+
}
|
|
5453
|
+
if (obj.type === "response_item") {
|
|
5454
|
+
const r = obj;
|
|
5455
|
+
const payload = r.payload;
|
|
5456
|
+
const pt = payload && typeof payload.type === "string" ? payload.type : null;
|
|
5457
|
+
if (pt && TOOL_CALL_PAYLOAD_TYPES.has(pt) && sessionId) {
|
|
5458
|
+
const extracted = extractToolCallPayload(pt, payload);
|
|
5459
|
+
if (!extracted) {
|
|
5460
|
+
skipped += 1;
|
|
5461
|
+
continue;
|
|
5462
|
+
}
|
|
5463
|
+
const ts = r.timestamp ?? lastTs;
|
|
5464
|
+
if (!ts) {
|
|
5465
|
+
skipped += 1;
|
|
5466
|
+
continue;
|
|
5467
|
+
}
|
|
5468
|
+
const srcId = sourceEventId(ctx.deviceId, ctx.sourceFile, offsetAtLineStart);
|
|
5469
|
+
const { args_hash, signature_hash, args_bytes } = hashArgs(extracted.input);
|
|
5470
|
+
const draft = {
|
|
5471
|
+
external_call_id: (extracted.callId ?? fallbackCallId(srcId, 0)).slice(0, 120),
|
|
5472
|
+
session_id: sessionId,
|
|
5473
|
+
source_event_id: srcId,
|
|
5474
|
+
agent: "codex_cli",
|
|
5475
|
+
server: extracted.server,
|
|
5476
|
+
name: extracted.name,
|
|
5477
|
+
turn_index: turnIndex,
|
|
5478
|
+
// Each response_item line carries exactly one call.
|
|
5479
|
+
call_index: 0,
|
|
5480
|
+
started_at: ts,
|
|
5481
|
+
ended_at: null,
|
|
5482
|
+
status: extracted.failed ? "error" : "unknown",
|
|
5483
|
+
args_hash,
|
|
5484
|
+
signature_hash,
|
|
5485
|
+
args_bytes,
|
|
5486
|
+
result_bytes: 0,
|
|
5487
|
+
model,
|
|
5488
|
+
command_families: extracted.commandFamilies
|
|
5489
|
+
};
|
|
5490
|
+
toolCalls.push(draft);
|
|
5491
|
+
if (extracted.callId) openCalls.set(extracted.callId, draft);
|
|
5492
|
+
const identity = toolIdentity(extracted.server, extracted.name);
|
|
5493
|
+
pendingToolAggregate[identity] = (pendingToolAggregate[identity] ?? 0) + 1;
|
|
5494
|
+
continue;
|
|
5495
|
+
}
|
|
5496
|
+
if (pt && TOOL_CALL_OUTPUT_PAYLOAD_TYPES.has(pt)) {
|
|
5497
|
+
const p = payload;
|
|
5498
|
+
const callId = firstString(p.call_id, p.id);
|
|
5499
|
+
const open2 = callId ? openCalls.get(callId) : void 0;
|
|
5500
|
+
if (!callId || !open2) {
|
|
5501
|
+
skipped += 1;
|
|
5502
|
+
continue;
|
|
5503
|
+
}
|
|
5504
|
+
openCalls.delete(callId);
|
|
5505
|
+
open2.ended_at = r.timestamp ?? lastTs ?? open2.started_at;
|
|
5506
|
+
open2.result_bytes = jsonBytes(p.output ?? p.result);
|
|
5507
|
+
if (open2.status === "unknown") {
|
|
5508
|
+
open2.status = outputIndicatesError(p) ? "error" : "success";
|
|
5509
|
+
}
|
|
5510
|
+
continue;
|
|
5511
|
+
}
|
|
5512
|
+
skipped += 1;
|
|
4997
5513
|
continue;
|
|
4998
5514
|
}
|
|
4999
5515
|
if (obj.type === "event_msg") {
|
|
5000
5516
|
const m = obj;
|
|
5001
5517
|
const ts = m.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
5002
5518
|
const payload = m.payload;
|
|
5003
|
-
if (!payload
|
|
5519
|
+
if (!payload?.type) {
|
|
5004
5520
|
skipped += 1;
|
|
5005
5521
|
continue;
|
|
5006
5522
|
}
|
|
@@ -5037,11 +5553,12 @@ async function parseCodexRollout(ctx) {
|
|
|
5037
5553
|
reasoning: tk.reasoning_output_tokens ?? 0
|
|
5038
5554
|
},
|
|
5039
5555
|
duration_ms: null,
|
|
5040
|
-
tool_calls:
|
|
5556
|
+
tool_calls: pendingToolAggregate,
|
|
5041
5557
|
files_touched: [],
|
|
5042
5558
|
source_file: ctx.sourceFile,
|
|
5043
5559
|
source_byte_offset: offsetAtLineStart
|
|
5044
5560
|
});
|
|
5561
|
+
pendingToolAggregate = {};
|
|
5045
5562
|
turnIndex += 1;
|
|
5046
5563
|
continue;
|
|
5047
5564
|
}
|
|
@@ -5079,16 +5596,39 @@ async function parseCodexRollout(ctx) {
|
|
|
5079
5596
|
if (ctx.onEvents && chunk.length > 0) await ctx.onEvents(chunk);
|
|
5080
5597
|
return {
|
|
5081
5598
|
events,
|
|
5599
|
+
toolCalls,
|
|
5082
5600
|
stats: { rawLines, emittedEvents: emitted, skipped },
|
|
5083
5601
|
sourceFile: ctx.sourceFile
|
|
5084
5602
|
};
|
|
5085
5603
|
}
|
|
5604
|
+
var TOOL_CALL_PAYLOAD_TYPES, TOOL_CALL_OUTPUT_PAYLOAD_TYPES, SHELL_TOOL_NAMES2, SHELL_WRAPPER_BINARIES;
|
|
5086
5605
|
var init_codex = __esm({
|
|
5087
5606
|
"../../packages/parsers/src/codex/index.ts"() {
|
|
5088
5607
|
"use strict";
|
|
5089
5608
|
init_src();
|
|
5090
|
-
init_types();
|
|
5091
5609
|
init_git();
|
|
5610
|
+
init_shell_families();
|
|
5611
|
+
init_tool_hash();
|
|
5612
|
+
init_types();
|
|
5613
|
+
TOOL_CALL_PAYLOAD_TYPES = /* @__PURE__ */ new Set([
|
|
5614
|
+
"function_call",
|
|
5615
|
+
"local_shell_call",
|
|
5616
|
+
"custom_tool_call",
|
|
5617
|
+
"mcp_tool_call"
|
|
5618
|
+
]);
|
|
5619
|
+
TOOL_CALL_OUTPUT_PAYLOAD_TYPES = /* @__PURE__ */ new Set([
|
|
5620
|
+
"function_call_output",
|
|
5621
|
+
"local_shell_call_output",
|
|
5622
|
+
"custom_tool_call_output",
|
|
5623
|
+
"mcp_tool_call_output"
|
|
5624
|
+
]);
|
|
5625
|
+
SHELL_TOOL_NAMES2 = /* @__PURE__ */ new Set([
|
|
5626
|
+
"shell",
|
|
5627
|
+
"local_shell_call",
|
|
5628
|
+
"exec_command",
|
|
5629
|
+
"run_terminal_cmd"
|
|
5630
|
+
]);
|
|
5631
|
+
SHELL_WRAPPER_BINARIES = /* @__PURE__ */ new Set(["bash", "sh", "zsh", "dash", "fish"]);
|
|
5092
5632
|
}
|
|
5093
5633
|
});
|
|
5094
5634
|
|
|
@@ -44392,6 +44932,16 @@ var init_ids2 = __esm({
|
|
|
44392
44932
|
});
|
|
44393
44933
|
|
|
44394
44934
|
// ../../packages/companion-core/src/queue/index.ts
|
|
44935
|
+
function attachSegmentIds(calls, segments) {
|
|
44936
|
+
const segmentByEvent = /* @__PURE__ */ new Map();
|
|
44937
|
+
for (const seg of segments) {
|
|
44938
|
+
for (const id of seg.source_event_ids) segmentByEvent.set(id, seg.segment_id);
|
|
44939
|
+
}
|
|
44940
|
+
return calls.map((c) => ({
|
|
44941
|
+
...c,
|
|
44942
|
+
segment_id: segmentByEvent.get(c.source_event_id) ?? null
|
|
44943
|
+
}));
|
|
44944
|
+
}
|
|
44395
44945
|
var init_queue = __esm({
|
|
44396
44946
|
"../../packages/companion-core/src/queue/index.ts"() {
|
|
44397
44947
|
"use strict";
|
|
@@ -44400,21 +44950,6 @@ var init_queue = __esm({
|
|
|
44400
44950
|
}
|
|
44401
44951
|
});
|
|
44402
44952
|
|
|
44403
|
-
// ../../packages/companion-core/src/pipeline/prompts.ts
|
|
44404
|
-
var OLLAMA_CHAT_MODEL, OLLAMA_EMBED_MODEL, SUMMARISER_SYSTEM_PROMPT, SUMMARISER_MAX_TOKENS, SUMMARISER_TEMPERATURE, QWEN_CHARS_PER_TOKEN, ABSTRACT_OUTPUT_MAX_CHARS;
|
|
44405
|
-
var init_prompts = __esm({
|
|
44406
|
-
"../../packages/companion-core/src/pipeline/prompts.ts"() {
|
|
44407
|
-
"use strict";
|
|
44408
|
-
OLLAMA_CHAT_MODEL = "qwen3:4b";
|
|
44409
|
-
OLLAMA_EMBED_MODEL = "bge-small-en-v1.5";
|
|
44410
|
-
SUMMARISER_SYSTEM_PROMPT = "You summarise an AI coding session in ONE sentence, \u2264 240 characters. If the user message includes sampled conversation excerpts, base your summary on what the developer was actually working on (the substance \u2014 what was being built, debugged, refactored, or designed). If only metadata is given, paraphrase the metadata. Never quote the excerpts verbatim. No PII, no code literals, no file paths, no API keys. Reply with only the sentence.";
|
|
44411
|
-
SUMMARISER_MAX_TOKENS = 120;
|
|
44412
|
-
SUMMARISER_TEMPERATURE = 0.2;
|
|
44413
|
-
QWEN_CHARS_PER_TOKEN = 3.3;
|
|
44414
|
-
ABSTRACT_OUTPUT_MAX_CHARS = 240;
|
|
44415
|
-
}
|
|
44416
|
-
});
|
|
44417
|
-
|
|
44418
44953
|
// ../../packages/companion-core/src/pipeline/cognition.ts
|
|
44419
44954
|
function buildCognitionUserPrompt(abstract) {
|
|
44420
44955
|
return `Summary: "${abstract.replace(/\s+/g, " ").trim().slice(0, 480)}"
|
|
@@ -44497,6 +45032,21 @@ var init_cognition = __esm({
|
|
|
44497
45032
|
}
|
|
44498
45033
|
});
|
|
44499
45034
|
|
|
45035
|
+
// ../../packages/companion-core/src/pipeline/prompts.ts
|
|
45036
|
+
var OLLAMA_CHAT_MODEL, OLLAMA_EMBED_MODEL, SUMMARISER_SYSTEM_PROMPT, SUMMARISER_MAX_TOKENS, SUMMARISER_TEMPERATURE, QWEN_CHARS_PER_TOKEN, ABSTRACT_OUTPUT_MAX_CHARS;
|
|
45037
|
+
var init_prompts = __esm({
|
|
45038
|
+
"../../packages/companion-core/src/pipeline/prompts.ts"() {
|
|
45039
|
+
"use strict";
|
|
45040
|
+
OLLAMA_CHAT_MODEL = "qwen3:4b";
|
|
45041
|
+
OLLAMA_EMBED_MODEL = "bge-small-en-v1.5";
|
|
45042
|
+
SUMMARISER_SYSTEM_PROMPT = "You summarise an AI coding session in ONE sentence, \u2264 240 characters. If the user message includes sampled conversation excerpts, base your summary on what the developer was actually working on (the substance \u2014 what was being built, debugged, refactored, or designed). If only metadata is given, paraphrase the metadata. Never quote the excerpts verbatim. No PII, no code literals, no file paths, no API keys. Reply with only the sentence.";
|
|
45043
|
+
SUMMARISER_MAX_TOKENS = 120;
|
|
45044
|
+
SUMMARISER_TEMPERATURE = 0.2;
|
|
45045
|
+
QWEN_CHARS_PER_TOKEN = 3.3;
|
|
45046
|
+
ABSTRACT_OUTPUT_MAX_CHARS = 240;
|
|
45047
|
+
}
|
|
45048
|
+
});
|
|
45049
|
+
|
|
44500
45050
|
// ../../packages/companion-core/src/pipeline/title.ts
|
|
44501
45051
|
function buildTitleUserPrompt(input) {
|
|
44502
45052
|
const lines = input.abstracts.map(
|
|
@@ -44674,9 +45224,7 @@ async function buildForOneSession(sessionId, events, adapters2, onSlice) {
|
|
|
44674
45224
|
} catch (err) {
|
|
44675
45225
|
failed += 1;
|
|
44676
45226
|
lastError = err instanceof Error ? err.message : String(err);
|
|
44677
|
-
console.warn(
|
|
44678
|
-
`[modelstat] slice failed in session ${sessionId}: ${lastError}`
|
|
44679
|
-
);
|
|
45227
|
+
console.warn(`[modelstat] slice failed in session ${sessionId}: ${lastError}`);
|
|
44680
45228
|
}
|
|
44681
45229
|
}
|
|
44682
45230
|
if (failed > 0) {
|
|
@@ -44781,6 +45329,24 @@ Write the SHORTEST keyword-dense paragraph (1-3 sentences, \u2264${ABSTRACT_OUTP
|
|
|
44781
45329
|
for (const c of [...components].slice(0, 8)) {
|
|
44782
45330
|
tags.push({ root_key: "components", name: c, confidence: 0.6 });
|
|
44783
45331
|
}
|
|
45332
|
+
const toolCallCounts = /* @__PURE__ */ new Map();
|
|
45333
|
+
let toolCallTotal = 0;
|
|
45334
|
+
for (const ev of slice) {
|
|
45335
|
+
for (const [identity, n] of Object.entries(ev.tool_calls ?? {})) {
|
|
45336
|
+
if (!(n > 0)) continue;
|
|
45337
|
+
toolCallCounts.set(identity, (toolCallCounts.get(identity) ?? 0) + n);
|
|
45338
|
+
toolCallTotal += n;
|
|
45339
|
+
}
|
|
45340
|
+
}
|
|
45341
|
+
const topToolCalls = [...toolCallCounts.entries()].filter(([identity]) => identity.length <= 120).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, 8);
|
|
45342
|
+
for (const [identity, count] of topToolCalls) {
|
|
45343
|
+
const share = Math.round(count / toolCallTotal * 100) / 100;
|
|
45344
|
+
tags.push({
|
|
45345
|
+
root_key: "tool_calls",
|
|
45346
|
+
name: identity,
|
|
45347
|
+
confidence: Math.min(1, Math.max(0.05, share))
|
|
45348
|
+
});
|
|
45349
|
+
}
|
|
44784
45350
|
let segmentEmbedding;
|
|
44785
45351
|
try {
|
|
44786
45352
|
const embedded = await adapters2.embed(redacted.text.slice(0, ABSTRACT_MAX_CHARS));
|
|
@@ -44868,13 +45434,13 @@ var SEGMENT_TIME_GAP_MS, SEGMENT_TOPIC_THRESHOLD, SEGMENT_MAX_TURNS, SEGMENT_MAX
|
|
|
44868
45434
|
var init_pipeline = __esm({
|
|
44869
45435
|
"../../packages/companion-core/src/pipeline/index.ts"() {
|
|
44870
45436
|
"use strict";
|
|
44871
|
-
init_redact();
|
|
44872
45437
|
init_ids();
|
|
44873
|
-
init_prompts();
|
|
44874
|
-
init_cognition();
|
|
44875
45438
|
init_redact();
|
|
45439
|
+
init_cognition();
|
|
44876
45440
|
init_prompts();
|
|
45441
|
+
init_redact();
|
|
44877
45442
|
init_cognition();
|
|
45443
|
+
init_prompts();
|
|
44878
45444
|
init_title();
|
|
44879
45445
|
SEGMENT_TIME_GAP_MS = 15 * 6e4;
|
|
44880
45446
|
SEGMENT_TOPIC_THRESHOLD = 0.35;
|
|
@@ -45698,7 +46264,8 @@ async function scanAll(cb = {}) {
|
|
|
45698
46264
|
jobs.push({
|
|
45699
46265
|
path: full,
|
|
45700
46266
|
parse: async (sink2) => {
|
|
45701
|
-
await parseClaudeCodeJsonl({ deviceId, sourceFile: full, onEvents: sink2 });
|
|
46267
|
+
const r = await parseClaudeCodeJsonl({ deviceId, sourceFile: full, onEvents: sink2 });
|
|
46268
|
+
return { toolCalls: r.toolCalls ?? [] };
|
|
45702
46269
|
}
|
|
45703
46270
|
});
|
|
45704
46271
|
}
|
|
@@ -45721,7 +46288,8 @@ async function scanAll(cb = {}) {
|
|
|
45721
46288
|
jobs.push({
|
|
45722
46289
|
path: full,
|
|
45723
46290
|
parse: async (sink2) => {
|
|
45724
|
-
await parseCodexRollout({ deviceId, sourceFile: full, onEvents: sink2 });
|
|
46291
|
+
const r = await parseCodexRollout({ deviceId, sourceFile: full, onEvents: sink2 });
|
|
46292
|
+
return { toolCalls: r.toolCalls ?? [] };
|
|
45725
46293
|
}
|
|
45726
46294
|
});
|
|
45727
46295
|
}
|
|
@@ -45737,10 +46305,11 @@ async function scanAll(cb = {}) {
|
|
|
45737
46305
|
let eventsUploaded = 0;
|
|
45738
46306
|
let segmentsUploaded = 0;
|
|
45739
46307
|
let buffer = [];
|
|
46308
|
+
let toolCallBuffer = [];
|
|
45740
46309
|
let pendingCursors = [];
|
|
45741
46310
|
const runSegmentsBySession = /* @__PURE__ */ new Map();
|
|
45742
46311
|
async function flushBatch() {
|
|
45743
|
-
if (!buffer.length) return;
|
|
46312
|
+
if (!buffer.length && !toolCallBuffer.length) return;
|
|
45744
46313
|
const events = buffer.map(withNonNullTokens);
|
|
45745
46314
|
const segments = await buildSegments(events, cb.onProgress);
|
|
45746
46315
|
for (const seg of segments) {
|
|
@@ -45764,6 +46333,10 @@ async function scanAll(cb = {}) {
|
|
|
45764
46333
|
agent_version: AGENT_VERSION,
|
|
45765
46334
|
events,
|
|
45766
46335
|
segments,
|
|
46336
|
+
// Per-call tool invocations: now that segments exist, attribute
|
|
46337
|
+
// each call to the segment covering its source event (null when
|
|
46338
|
+
// no segment covers it — e.g. codex response_item anchors).
|
|
46339
|
+
tool_calls: attachSegmentIds(toolCallBuffer, segments),
|
|
45767
46340
|
...Object.keys(sessionTitles).length ? { session_titles: sessionTitles } : {}
|
|
45768
46341
|
};
|
|
45769
46342
|
cb.onUpload?.({ events: events.length, segments: segments.length });
|
|
@@ -45774,6 +46347,7 @@ async function scanAll(cb = {}) {
|
|
|
45774
46347
|
for (const pc of pendingCursors) state.setCursor(pc.path, pc.cs);
|
|
45775
46348
|
pendingCursors = [];
|
|
45776
46349
|
buffer = [];
|
|
46350
|
+
toolCallBuffer = [];
|
|
45777
46351
|
cb.onUploaded?.({ events: res.accepted, segments: segments.length });
|
|
45778
46352
|
}
|
|
45779
46353
|
const sink = async (events) => {
|
|
@@ -45787,6 +46361,12 @@ async function scanAll(cb = {}) {
|
|
|
45787
46361
|
);
|
|
45788
46362
|
}
|
|
45789
46363
|
};
|
|
46364
|
+
const bufferToolCalls = async (calls) => {
|
|
46365
|
+
for (const c of calls) {
|
|
46366
|
+
if (toolCallBuffer.length >= BATCH_MAX_TOOL_CALLS) await flushBatch();
|
|
46367
|
+
toolCallBuffer.push(c);
|
|
46368
|
+
}
|
|
46369
|
+
};
|
|
45790
46370
|
for (let i = 0; i < jobs.length; i++) {
|
|
45791
46371
|
const job = jobs[i];
|
|
45792
46372
|
cb.onFile?.(job.path, i, jobs.length);
|
|
@@ -45798,7 +46378,8 @@ async function scanAll(cb = {}) {
|
|
|
45798
46378
|
}
|
|
45799
46379
|
filesScanned += 1;
|
|
45800
46380
|
try {
|
|
45801
|
-
await job.parse(sink);
|
|
46381
|
+
const r = await job.parse(sink);
|
|
46382
|
+
await bufferToolCalls(r.toolCalls);
|
|
45802
46383
|
if (cs) pendingCursors.push({ path: job.path, cs });
|
|
45803
46384
|
} catch (e) {
|
|
45804
46385
|
console.warn(` ! parse failed for ${job.path}:`, e.message);
|
|
@@ -45807,17 +46388,19 @@ async function scanAll(cb = {}) {
|
|
|
45807
46388
|
await flushBatch();
|
|
45808
46389
|
return { filesScanned, filesUnchanged, batchesUploaded, eventsUploaded, segmentsUploaded };
|
|
45809
46390
|
}
|
|
45810
|
-
var AGENT_VERSION, BATCH_MAX_EVENTS, BATCH_BUFFER_HARD_CAP, ZERO_TOKENS;
|
|
46391
|
+
var AGENT_VERSION, BATCH_MAX_EVENTS, BATCH_MAX_TOOL_CALLS, BATCH_BUFFER_HARD_CAP, ZERO_TOKENS;
|
|
45811
46392
|
var init_scan = __esm({
|
|
45812
46393
|
"src/scan.ts"() {
|
|
45813
46394
|
"use strict";
|
|
45814
|
-
init_src2();
|
|
45815
46395
|
init_src3();
|
|
45816
|
-
|
|
45817
|
-
|
|
46396
|
+
init_queue();
|
|
46397
|
+
init_src2();
|
|
45818
46398
|
init_api();
|
|
45819
|
-
|
|
46399
|
+
init_config2();
|
|
46400
|
+
init_pipeline2();
|
|
46401
|
+
AGENT_VERSION = true ? "agent-0.0.47" : "agent-dev";
|
|
45820
46402
|
BATCH_MAX_EVENTS = 2e3;
|
|
46403
|
+
BATCH_MAX_TOOL_CALLS = 2e4;
|
|
45821
46404
|
BATCH_BUFFER_HARD_CAP = BATCH_MAX_EVENTS * 2;
|
|
45822
46405
|
ZERO_TOKENS = {
|
|
45823
46406
|
input: 0,
|
|
@@ -46028,7 +46611,7 @@ var PROCESSING_VERSION;
|
|
|
46028
46611
|
var init_processing_version = __esm({
|
|
46029
46612
|
"src/processing-version.ts"() {
|
|
46030
46613
|
"use strict";
|
|
46031
|
-
PROCESSING_VERSION =
|
|
46614
|
+
PROCESSING_VERSION = 5;
|
|
46032
46615
|
}
|
|
46033
46616
|
});
|
|
46034
46617
|
|
|
@@ -48075,7 +48658,7 @@ var init_daemon = __esm({
|
|
|
48075
48658
|
init_lock();
|
|
48076
48659
|
init_scan();
|
|
48077
48660
|
init_single_flight();
|
|
48078
|
-
AGENT_VERSION2 = true ? "agent-0.0.
|
|
48661
|
+
AGENT_VERSION2 = true ? "agent-0.0.47" : "agent-dev";
|
|
48079
48662
|
HEARTBEAT_INTERVAL_MS = 1e4;
|
|
48080
48663
|
SCAN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
48081
48664
|
DISCOVERY_INTERVAL_MS = 6e4;
|
|
@@ -48640,7 +49223,7 @@ function tryOpenBrowser(url) {
|
|
|
48640
49223
|
return false;
|
|
48641
49224
|
}
|
|
48642
49225
|
}
|
|
48643
|
-
var AGENT_VERSION3 = true ? "agent-0.0.
|
|
49226
|
+
var AGENT_VERSION3 = true ? "agent-0.0.47" : "agent-dev";
|
|
48644
49227
|
function osFamily() {
|
|
48645
49228
|
const p = platform4();
|
|
48646
49229
|
if (p === "darwin") return "macos";
|