repoburg 1.3.273 → 1.3.275
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/agent-pane/backend/dist/index.js +424 -79
- package/agent-pane/backend/dist/server.js +424 -79
- package/agent-pane/frontend/dist/assets/{index-DlwZnsU3.css → index-BKDM-AC5.css} +1 -1
- package/agent-pane/frontend/dist/assets/index-BNyA-dQb.js +617 -0
- package/agent-pane/frontend/dist/index.html +2 -2
- package/backend/dist/src/core-entities/llm-call-log.entity.d.ts +2 -0
- package/backend/dist/src/core-entities/llm-call-log.entity.js +11 -0
- package/backend/dist/src/core-entities/llm-call-log.entity.js.map +1 -1
- package/backend/dist/src/llm-call-logs/dto/llm-call-log.dto.d.ts +2 -0
- package/backend/dist/src/llm-call-logs/dto/llm-call-log.dto.js +6 -0
- package/backend/dist/src/llm-call-logs/dto/llm-call-log.dto.js.map +1 -1
- package/backend/dist/src/llm-call-logs/llm-call-logs.module.js +2 -1
- package/backend/dist/src/llm-call-logs/llm-call-logs.module.js.map +1 -1
- package/backend/dist/src/llm-call-logs/llm-call-logs.service.d.ts +3 -1
- package/backend/dist/src/llm-call-logs/llm-call-logs.service.js +8 -2
- package/backend/dist/src/llm-call-logs/llm-call-logs.service.js.map +1 -1
- package/backend/dist/src/llm-provider/alibaba-llm.provider.js +1 -0
- package/backend/dist/src/llm-provider/alibaba-llm.provider.js.map +1 -1
- package/backend/dist/src/llm-provider/ollama-llm.provider.js +1 -0
- package/backend/dist/src/llm-provider/ollama-llm.provider.js.map +1 -1
- package/backend/dist/src/llm-provider/openai-llm.provider.js +1 -0
- package/backend/dist/src/llm-provider/openai-llm.provider.js.map +1 -1
- package/backend/dist/src/llm-provider/openrouter-llm.provider.js +1 -0
- package/backend/dist/src/llm-provider/openrouter-llm.provider.js.map +1 -1
- package/backend/dist/src/llm-provider/zai-llm.provider.js +1 -0
- package/backend/dist/src/llm-provider/zai-llm.provider.js.map +1 -1
- package/backend/dist/src/usage-export/usage-export.module.d.ts +2 -0
- package/backend/dist/src/usage-export/usage-export.module.js +21 -0
- package/backend/dist/src/usage-export/usage-export.module.js.map +1 -0
- package/backend/dist/src/usage-export/usage-export.service.d.ts +6 -0
- package/backend/dist/src/usage-export/usage-export.service.js +54 -0
- package/backend/dist/src/usage-export/usage-export.service.js.map +1 -0
- package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
- package/daemon/dist/workspace-validation.js +11 -2
- package/daemon/dist/workspace-validation.spec.js +8 -2
- package/package.json +1 -1
- package/tabtape/extension/dist/build-info.json +3 -3
- package/tabtape/extension/dist/manifest.json +1 -1
- package/tabtape/ui/dist/build-info.json +3 -3
- package/agent-pane/frontend/dist/assets/index-WRsdlJfD.js +0 -606
|
@@ -7850,7 +7850,7 @@ var require_thread_stream = __commonJS({
|
|
|
7850
7850
|
var { version } = require_package();
|
|
7851
7851
|
var { EventEmitter: EventEmitter2 } = __require("events");
|
|
7852
7852
|
var { Worker } = __require("worker_threads");
|
|
7853
|
-
var { join:
|
|
7853
|
+
var { join: join5 } = __require("path");
|
|
7854
7854
|
var { pathToFileURL } = __require("url");
|
|
7855
7855
|
var { wait } = require_wait();
|
|
7856
7856
|
var {
|
|
@@ -7901,7 +7901,7 @@ var require_thread_stream = __commonJS({
|
|
|
7901
7901
|
function createWorker(stream, opts) {
|
|
7902
7902
|
const { filename, workerData } = opts;
|
|
7903
7903
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
7904
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
7904
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join5(__dirname, "lib", "worker.js");
|
|
7905
7905
|
const worker = new Worker(toExecute, {
|
|
7906
7906
|
...opts.workerOpts,
|
|
7907
7907
|
name: opts.workerOpts?.name || "thread-stream",
|
|
@@ -8369,7 +8369,7 @@ var require_transport = __commonJS({
|
|
|
8369
8369
|
var { createRequire } = __require("module");
|
|
8370
8370
|
var { existsSync: existsSync3 } = __require("node:fs");
|
|
8371
8371
|
var getCallers = require_caller();
|
|
8372
|
-
var { join:
|
|
8372
|
+
var { join: join5, isAbsolute, sep } = __require("node:path");
|
|
8373
8373
|
var { fileURLToPath: fileURLToPath3 } = __require("node:url");
|
|
8374
8374
|
var sleep = require_atomic_sleep();
|
|
8375
8375
|
var onExit = require_on_exit_leak_free();
|
|
@@ -8522,7 +8522,7 @@ var require_transport = __commonJS({
|
|
|
8522
8522
|
throw new Error("only one of target or targets can be specified");
|
|
8523
8523
|
}
|
|
8524
8524
|
if (targets) {
|
|
8525
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
8525
|
+
target = bundlerOverrides["pino-worker"] || join5(__dirname, "worker.js");
|
|
8526
8526
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
8527
8527
|
return {
|
|
8528
8528
|
...dest,
|
|
@@ -8540,7 +8540,7 @@ var require_transport = __commonJS({
|
|
|
8540
8540
|
});
|
|
8541
8541
|
});
|
|
8542
8542
|
} else if (pipeline) {
|
|
8543
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
8543
|
+
target = bundlerOverrides["pino-worker"] || join5(__dirname, "worker.js");
|
|
8544
8544
|
options.pipelines = [pipeline.map((dest) => {
|
|
8545
8545
|
return {
|
|
8546
8546
|
...dest,
|
|
@@ -8563,7 +8563,7 @@ var require_transport = __commonJS({
|
|
|
8563
8563
|
return origin;
|
|
8564
8564
|
}
|
|
8565
8565
|
if (origin === "pino/file") {
|
|
8566
|
-
return
|
|
8566
|
+
return join5(__dirname, "..", "file.js");
|
|
8567
8567
|
}
|
|
8568
8568
|
let fixTarget2;
|
|
8569
8569
|
for (const filePath of callers) {
|
|
@@ -8678,14 +8678,14 @@ var require_tools = __commonJS({
|
|
|
8678
8678
|
}
|
|
8679
8679
|
return point < 32 ? JSON.stringify(str) : '"' + result + '"';
|
|
8680
8680
|
}
|
|
8681
|
-
function asJson(obj, msg,
|
|
8681
|
+
function asJson(obj, msg, num2, time) {
|
|
8682
8682
|
if (asJsonChan.hasSubscribers === false) {
|
|
8683
|
-
return _asJson.call(this, obj, msg,
|
|
8683
|
+
return _asJson.call(this, obj, msg, num2, time);
|
|
8684
8684
|
}
|
|
8685
8685
|
const store = { instance: this, arguments };
|
|
8686
|
-
return asJsonChan.traceSync(_asJson, store, this, obj, msg,
|
|
8686
|
+
return asJsonChan.traceSync(_asJson, store, this, obj, msg, num2, time);
|
|
8687
8687
|
}
|
|
8688
|
-
function _asJson(obj, msg,
|
|
8688
|
+
function _asJson(obj, msg, num2, time) {
|
|
8689
8689
|
const stringify2 = this[stringifySym];
|
|
8690
8690
|
const stringifySafe = this[stringifySafeSym];
|
|
8691
8691
|
const stringifiers = this[stringifiersSym];
|
|
@@ -8695,7 +8695,7 @@ var require_tools = __commonJS({
|
|
|
8695
8695
|
const formatters = this[formattersSym];
|
|
8696
8696
|
const messageKey = this[messageKeySym];
|
|
8697
8697
|
const errorKey = this[errorKeySym];
|
|
8698
|
-
let data = this[lsCacheSym][
|
|
8698
|
+
let data = this[lsCacheSym][num2] + time;
|
|
8699
8699
|
data = data + chindings;
|
|
8700
8700
|
let value;
|
|
8701
8701
|
if (formatters.log) {
|
|
@@ -9320,7 +9320,7 @@ var require_proto = __commonJS({
|
|
|
9320
9320
|
function defaultMixinMergeStrategy(mergeObject, mixinObject) {
|
|
9321
9321
|
return Object.assign(mixinObject, mergeObject);
|
|
9322
9322
|
}
|
|
9323
|
-
function write(_obj, msg,
|
|
9323
|
+
function write(_obj, msg, num2) {
|
|
9324
9324
|
const t = this[timeSym]();
|
|
9325
9325
|
const mixin = this[mixinSym];
|
|
9326
9326
|
const errorKey = this[errorKeySym];
|
|
@@ -9342,12 +9342,12 @@ var require_proto = __commonJS({
|
|
|
9342
9342
|
}
|
|
9343
9343
|
}
|
|
9344
9344
|
if (mixin) {
|
|
9345
|
-
obj = mixinMergeStrategy(obj, mixin(obj,
|
|
9345
|
+
obj = mixinMergeStrategy(obj, mixin(obj, num2, this));
|
|
9346
9346
|
}
|
|
9347
|
-
const s = this[asJsonSym](obj, msg,
|
|
9347
|
+
const s = this[asJsonSym](obj, msg, num2, t);
|
|
9348
9348
|
const stream = this[streamSym];
|
|
9349
9349
|
if (stream[needsMetadataGsym] === true) {
|
|
9350
|
-
stream.lastLevel =
|
|
9350
|
+
stream.lastLevel = num2;
|
|
9351
9351
|
stream.lastObj = obj;
|
|
9352
9352
|
stream.lastMsg = msg;
|
|
9353
9353
|
stream.lastTime = t.slice(this[timeSliceIndexSym]);
|
|
@@ -9543,7 +9543,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
9543
9543
|
return circularValue;
|
|
9544
9544
|
}
|
|
9545
9545
|
let res = "";
|
|
9546
|
-
let
|
|
9546
|
+
let join5 = ",";
|
|
9547
9547
|
const originalIndentation = indentation;
|
|
9548
9548
|
if (Array.isArray(value)) {
|
|
9549
9549
|
if (value.length === 0) {
|
|
@@ -9557,7 +9557,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
9557
9557
|
indentation += spacer;
|
|
9558
9558
|
res += `
|
|
9559
9559
|
${indentation}`;
|
|
9560
|
-
|
|
9560
|
+
join5 = `,
|
|
9561
9561
|
${indentation}`;
|
|
9562
9562
|
}
|
|
9563
9563
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -9565,13 +9565,13 @@ ${indentation}`;
|
|
|
9565
9565
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
9566
9566
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
9567
9567
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
9568
|
-
res +=
|
|
9568
|
+
res += join5;
|
|
9569
9569
|
}
|
|
9570
9570
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
9571
9571
|
res += tmp !== void 0 ? tmp : "null";
|
|
9572
9572
|
if (value.length - 1 > maximumBreadth) {
|
|
9573
9573
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
9574
|
-
res += `${
|
|
9574
|
+
res += `${join5}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
9575
9575
|
}
|
|
9576
9576
|
if (spacer !== "") {
|
|
9577
9577
|
res += `
|
|
@@ -9592,7 +9592,7 @@ ${originalIndentation}`;
|
|
|
9592
9592
|
let separator = "";
|
|
9593
9593
|
if (spacer !== "") {
|
|
9594
9594
|
indentation += spacer;
|
|
9595
|
-
|
|
9595
|
+
join5 = `,
|
|
9596
9596
|
${indentation}`;
|
|
9597
9597
|
whitespace = " ";
|
|
9598
9598
|
}
|
|
@@ -9606,13 +9606,13 @@ ${indentation}`;
|
|
|
9606
9606
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
9607
9607
|
if (tmp !== void 0) {
|
|
9608
9608
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
9609
|
-
separator =
|
|
9609
|
+
separator = join5;
|
|
9610
9610
|
}
|
|
9611
9611
|
}
|
|
9612
9612
|
if (keyLength > maximumBreadth) {
|
|
9613
9613
|
const removedKeys = keyLength - maximumBreadth;
|
|
9614
9614
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
9615
|
-
separator =
|
|
9615
|
+
separator = join5;
|
|
9616
9616
|
}
|
|
9617
9617
|
if (spacer !== "" && separator.length > 1) {
|
|
9618
9618
|
res = `
|
|
@@ -9653,7 +9653,7 @@ ${originalIndentation}`;
|
|
|
9653
9653
|
}
|
|
9654
9654
|
const originalIndentation = indentation;
|
|
9655
9655
|
let res = "";
|
|
9656
|
-
let
|
|
9656
|
+
let join5 = ",";
|
|
9657
9657
|
if (Array.isArray(value)) {
|
|
9658
9658
|
if (value.length === 0) {
|
|
9659
9659
|
return "[]";
|
|
@@ -9666,7 +9666,7 @@ ${originalIndentation}`;
|
|
|
9666
9666
|
indentation += spacer;
|
|
9667
9667
|
res += `
|
|
9668
9668
|
${indentation}`;
|
|
9669
|
-
|
|
9669
|
+
join5 = `,
|
|
9670
9670
|
${indentation}`;
|
|
9671
9671
|
}
|
|
9672
9672
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -9674,13 +9674,13 @@ ${indentation}`;
|
|
|
9674
9674
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
9675
9675
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
9676
9676
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
9677
|
-
res +=
|
|
9677
|
+
res += join5;
|
|
9678
9678
|
}
|
|
9679
9679
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
9680
9680
|
res += tmp !== void 0 ? tmp : "null";
|
|
9681
9681
|
if (value.length - 1 > maximumBreadth) {
|
|
9682
9682
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
9683
|
-
res += `${
|
|
9683
|
+
res += `${join5}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
9684
9684
|
}
|
|
9685
9685
|
if (spacer !== "") {
|
|
9686
9686
|
res += `
|
|
@@ -9693,7 +9693,7 @@ ${originalIndentation}`;
|
|
|
9693
9693
|
let whitespace = "";
|
|
9694
9694
|
if (spacer !== "") {
|
|
9695
9695
|
indentation += spacer;
|
|
9696
|
-
|
|
9696
|
+
join5 = `,
|
|
9697
9697
|
${indentation}`;
|
|
9698
9698
|
whitespace = " ";
|
|
9699
9699
|
}
|
|
@@ -9702,7 +9702,7 @@ ${indentation}`;
|
|
|
9702
9702
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
9703
9703
|
if (tmp !== void 0) {
|
|
9704
9704
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
9705
|
-
separator =
|
|
9705
|
+
separator = join5;
|
|
9706
9706
|
}
|
|
9707
9707
|
}
|
|
9708
9708
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -9760,20 +9760,20 @@ ${originalIndentation}`;
|
|
|
9760
9760
|
indentation += spacer;
|
|
9761
9761
|
let res2 = `
|
|
9762
9762
|
${indentation}`;
|
|
9763
|
-
const
|
|
9763
|
+
const join6 = `,
|
|
9764
9764
|
${indentation}`;
|
|
9765
9765
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
9766
9766
|
let i = 0;
|
|
9767
9767
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
9768
9768
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
9769
9769
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
9770
|
-
res2 +=
|
|
9770
|
+
res2 += join6;
|
|
9771
9771
|
}
|
|
9772
9772
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
9773
9773
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
9774
9774
|
if (value.length - 1 > maximumBreadth) {
|
|
9775
9775
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
9776
|
-
res2 += `${
|
|
9776
|
+
res2 += `${join6}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
9777
9777
|
}
|
|
9778
9778
|
res2 += `
|
|
9779
9779
|
${originalIndentation}`;
|
|
@@ -9789,16 +9789,16 @@ ${originalIndentation}`;
|
|
|
9789
9789
|
return '"[Object]"';
|
|
9790
9790
|
}
|
|
9791
9791
|
indentation += spacer;
|
|
9792
|
-
const
|
|
9792
|
+
const join5 = `,
|
|
9793
9793
|
${indentation}`;
|
|
9794
9794
|
let res = "";
|
|
9795
9795
|
let separator = "";
|
|
9796
9796
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
9797
9797
|
if (isTypedArrayWithEntries(value)) {
|
|
9798
|
-
res += stringifyTypedArray(value,
|
|
9798
|
+
res += stringifyTypedArray(value, join5, maximumBreadth);
|
|
9799
9799
|
keys = keys.slice(value.length);
|
|
9800
9800
|
maximumPropertiesToStringify -= value.length;
|
|
9801
|
-
separator =
|
|
9801
|
+
separator = join5;
|
|
9802
9802
|
}
|
|
9803
9803
|
if (deterministic) {
|
|
9804
9804
|
keys = sort(keys, comparator);
|
|
@@ -9809,13 +9809,13 @@ ${indentation}`;
|
|
|
9809
9809
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
9810
9810
|
if (tmp !== void 0) {
|
|
9811
9811
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
9812
|
-
separator =
|
|
9812
|
+
separator = join5;
|
|
9813
9813
|
}
|
|
9814
9814
|
}
|
|
9815
9815
|
if (keyLength > maximumBreadth) {
|
|
9816
9816
|
const removedKeys = keyLength - maximumBreadth;
|
|
9817
9817
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
9818
|
-
separator =
|
|
9818
|
+
separator = join5;
|
|
9819
9819
|
}
|
|
9820
9820
|
if (separator !== "") {
|
|
9821
9821
|
res = `
|
|
@@ -10709,13 +10709,13 @@ var require_serializer = __commonJS({
|
|
|
10709
10709
|
return "" + integer;
|
|
10710
10710
|
}
|
|
10711
10711
|
asNumber(i) {
|
|
10712
|
-
const
|
|
10713
|
-
if (
|
|
10712
|
+
const num2 = Number(i);
|
|
10713
|
+
if (num2 !== num2) {
|
|
10714
10714
|
throw new Error(`The value "${i}" cannot be converted to a number.`);
|
|
10715
|
-
} else if (
|
|
10715
|
+
} else if (num2 === Infinity || num2 === -Infinity) {
|
|
10716
10716
|
return "null";
|
|
10717
10717
|
} else {
|
|
10718
|
-
return "" +
|
|
10718
|
+
return "" + num2;
|
|
10719
10719
|
}
|
|
10720
10720
|
}
|
|
10721
10721
|
asBoolean(bool) {
|
|
@@ -28126,9 +28126,9 @@ var require_semver = __commonJS({
|
|
|
28126
28126
|
} else {
|
|
28127
28127
|
this.prerelease = m[4].split(".").map((id) => {
|
|
28128
28128
|
if (/^[0-9]+$/.test(id)) {
|
|
28129
|
-
const
|
|
28130
|
-
if (
|
|
28131
|
-
return
|
|
28129
|
+
const num2 = +id;
|
|
28130
|
+
if (num2 >= 0 && num2 < MAX_SAFE_INTEGER) {
|
|
28131
|
+
return num2;
|
|
28132
28132
|
}
|
|
28133
28133
|
}
|
|
28134
28134
|
return id;
|
|
@@ -37665,26 +37665,26 @@ var require_permessage_deflate = __commonJS({
|
|
|
37665
37665
|
value = value[0];
|
|
37666
37666
|
if (key === "client_max_window_bits") {
|
|
37667
37667
|
if (value !== true) {
|
|
37668
|
-
const
|
|
37669
|
-
if (!Number.isInteger(
|
|
37668
|
+
const num2 = +value;
|
|
37669
|
+
if (!Number.isInteger(num2) || num2 < 8 || num2 > 15) {
|
|
37670
37670
|
throw new TypeError(
|
|
37671
37671
|
`Invalid value for parameter "${key}": ${value}`
|
|
37672
37672
|
);
|
|
37673
37673
|
}
|
|
37674
|
-
value =
|
|
37674
|
+
value = num2;
|
|
37675
37675
|
} else if (!this._isServer) {
|
|
37676
37676
|
throw new TypeError(
|
|
37677
37677
|
`Invalid value for parameter "${key}": ${value}`
|
|
37678
37678
|
);
|
|
37679
37679
|
}
|
|
37680
37680
|
} else if (key === "server_max_window_bits") {
|
|
37681
|
-
const
|
|
37682
|
-
if (!Number.isInteger(
|
|
37681
|
+
const num2 = +value;
|
|
37682
|
+
if (!Number.isInteger(num2) || num2 < 8 || num2 > 15) {
|
|
37683
37683
|
throw new TypeError(
|
|
37684
37684
|
`Invalid value for parameter "${key}": ${value}`
|
|
37685
37685
|
);
|
|
37686
37686
|
}
|
|
37687
|
-
value =
|
|
37687
|
+
value = num2;
|
|
37688
37688
|
} else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") {
|
|
37689
37689
|
if (value !== true) {
|
|
37690
37690
|
throw new TypeError(
|
|
@@ -38398,8 +38398,8 @@ var require_receiver = __commonJS({
|
|
|
38398
38398
|
return;
|
|
38399
38399
|
}
|
|
38400
38400
|
const buf = this.consume(8);
|
|
38401
|
-
const
|
|
38402
|
-
if (
|
|
38401
|
+
const num2 = buf.readUInt32BE(0);
|
|
38402
|
+
if (num2 > Math.pow(2, 53 - 32) - 1) {
|
|
38403
38403
|
const error = this.createError(
|
|
38404
38404
|
RangeError,
|
|
38405
38405
|
"Unsupported WebSocket frame: payload length > 2^53 - 1",
|
|
@@ -38410,7 +38410,7 @@ var require_receiver = __commonJS({
|
|
|
38410
38410
|
cb(error);
|
|
38411
38411
|
return;
|
|
38412
38412
|
}
|
|
38413
|
-
this._payloadLength =
|
|
38413
|
+
this._payloadLength = num2 * Math.pow(2, 32) + buf.readUInt32BE(4);
|
|
38414
38414
|
this.haveLength(cb);
|
|
38415
38415
|
}
|
|
38416
38416
|
/**
|
|
@@ -41330,6 +41330,25 @@ function v4(options, buf, offset) {
|
|
|
41330
41330
|
}
|
|
41331
41331
|
var v4_default = v4;
|
|
41332
41332
|
|
|
41333
|
+
// src/db/item-trim.ts
|
|
41334
|
+
var TRIMMABLE_KEYS = ["aggregated_output", "output"];
|
|
41335
|
+
var MAX_ITEM_TEXT_BYTES = 64e3;
|
|
41336
|
+
function prunedMarker(maxBytes) {
|
|
41337
|
+
return `\u2026 [pruned: kept newest ${maxBytes} bytes]
|
|
41338
|
+
`;
|
|
41339
|
+
}
|
|
41340
|
+
function trimItemData(data, maxBytes = MAX_ITEM_TEXT_BYTES) {
|
|
41341
|
+
let trimmed = null;
|
|
41342
|
+
for (const key of TRIMMABLE_KEYS) {
|
|
41343
|
+
const value = data[key];
|
|
41344
|
+
if (typeof value === "string" && value.length > maxBytes) {
|
|
41345
|
+
if (!trimmed) trimmed = { ...data };
|
|
41346
|
+
trimmed[key] = prunedMarker(maxBytes) + value.slice(-maxBytes);
|
|
41347
|
+
}
|
|
41348
|
+
}
|
|
41349
|
+
return trimmed ?? data;
|
|
41350
|
+
}
|
|
41351
|
+
|
|
41333
41352
|
// src/providers/registry.ts
|
|
41334
41353
|
var providers = /* @__PURE__ */ new Map();
|
|
41335
41354
|
function registerProvider(id, provider) {
|
|
@@ -41390,7 +41409,7 @@ async function registerSessionRoutes(fastify) {
|
|
|
41390
41409
|
for (const row of itemRows) {
|
|
41391
41410
|
const item = {
|
|
41392
41411
|
...row,
|
|
41393
|
-
data: row.data ? JSON.parse(row.data) : null
|
|
41412
|
+
data: row.data ? trimItemData(JSON.parse(row.data)) : null
|
|
41394
41413
|
};
|
|
41395
41414
|
const list = itemsByTurn.get(item.turn_id) ?? [];
|
|
41396
41415
|
list.push(item);
|
|
@@ -43415,7 +43434,6 @@ async function registerPerfLogRoutes(fastify) {
|
|
|
43415
43434
|
}
|
|
43416
43435
|
|
|
43417
43436
|
// src/routes/maintenance.ts
|
|
43418
|
-
var TRIMMABLE_KEYS = ["aggregated_output", "output"];
|
|
43419
43437
|
async function registerMaintenanceRoutes(fastify) {
|
|
43420
43438
|
fastify.post(
|
|
43421
43439
|
"/api/maintenance/prune-items",
|
|
@@ -43448,17 +43466,9 @@ async function registerMaintenanceRoutes(fastify) {
|
|
|
43448
43466
|
} catch {
|
|
43449
43467
|
continue;
|
|
43450
43468
|
}
|
|
43451
|
-
|
|
43452
|
-
|
|
43453
|
-
|
|
43454
|
-
if (typeof v === "string" && v.length > maxBytes) {
|
|
43455
|
-
data[key] = `\u2026 [pruned: kept newest ${maxBytes} bytes]
|
|
43456
|
-
` + v.slice(-maxBytes);
|
|
43457
|
-
changed = true;
|
|
43458
|
-
}
|
|
43459
|
-
}
|
|
43460
|
-
if (!changed) continue;
|
|
43461
|
-
const next = JSON.stringify(data);
|
|
43469
|
+
const trimmed = trimItemData(data, maxBytes);
|
|
43470
|
+
if (trimmed === data) continue;
|
|
43471
|
+
const next = JSON.stringify(trimmed);
|
|
43462
43472
|
bytesBefore += row.data.length;
|
|
43463
43473
|
bytesAfter += next.length;
|
|
43464
43474
|
pruned++;
|
|
@@ -98306,6 +98316,7 @@ Icons come from ONE library: Lucide (https://lucide.dev/icons, ISC).
|
|
|
98306
98316
|
- createSession({ cwd, runtime_type, model, model_reasoning_effort, title }) - agent session owned by this app; model_reasoning_effort is the effort for its turns ("low" | "medium" | "high" | "xhigh" | "max" | "ultra", the levels the model supports), omitted = the runtime's default
|
|
98307
98317
|
- submitTurn(sessionId, prompt, { attachments }?) - send a prompt to a session; attachments (optional) are stored files (id, url or the uploadFile result) or inline Blobs / { name, type, data } sent with that turn only; the agent sees attached images (Claude and Codex)
|
|
98308
98318
|
- onTurnCompleted(callback) - callback(event, { turnId, response }) when a turn ends
|
|
98319
|
+
- onBackgroundTasks(callback) - callback({ sessionId, tasks }) when the live background-task set of one of the app's sessions changes (Monitor shells, backgrounded subagents); tasks is the CURRENT set, empty when none are left
|
|
98309
98320
|
- onToolCall(callback) - callback({ callId, name, tool, args }) when the AGENT calls one of the manifest tools (name and tool carry the same tool name); answer with resolveToolCall(callId, result)
|
|
98310
98321
|
- openSession(sessionId) - show that session in the pane (the view switches to its conversation); works only while the app is on screen, so call it from a click handler
|
|
98311
98322
|
- openUrl(url) - open an absolute http(s) URL in a new browser tab; call it from a click handler (popup blockers allow tabs opened by a click)
|
|
@@ -98590,6 +98601,10 @@ interface AgentPaneCreateSessionOptions {
|
|
|
98590
98601
|
interface AgentPaneTurnPayload { turnId?: string; response?: string | null; error?: string }
|
|
98591
98602
|
interface AgentPaneDeltaPayload { sessionId?: string; turnId?: string; itemId?: string; delta?: string }
|
|
98592
98603
|
interface AgentPaneToolCallPayload { callId: string; tool: string; name: string; args: Record<string, unknown> }
|
|
98604
|
+
/** Live background tasks of a session (Monitor shells, backgrounded subagents):
|
|
98605
|
+
* the CURRENT set, REPLACE semantics \u2014 an empty array means none are left. */
|
|
98606
|
+
interface AgentPaneBackgroundTasksPayload { sessionId?: string; tasks?: AgentPaneBackgroundTask[] }
|
|
98607
|
+
interface AgentPaneBackgroundTask { task_id: string; task_type: string; description: string }
|
|
98593
98608
|
/** A file the app stored with uploadFile (PNG, JPEG, GIF or WebP, max 5 MB). */
|
|
98594
98609
|
interface AgentPaneFile {
|
|
98595
98610
|
/** Content id "<sha256>.<ext>": the same bytes always get the same id. */
|
|
@@ -98627,6 +98642,9 @@ declare const AgentPane: {
|
|
|
98627
98642
|
onTurnDelta(cb: (payload: AgentPaneDeltaPayload) => void): void;
|
|
98628
98643
|
onToolCall(cb: (payload: AgentPaneToolCallPayload) => void): void;
|
|
98629
98644
|
onStateChanged(cb: (payload: unknown) => void): void;
|
|
98645
|
+
/** Fires when the live background-task set of one of the app's sessions
|
|
98646
|
+
* changes (also empty sets, when the last task ends). */
|
|
98647
|
+
onBackgroundTasks(cb: (payload: AgentPaneBackgroundTasksPayload | null) => void): void;
|
|
98630
98648
|
resolveToolCall(callId: string, result?: unknown): Promise<{ ok: boolean }>;
|
|
98631
98649
|
/** Show a session in the pane (switches the view to its conversation).
|
|
98632
98650
|
* Only works while the app is on screen: call it from a click handler. */
|
|
@@ -99075,6 +99093,8 @@ function getHeadlessToolHandler(appId, workspace = "") {
|
|
|
99075
99093
|
onTurnCompleted: () => {
|
|
99076
99094
|
},
|
|
99077
99095
|
onTurnDelta: () => {
|
|
99096
|
+
},
|
|
99097
|
+
onBackgroundTasks: () => {
|
|
99078
99098
|
}
|
|
99079
99099
|
};
|
|
99080
99100
|
const sandbox = {
|
|
@@ -99585,7 +99605,8 @@ async function registerAppRoutes(fastify, opts) {
|
|
|
99585
99605
|
if (!APP_ID_RE.test(id)) return reply.code(400).send({ error: "Invalid app id" });
|
|
99586
99606
|
if (!readManifest(id)) return reply.code(404).send({ error: "App not found" });
|
|
99587
99607
|
const rows = getDb().prepare("SELECT * FROM sessions WHERE origin_app_id = ? ORDER BY created_at DESC").all(id);
|
|
99588
|
-
|
|
99608
|
+
const tasks = listAllBackgroundTasks();
|
|
99609
|
+
return rows.map((row) => ({ ...row, background_tasks: tasks[row.id] ?? [] }));
|
|
99589
99610
|
});
|
|
99590
99611
|
fastify.post(
|
|
99591
99612
|
"/api/apps/:id/edit-session",
|
|
@@ -99761,6 +99782,329 @@ async function registerSidecarRoutes(fastify) {
|
|
|
99761
99782
|
);
|
|
99762
99783
|
}
|
|
99763
99784
|
|
|
99785
|
+
// src/usage/usage-service.ts
|
|
99786
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
99787
|
+
import { homedir as homedir3 } from "node:os";
|
|
99788
|
+
import { join as join3 } from "node:path";
|
|
99789
|
+
|
|
99790
|
+
// src/usage/usage-pricing.ts
|
|
99791
|
+
var PRICES = {
|
|
99792
|
+
// --- Z.AI GLM (cache writes are currently listed free) ---
|
|
99793
|
+
"glm-5.3-flashx": { input: 0.37, cachedInput: 0.075, cacheWrite: 0, output: 1.25 },
|
|
99794
|
+
"glm-5.3-flash": { input: 0.15, cachedInput: 0.03, cacheWrite: 0, output: 0.5 },
|
|
99795
|
+
"glm-5.3": { input: 1.4, cachedInput: 0.26, cacheWrite: 0, output: 4.4 },
|
|
99796
|
+
"glm-5.2": { input: 1.4, cachedInput: 0.26, cacheWrite: 0, output: 4.4 },
|
|
99797
|
+
"glm-5.1": { input: 1.4, cachedInput: 0.26, cacheWrite: 0, output: 4.4 },
|
|
99798
|
+
"glm-5": { input: 1, cachedInput: 0.2, cacheWrite: 0, output: 3.2 },
|
|
99799
|
+
"glm-4.7-flashx": { input: 0.07, cachedInput: 0.01, cacheWrite: 0, output: 0.4 },
|
|
99800
|
+
"glm-4.7": { input: 0.6, cachedInput: 0.11, cacheWrite: 0, output: 2.2 },
|
|
99801
|
+
"glm-4.6": { input: 0.6, cachedInput: 0.11, cacheWrite: 0, output: 2.2 },
|
|
99802
|
+
"glm-4.5-air": { input: 0.2, cachedInput: 0.03, cacheWrite: 0, output: 1.1 },
|
|
99803
|
+
"glm-4.5": { input: 0.6, cachedInput: 0.11, cacheWrite: 0, output: 2.2 },
|
|
99804
|
+
// --- OpenAI (no separate cache-write price; cached input only) ---
|
|
99805
|
+
"gpt-5.2-codex": { input: 1.75, cachedInput: 0.175, cacheWrite: 1.75, output: 14 },
|
|
99806
|
+
"gpt-5.3-codex": { input: 1.75, cachedInput: 0.175, cacheWrite: 1.75, output: 14 },
|
|
99807
|
+
"gpt-5.1-codex": { input: 1.25, cachedInput: 0.125, cacheWrite: 1.25, output: 10 },
|
|
99808
|
+
"gpt-5.2": { input: 1.75, cachedInput: 0.175, cacheWrite: 1.75, output: 14 },
|
|
99809
|
+
"gpt-5.1": { input: 1.25, cachedInput: 0.125, cacheWrite: 1.25, output: 10 },
|
|
99810
|
+
"gpt-5-mini": { input: 0.25, cachedInput: 0.025, cacheWrite: 0.25, output: 2 },
|
|
99811
|
+
"gpt-5-nano": { input: 0.05, cachedInput: 5e-3, cacheWrite: 0.05, output: 0.4 },
|
|
99812
|
+
"gpt-5": { input: 1.25, cachedInput: 0.125, cacheWrite: 1.25, output: 10 },
|
|
99813
|
+
"gpt-4.1-mini": { input: 0.4, cachedInput: 0.1, cacheWrite: 0.4, output: 1.6 },
|
|
99814
|
+
"gpt-4.1": { input: 2, cachedInput: 0.5, cacheWrite: 2, output: 8 },
|
|
99815
|
+
"gpt-4o-mini": { input: 0.15, cachedInput: 0.075, cacheWrite: 0.15, output: 0.6 },
|
|
99816
|
+
"gpt-4o": { input: 2.5, cachedInput: 1.25, cacheWrite: 2.5, output: 10 },
|
|
99817
|
+
// --- Anthropic Claude (5m cache writes; reads at 0.1x base) ---
|
|
99818
|
+
"claude-opus-5-5": { input: 4, cachedInput: 0.2, cacheWrite: 5, output: 20 },
|
|
99819
|
+
"claude-opus-4-5": { input: 5, cachedInput: 0.5, cacheWrite: 6.25, output: 25 },
|
|
99820
|
+
"claude-opus-4": { input: 15, cachedInput: 1.5, cacheWrite: 18.75, output: 75 },
|
|
99821
|
+
"claude-sonnet-5-5": { input: 2, cachedInput: 0.1, cacheWrite: 2.5, output: 10 },
|
|
99822
|
+
"claude-sonnet-5": { input: 2, cachedInput: 0.2, cacheWrite: 2.5, output: 10 },
|
|
99823
|
+
"claude-sonnet-4-5": { input: 3, cachedInput: 0.3, cacheWrite: 3.75, output: 15 },
|
|
99824
|
+
"claude-sonnet-4": { input: 3, cachedInput: 0.3, cacheWrite: 3.75, output: 15 },
|
|
99825
|
+
"claude-haiku-5-5": { input: 0.1, cachedInput: 0.01, cacheWrite: 0.125, output: 0.5 },
|
|
99826
|
+
"claude-haiku-4-5": { input: 1, cachedInput: 0.1, cacheWrite: 1.25, output: 5 }
|
|
99827
|
+
};
|
|
99828
|
+
var SORTED_KEYS = Object.keys(PRICES).sort((a, b) => b.length - a.length);
|
|
99829
|
+
function normalizeModelId(modelId) {
|
|
99830
|
+
const lastSegment = modelId.toLowerCase().split("/").pop() ?? "";
|
|
99831
|
+
const withoutTag = lastSegment.split(":")[0];
|
|
99832
|
+
return withoutTag.replace(/-(\d{8}|\d{4}-\d{2}-\d{2})$/, "");
|
|
99833
|
+
}
|
|
99834
|
+
function findModelPricing(modelId) {
|
|
99835
|
+
const normalized = normalizeModelId(modelId);
|
|
99836
|
+
for (const key of SORTED_KEYS) {
|
|
99837
|
+
if (normalized === key || normalized.startsWith(`${key}-`)) return PRICES[key];
|
|
99838
|
+
}
|
|
99839
|
+
return null;
|
|
99840
|
+
}
|
|
99841
|
+
function computeCost(modelId, usage, inputIncludesCached) {
|
|
99842
|
+
const pricing = findModelPricing(modelId);
|
|
99843
|
+
if (!pricing) return null;
|
|
99844
|
+
const m = 1e6;
|
|
99845
|
+
const { inputTokens, cachedInputTokens, cacheWriteInputTokens, outputTokens } = usage;
|
|
99846
|
+
const uncached = inputIncludesCached ? Math.max(0, inputTokens - cachedInputTokens - cacheWriteInputTokens) : inputTokens;
|
|
99847
|
+
return (uncached * pricing.input + cachedInputTokens * pricing.cachedInput + cacheWriteInputTokens * pricing.cacheWrite + outputTokens * pricing.output) / m;
|
|
99848
|
+
}
|
|
99849
|
+
|
|
99850
|
+
// src/usage/usage-service.ts
|
|
99851
|
+
function usageFilesDir() {
|
|
99852
|
+
return process.env.AGENT_PANE_USAGE_DIR ?? join3(homedir3(), ".repoburg", "usage");
|
|
99853
|
+
}
|
|
99854
|
+
function emptyBucket() {
|
|
99855
|
+
return { calls: 0, errors: 0, input: 0, cached: 0, cacheWrite: 0, output: 0, cost: 0 };
|
|
99856
|
+
}
|
|
99857
|
+
function newAggregator() {
|
|
99858
|
+
return {
|
|
99859
|
+
totals: emptyBucket(),
|
|
99860
|
+
unpricedModels: /* @__PURE__ */ new Set(),
|
|
99861
|
+
byRuntime: /* @__PURE__ */ new Map(),
|
|
99862
|
+
byModel: /* @__PURE__ */ new Map(),
|
|
99863
|
+
byDay: /* @__PURE__ */ new Map()
|
|
99864
|
+
};
|
|
99865
|
+
}
|
|
99866
|
+
var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
99867
|
+
function addEvent(agg, event) {
|
|
99868
|
+
const { runtimeType, provider, model, effort, day, isError, usage, inputIncludesCached } = event;
|
|
99869
|
+
const cost = usage ? computeCost(model, usage, inputIncludesCached) : null;
|
|
99870
|
+
if (usage && cost === null) agg.unpricedModels.add(model);
|
|
99871
|
+
const bump = (b) => {
|
|
99872
|
+
b.calls += 1;
|
|
99873
|
+
if (isError) b.errors += 1;
|
|
99874
|
+
if (usage) {
|
|
99875
|
+
b.input += usage.inputTokens;
|
|
99876
|
+
b.cached += usage.cachedInputTokens;
|
|
99877
|
+
b.cacheWrite += usage.cacheWriteInputTokens;
|
|
99878
|
+
b.output += usage.outputTokens;
|
|
99879
|
+
b.cost += cost ?? 0;
|
|
99880
|
+
}
|
|
99881
|
+
};
|
|
99882
|
+
bump(agg.totals);
|
|
99883
|
+
const runtimeBucket = agg.byRuntime.get(runtimeType) ?? emptyBucket();
|
|
99884
|
+
bump(runtimeBucket);
|
|
99885
|
+
agg.byRuntime.set(runtimeType, runtimeBucket);
|
|
99886
|
+
const dayBucket = agg.byDay.get(day) ?? emptyBucket();
|
|
99887
|
+
bump(dayBucket);
|
|
99888
|
+
agg.byDay.set(day, dayBucket);
|
|
99889
|
+
const key = `${runtimeType}|${provider ?? ""}|${model}|${effort ?? ""}`;
|
|
99890
|
+
const row = agg.byModel.get(key);
|
|
99891
|
+
if (row) {
|
|
99892
|
+
row.calls += 1;
|
|
99893
|
+
if (isError) row.errors += 1;
|
|
99894
|
+
if (usage) {
|
|
99895
|
+
row.input_tokens += usage.inputTokens;
|
|
99896
|
+
row.cached_input_tokens += usage.cachedInputTokens;
|
|
99897
|
+
row.cache_write_input_tokens += usage.cacheWriteInputTokens;
|
|
99898
|
+
row.output_tokens += usage.outputTokens;
|
|
99899
|
+
if (cost !== null) row.cost_usd = (row.cost_usd ?? 0) + cost;
|
|
99900
|
+
}
|
|
99901
|
+
} else {
|
|
99902
|
+
agg.byModel.set(key, {
|
|
99903
|
+
runtime_type: runtimeType,
|
|
99904
|
+
provider,
|
|
99905
|
+
model,
|
|
99906
|
+
reasoning_effort: effort,
|
|
99907
|
+
calls: 1,
|
|
99908
|
+
errors: isError ? 1 : 0,
|
|
99909
|
+
input_tokens: usage?.inputTokens ?? 0,
|
|
99910
|
+
cached_input_tokens: usage?.cachedInputTokens ?? 0,
|
|
99911
|
+
cache_write_input_tokens: usage?.cacheWriteInputTokens ?? 0,
|
|
99912
|
+
output_tokens: usage?.outputTokens ?? 0,
|
|
99913
|
+
cost_usd: cost,
|
|
99914
|
+
priced: cost !== null
|
|
99915
|
+
});
|
|
99916
|
+
}
|
|
99917
|
+
}
|
|
99918
|
+
function parseTokenUsage(raw) {
|
|
99919
|
+
if (!raw) return null;
|
|
99920
|
+
try {
|
|
99921
|
+
const parsed = JSON.parse(raw);
|
|
99922
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
99923
|
+
return {
|
|
99924
|
+
inputTokens: num(parsed.input_tokens),
|
|
99925
|
+
cachedInputTokens: num(parsed.cached_input_tokens),
|
|
99926
|
+
cacheWriteInputTokens: num(parsed.cache_write_input_tokens),
|
|
99927
|
+
outputTokens: num(parsed.output_tokens)
|
|
99928
|
+
};
|
|
99929
|
+
} catch {
|
|
99930
|
+
return null;
|
|
99931
|
+
}
|
|
99932
|
+
}
|
|
99933
|
+
function addPaneTurns(agg, sinceIso, untilIso) {
|
|
99934
|
+
const params = [];
|
|
99935
|
+
let where = "s.runtime_type IN ('claude','codex') AND t.status IN ('completed','failed','aborted')";
|
|
99936
|
+
if (sinceIso) {
|
|
99937
|
+
params.push(sinceIso);
|
|
99938
|
+
where += " AND t.created_at >= ?";
|
|
99939
|
+
}
|
|
99940
|
+
if (untilIso) {
|
|
99941
|
+
params.push(untilIso);
|
|
99942
|
+
where += " AND t.created_at < ?";
|
|
99943
|
+
}
|
|
99944
|
+
const rows = getDb().prepare(
|
|
99945
|
+
`SELECT s.runtime_type, s.model, s.model_reasoning_effort, t.token_usage, t.status, t.created_at
|
|
99946
|
+
FROM turns t JOIN sessions s ON s.id = t.session_id WHERE ${where}`
|
|
99947
|
+
).all(...params);
|
|
99948
|
+
for (const row of rows) {
|
|
99949
|
+
const day = row.created_at.slice(0, 10);
|
|
99950
|
+
addEvent(agg, {
|
|
99951
|
+
runtimeType: row.runtime_type,
|
|
99952
|
+
provider: null,
|
|
99953
|
+
model: row.model ?? "(default)",
|
|
99954
|
+
effort: row.model_reasoning_effort ?? null,
|
|
99955
|
+
day,
|
|
99956
|
+
isError: row.status === "failed",
|
|
99957
|
+
usage: parseTokenUsage(row.token_usage),
|
|
99958
|
+
// Anthropic reports input/cache-read/cache-write as disjoint buckets.
|
|
99959
|
+
inputIncludesCached: row.runtime_type !== "claude"
|
|
99960
|
+
});
|
|
99961
|
+
}
|
|
99962
|
+
}
|
|
99963
|
+
function addRepoburgExport(agg, sinceIso, untilIso) {
|
|
99964
|
+
let files;
|
|
99965
|
+
try {
|
|
99966
|
+
files = readdirSync2(usageFilesDir()).filter((f) => /^usage-\d{4}-\d{2}-\d{2}\.jsonl$/.test(f)).sort();
|
|
99967
|
+
} catch {
|
|
99968
|
+
return;
|
|
99969
|
+
}
|
|
99970
|
+
const sinceDay = sinceIso?.slice(0, 10) ?? null;
|
|
99971
|
+
const untilDay = untilIso ? untilIso.slice(0, 10) : null;
|
|
99972
|
+
for (const file of files) {
|
|
99973
|
+
const day = file.slice("usage-".length, file.length - ".jsonl".length);
|
|
99974
|
+
if (sinceDay && day < sinceDay) continue;
|
|
99975
|
+
if (untilDay && day > untilDay) continue;
|
|
99976
|
+
let content;
|
|
99977
|
+
try {
|
|
99978
|
+
content = readFileSync2(join3(usageFilesDir(), file), "utf-8");
|
|
99979
|
+
} catch {
|
|
99980
|
+
continue;
|
|
99981
|
+
}
|
|
99982
|
+
for (const line of content.split("\n")) {
|
|
99983
|
+
const trimmed = line.trim();
|
|
99984
|
+
if (!trimmed) continue;
|
|
99985
|
+
let record;
|
|
99986
|
+
try {
|
|
99987
|
+
record = JSON.parse(trimmed);
|
|
99988
|
+
} catch {
|
|
99989
|
+
continue;
|
|
99990
|
+
}
|
|
99991
|
+
if (sinceIso && record.ts < sinceIso) continue;
|
|
99992
|
+
if (untilIso && record.ts >= untilIso) continue;
|
|
99993
|
+
const status = record.status_code;
|
|
99994
|
+
addEvent(agg, {
|
|
99995
|
+
runtimeType: "repoburg",
|
|
99996
|
+
provider: record.provider ?? null,
|
|
99997
|
+
model: record.model_id ?? "(unknown)",
|
|
99998
|
+
effort: record.reasoning_effort ?? null,
|
|
99999
|
+
day: record.ts.slice(0, 10),
|
|
100000
|
+
isError: status === null || status < 200 || status >= 300,
|
|
100001
|
+
usage: {
|
|
100002
|
+
inputTokens: num(record.input_tokens),
|
|
100003
|
+
cachedInputTokens: num(record.cached_tokens),
|
|
100004
|
+
cacheWriteInputTokens: 0,
|
|
100005
|
+
outputTokens: num(record.output_tokens)
|
|
100006
|
+
},
|
|
100007
|
+
// OpenAI-compatible providers report cached tokens inside input.
|
|
100008
|
+
inputIncludesCached: true
|
|
100009
|
+
});
|
|
100010
|
+
}
|
|
100011
|
+
}
|
|
100012
|
+
}
|
|
100013
|
+
function getUsageSummary(sinceIso, untilIso) {
|
|
100014
|
+
const agg = newAggregator();
|
|
100015
|
+
addPaneTurns(agg, sinceIso, untilIso);
|
|
100016
|
+
addRepoburgExport(agg, sinceIso, untilIso);
|
|
100017
|
+
const byRuntime = [...agg.byRuntime.entries()].map(([runtimeType, b]) => ({
|
|
100018
|
+
runtime_type: runtimeType,
|
|
100019
|
+
calls: b.calls,
|
|
100020
|
+
errors: b.errors,
|
|
100021
|
+
input_tokens: b.input,
|
|
100022
|
+
cached_input_tokens: b.cached,
|
|
100023
|
+
cache_write_input_tokens: b.cacheWrite,
|
|
100024
|
+
output_tokens: b.output,
|
|
100025
|
+
cost_usd: b.cost
|
|
100026
|
+
})).sort((a, b) => a.runtime_type.localeCompare(b.runtime_type));
|
|
100027
|
+
const byModel = [...agg.byModel.values()].map((row) => ({
|
|
100028
|
+
runtime_type: row.runtime_type,
|
|
100029
|
+
provider: row.provider,
|
|
100030
|
+
model: row.model,
|
|
100031
|
+
reasoning_effort: row.reasoning_effort,
|
|
100032
|
+
calls: row.calls,
|
|
100033
|
+
errors: row.errors,
|
|
100034
|
+
input_tokens: row.input_tokens,
|
|
100035
|
+
cached_input_tokens: row.cached_input_tokens,
|
|
100036
|
+
cache_write_input_tokens: row.cache_write_input_tokens,
|
|
100037
|
+
output_tokens: row.output_tokens,
|
|
100038
|
+
// Unpriced models stay null; a priced row that also saw zero-token
|
|
100039
|
+
// error events keeps its exact sum.
|
|
100040
|
+
cost_usd: row.priced ? row.cost_usd ?? 0 : null
|
|
100041
|
+
})).sort((a, b) => (b.cost_usd ?? 0) - (a.cost_usd ?? 0) || b.calls - a.calls);
|
|
100042
|
+
const daily = [...agg.byDay.entries()].map(([date, b]) => ({
|
|
100043
|
+
date,
|
|
100044
|
+
calls: b.calls,
|
|
100045
|
+
input_tokens: b.input,
|
|
100046
|
+
cached_input_tokens: b.cached,
|
|
100047
|
+
cache_write_input_tokens: b.cacheWrite,
|
|
100048
|
+
output_tokens: b.output,
|
|
100049
|
+
cost_usd: b.cost
|
|
100050
|
+
})).sort((a, b) => a.date.localeCompare(b.date));
|
|
100051
|
+
return {
|
|
100052
|
+
window: { since: sinceIso, until: untilIso },
|
|
100053
|
+
totals: {
|
|
100054
|
+
calls: agg.totals.calls,
|
|
100055
|
+
errors: agg.totals.errors,
|
|
100056
|
+
input_tokens: agg.totals.input,
|
|
100057
|
+
cached_input_tokens: agg.totals.cached,
|
|
100058
|
+
cache_write_input_tokens: agg.totals.cacheWrite,
|
|
100059
|
+
output_tokens: agg.totals.output,
|
|
100060
|
+
total_tokens: agg.totals.input + agg.totals.cached + agg.totals.cacheWrite + agg.totals.output,
|
|
100061
|
+
cost_usd: agg.totals.cost,
|
|
100062
|
+
unpriced_models: [...agg.unpricedModels].sort()
|
|
100063
|
+
},
|
|
100064
|
+
by_runtime: byRuntime,
|
|
100065
|
+
by_model: byModel,
|
|
100066
|
+
daily
|
|
100067
|
+
};
|
|
100068
|
+
}
|
|
100069
|
+
|
|
100070
|
+
// src/routes/usage.ts
|
|
100071
|
+
function parseTimeParam(value) {
|
|
100072
|
+
if (typeof value !== "string" || value === "") return null;
|
|
100073
|
+
if (Number.isNaN(Date.parse(value))) {
|
|
100074
|
+
throw Object.assign(new Error(`Invalid timestamp: ${value}`), { statusCode: 400 });
|
|
100075
|
+
}
|
|
100076
|
+
return value;
|
|
100077
|
+
}
|
|
100078
|
+
async function registerUsageRoutes(fastify) {
|
|
100079
|
+
fastify.get(
|
|
100080
|
+
"/api/usage/summary",
|
|
100081
|
+
{
|
|
100082
|
+
schema: {
|
|
100083
|
+
querystring: {
|
|
100084
|
+
type: "object",
|
|
100085
|
+
properties: {
|
|
100086
|
+
since: { type: "string" },
|
|
100087
|
+
until: { type: "string" }
|
|
100088
|
+
}
|
|
100089
|
+
}
|
|
100090
|
+
}
|
|
100091
|
+
},
|
|
100092
|
+
async (request, reply) => {
|
|
100093
|
+
try {
|
|
100094
|
+
const since = parseTimeParam(request.query?.since);
|
|
100095
|
+
const until = parseTimeParam(request.query?.until);
|
|
100096
|
+
return getUsageSummary(since, until);
|
|
100097
|
+
} catch (err) {
|
|
100098
|
+
const e = err;
|
|
100099
|
+
if (e.statusCode === 400) {
|
|
100100
|
+
return reply.code(400).send({ error: e.message });
|
|
100101
|
+
}
|
|
100102
|
+
throw err;
|
|
100103
|
+
}
|
|
100104
|
+
}
|
|
100105
|
+
);
|
|
100106
|
+
}
|
|
100107
|
+
|
|
99764
100108
|
// src/codex/item-mapper.ts
|
|
99765
100109
|
function mapItemData(item) {
|
|
99766
100110
|
switch (item.type) {
|
|
@@ -100525,9 +100869,9 @@ var codexProvider = {
|
|
|
100525
100869
|
|
|
100526
100870
|
// src/claude/claude-provider.ts
|
|
100527
100871
|
import { query, forkSession as sdkForkSession } from "@anthropic-ai/claude-agent-sdk";
|
|
100528
|
-
import { readFileSync as
|
|
100872
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
100529
100873
|
import { tmpdir } from "os";
|
|
100530
|
-
import { join as
|
|
100874
|
+
import { join as join4 } from "path";
|
|
100531
100875
|
|
|
100532
100876
|
// src/claude/claude-message-mapper.ts
|
|
100533
100877
|
function mapAssistantContent(content, messageId, thinkingTexts) {
|
|
@@ -101047,7 +101391,8 @@ function handleLoopError(entry, sessionId, errMsg, db2) {
|
|
|
101047
101391
|
turn_id: row.turn_id,
|
|
101048
101392
|
external_item_id: row.external_item_id,
|
|
101049
101393
|
type: row.type,
|
|
101050
|
-
|
|
101394
|
+
// MUH-25 — re-broadcasts ship trimmed payloads too.
|
|
101395
|
+
data: row.data ? trimItemData(JSON.parse(row.data)) : {},
|
|
101051
101396
|
status: "failed",
|
|
101052
101397
|
created_at: row.created_at,
|
|
101053
101398
|
updated_at: now
|
|
@@ -101468,7 +101813,7 @@ function constructMonitorOutputPath(entry, taskId) {
|
|
|
101468
101813
|
if (!entry.sessionId) return "";
|
|
101469
101814
|
const uid = typeof process.getuid === "function" ? process.getuid() : 0;
|
|
101470
101815
|
const encodedCwd = entry.cwd.replace(/\//g, "-");
|
|
101471
|
-
return
|
|
101816
|
+
return join4(tmpdir(), `claude-${uid}`, encodedCwd, entry.sessionId, "tasks", `${taskId}.output`);
|
|
101472
101817
|
}
|
|
101473
101818
|
function handleTaskStarted(message, sessionId, turnId, entry, db2) {
|
|
101474
101819
|
const m = message;
|
|
@@ -101511,7 +101856,7 @@ function handleTaskProgress(message, sessionId, turnId, entry, db2) {
|
|
|
101511
101856
|
const outputPath = existing.output_file || constructMonitorOutputPath(entry, m.task_id);
|
|
101512
101857
|
if (outputPath) {
|
|
101513
101858
|
try {
|
|
101514
|
-
output =
|
|
101859
|
+
output = readFileSync3(outputPath, "utf-8");
|
|
101515
101860
|
} catch {
|
|
101516
101861
|
}
|
|
101517
101862
|
}
|
|
@@ -101560,13 +101905,11 @@ function handleTaskNotification(message, sessionId, turnId, entry, db2) {
|
|
|
101560
101905
|
if (!row) return;
|
|
101561
101906
|
const existing = row.data ? JSON.parse(row.data) : {};
|
|
101562
101907
|
const taskType = existing.task_type ?? "unknown";
|
|
101563
|
-
const
|
|
101564
|
-
const constructedPath = taskType === "local_bash" ? constructMonitorOutputPath(entry, m.task_id) : "";
|
|
101565
|
-
const outputPath = sdkOutputFile || constructedPath;
|
|
101908
|
+
const outputPath = taskType === "local_bash" ? m.output_file || constructMonitorOutputPath(entry, m.task_id) : null;
|
|
101566
101909
|
let output = "";
|
|
101567
101910
|
if (outputPath) {
|
|
101568
101911
|
try {
|
|
101569
|
-
output =
|
|
101912
|
+
output = readFileSync3(outputPath, "utf-8");
|
|
101570
101913
|
} catch {
|
|
101571
101914
|
}
|
|
101572
101915
|
}
|
|
@@ -101574,7 +101917,7 @@ function handleTaskNotification(message, sessionId, turnId, entry, db2) {
|
|
|
101574
101917
|
...existing,
|
|
101575
101918
|
status: m.status,
|
|
101576
101919
|
summary: m.summary,
|
|
101577
|
-
output_file: outputPath,
|
|
101920
|
+
output_file: m.output_file || outputPath || existing.output_file || null,
|
|
101578
101921
|
output,
|
|
101579
101922
|
token_count: m.usage?.total_tokens ?? existing.token_count ?? null
|
|
101580
101923
|
};
|
|
@@ -101645,7 +101988,8 @@ function completeTurn(db2, sessionId, turnId, usage) {
|
|
|
101645
101988
|
}
|
|
101646
101989
|
function upsertItem(db2, desc, sessionId, turnId, status, broadcastEvent) {
|
|
101647
101990
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
101648
|
-
const
|
|
101991
|
+
const data = trimItemData(desc.data);
|
|
101992
|
+
const result = db2.prepare("UPDATE items SET data = ?, status = ?, updated_at = ? WHERE external_item_id = ? AND turn_id = ?").run(JSON.stringify(data), status, now, desc.externalId, turnId);
|
|
101649
101993
|
let itemId;
|
|
101650
101994
|
let createdAt;
|
|
101651
101995
|
if (result.changes === 0) {
|
|
@@ -101653,7 +101997,7 @@ function upsertItem(db2, desc, sessionId, turnId, status, broadcastEvent) {
|
|
|
101653
101997
|
createdAt = now;
|
|
101654
101998
|
db2.prepare(
|
|
101655
101999
|
"INSERT INTO items (id, turn_id, external_item_id, type, data, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
|
101656
|
-
).run(itemId, turnId, desc.externalId, desc.type, JSON.stringify(
|
|
102000
|
+
).run(itemId, turnId, desc.externalId, desc.type, JSON.stringify(data), status, now, now);
|
|
101657
102001
|
} else {
|
|
101658
102002
|
const row = db2.prepare("SELECT id, created_at FROM items WHERE external_item_id = ? AND turn_id = ?").get(desc.externalId, turnId);
|
|
101659
102003
|
itemId = row.id;
|
|
@@ -101664,7 +102008,7 @@ function upsertItem(db2, desc, sessionId, turnId, status, broadcastEvent) {
|
|
|
101664
102008
|
turn_id: turnId,
|
|
101665
102009
|
external_item_id: desc.externalId,
|
|
101666
102010
|
type: desc.type,
|
|
101667
|
-
data
|
|
102011
|
+
data,
|
|
101668
102012
|
status,
|
|
101669
102013
|
created_at: createdAt,
|
|
101670
102014
|
updated_at: now
|
|
@@ -103651,6 +103995,7 @@ async function createAgentPaneApp(dbPath) {
|
|
|
103651
103995
|
await registerVscodeWebRoutes(fastify);
|
|
103652
103996
|
await registerAppRoutes(fastify);
|
|
103653
103997
|
await registerSidecarRoutes(fastify);
|
|
103998
|
+
await registerUsageRoutes(fastify);
|
|
103654
103999
|
const wss2 = initWs();
|
|
103655
104000
|
wss2.on("connection", (ws) => {
|
|
103656
104001
|
ws.send(JSON.stringify({ event: "background_tasks:snapshot", data: { sessions: listAllBackgroundTasks() } }));
|