modelstat 0.7.1 → 0.8.1
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 +341 -69
- package/dist/cli.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -85,10 +85,15 @@ function parseRemote(url) {
|
|
|
85
85
|
return { host: null, slug: null };
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
+
function mainRepoPath(cwd) {
|
|
89
|
+
const i = cwd.indexOf("/.claude/");
|
|
90
|
+
return i === -1 ? cwd : cwd.slice(0, i);
|
|
91
|
+
}
|
|
88
92
|
async function resolveGitContext(cwd) {
|
|
89
93
|
if (!cwd) return null;
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
const target = mainRepoPath(cwd);
|
|
95
|
+
if (cache.has(target)) return cache.get(target) ?? null;
|
|
96
|
+
const root = findRepoRoot(target);
|
|
92
97
|
if (!root) {
|
|
93
98
|
const empty = {
|
|
94
99
|
remote_url: null,
|
|
@@ -97,7 +102,7 @@ async function resolveGitContext(cwd) {
|
|
|
97
102
|
branch: null,
|
|
98
103
|
commit_sha: null
|
|
99
104
|
};
|
|
100
|
-
cache.set(
|
|
105
|
+
cache.set(target, empty);
|
|
101
106
|
return empty;
|
|
102
107
|
}
|
|
103
108
|
const ran = async (args) => {
|
|
@@ -119,7 +124,7 @@ async function resolveGitContext(cwd) {
|
|
|
119
124
|
branch,
|
|
120
125
|
commit_sha: sha
|
|
121
126
|
};
|
|
122
|
-
cache.set(
|
|
127
|
+
cache.set(target, ctx);
|
|
123
128
|
return ctx;
|
|
124
129
|
}
|
|
125
130
|
function guessRepoSlugFromPath(cwd) {
|
|
@@ -16734,7 +16739,7 @@ var require_client_h2 = __commonJS({
|
|
|
16734
16739
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/dispatcher/client-h2.js"(exports, module) {
|
|
16735
16740
|
"use strict";
|
|
16736
16741
|
var assert = __require("assert");
|
|
16737
|
-
var { pipeline } = __require("stream");
|
|
16742
|
+
var { pipeline: pipeline2 } = __require("stream");
|
|
16738
16743
|
var util2 = require_util();
|
|
16739
16744
|
var {
|
|
16740
16745
|
RequestContentLengthMismatchError,
|
|
@@ -17367,7 +17372,7 @@ var require_client_h2 = __commonJS({
|
|
|
17367
17372
|
}
|
|
17368
17373
|
function writeStream(abort, socket, expectsPayload, h2stream, body, client, request3, contentLength) {
|
|
17369
17374
|
assert(contentLength !== 0 || client[kRunning] === 0, "stream body cannot be pipelined");
|
|
17370
|
-
const pipe =
|
|
17375
|
+
const pipe = pipeline2(
|
|
17371
17376
|
body,
|
|
17372
17377
|
h2stream,
|
|
17373
17378
|
(err) => {
|
|
@@ -18074,10 +18079,10 @@ var require_pool_base = __commonJS({
|
|
|
18074
18079
|
[kClients] = [];
|
|
18075
18080
|
[kNeedDrain] = false;
|
|
18076
18081
|
[kOnDrain](client, origin, targets) {
|
|
18077
|
-
const
|
|
18082
|
+
const queue2 = this[kQueue];
|
|
18078
18083
|
let needDrain = false;
|
|
18079
18084
|
while (!needDrain) {
|
|
18080
|
-
const item =
|
|
18085
|
+
const item = queue2.shift();
|
|
18081
18086
|
if (!item) {
|
|
18082
18087
|
break;
|
|
18083
18088
|
}
|
|
@@ -18089,7 +18094,7 @@ var require_pool_base = __commonJS({
|
|
|
18089
18094
|
this[kNeedDrain] = false;
|
|
18090
18095
|
this.emit("drain", origin, [this, ...targets]);
|
|
18091
18096
|
}
|
|
18092
|
-
if (this[kClosedResolve] &&
|
|
18097
|
+
if (this[kClosedResolve] && queue2.isEmpty()) {
|
|
18093
18098
|
const closeAll = [];
|
|
18094
18099
|
for (let i = 0; i < this[kClients].length; i++) {
|
|
18095
18100
|
const client2 = this[kClients][i];
|
|
@@ -21133,7 +21138,7 @@ var require_api_pipeline = __commonJS({
|
|
|
21133
21138
|
util2.destroy(ret, err);
|
|
21134
21139
|
}
|
|
21135
21140
|
};
|
|
21136
|
-
function
|
|
21141
|
+
function pipeline2(opts, handler) {
|
|
21137
21142
|
try {
|
|
21138
21143
|
const pipelineHandler = new PipelineHandler(opts, handler);
|
|
21139
21144
|
this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler);
|
|
@@ -21142,7 +21147,7 @@ var require_api_pipeline = __commonJS({
|
|
|
21142
21147
|
return new PassThrough().destroy(err);
|
|
21143
21148
|
}
|
|
21144
21149
|
}
|
|
21145
|
-
module.exports =
|
|
21150
|
+
module.exports = pipeline2;
|
|
21146
21151
|
}
|
|
21147
21152
|
});
|
|
21148
21153
|
|
|
@@ -22014,13 +22019,13 @@ var require_mock_call_history = __commonJS({
|
|
|
22014
22019
|
"use strict";
|
|
22015
22020
|
var { kMockCallHistoryAddLog } = require_mock_symbols();
|
|
22016
22021
|
var { InvalidArgumentError } = require_errors();
|
|
22017
|
-
function handleFilterCallsWithOptions(criteria, options, handler,
|
|
22022
|
+
function handleFilterCallsWithOptions(criteria, options, handler, store2) {
|
|
22018
22023
|
switch (options.operator) {
|
|
22019
22024
|
case "OR":
|
|
22020
|
-
|
|
22021
|
-
return
|
|
22025
|
+
store2.push(...handler(criteria));
|
|
22026
|
+
return store2;
|
|
22022
22027
|
case "AND":
|
|
22023
|
-
return handler.call({ logs:
|
|
22028
|
+
return handler.call({ logs: store2 }, criteria);
|
|
22024
22029
|
default:
|
|
22025
22030
|
throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'");
|
|
22026
22031
|
}
|
|
@@ -24377,12 +24382,12 @@ var require_cache = __commonJS({
|
|
|
24377
24382
|
}
|
|
24378
24383
|
return false;
|
|
24379
24384
|
}
|
|
24380
|
-
function assertCacheStore(
|
|
24381
|
-
if (typeof
|
|
24382
|
-
throw new TypeError(`expected type of ${name} to be a CacheStore, got ${
|
|
24385
|
+
function assertCacheStore(store2, name = "CacheStore") {
|
|
24386
|
+
if (typeof store2 !== "object" || store2 === null) {
|
|
24387
|
+
throw new TypeError(`expected type of ${name} to be a CacheStore, got ${store2 === null ? "null" : typeof store2}`);
|
|
24383
24388
|
}
|
|
24384
24389
|
for (const fn of ["get", "createWriteStream", "delete"]) {
|
|
24385
|
-
if (typeof
|
|
24390
|
+
if (typeof store2[fn] !== "function") {
|
|
24386
24391
|
throw new TypeError(`${name} needs to have a \`${fn}()\` function`);
|
|
24387
24392
|
}
|
|
24388
24393
|
}
|
|
@@ -24986,8 +24991,8 @@ var require_cache_handler = __commonJS({
|
|
|
24986
24991
|
* @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
|
|
24987
24992
|
* @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
|
|
24988
24993
|
*/
|
|
24989
|
-
constructor({ store, type, cacheByDefault }, cacheKey, handler) {
|
|
24990
|
-
this.#store =
|
|
24994
|
+
constructor({ store: store2, type, cacheByDefault }, cacheKey, handler) {
|
|
24995
|
+
this.#store = store2;
|
|
24991
24996
|
this.#cacheType = type;
|
|
24992
24997
|
this.#cacheByDefault = cacheByDefault;
|
|
24993
24998
|
this.#cacheKey = cacheKey;
|
|
@@ -25396,7 +25401,7 @@ var require_memory_cache_store = __commonJS({
|
|
|
25396
25401
|
assertCacheKey(key);
|
|
25397
25402
|
assertCacheValue(val);
|
|
25398
25403
|
const topLevelKey = `${key.origin}:${key.path}`;
|
|
25399
|
-
const
|
|
25404
|
+
const store2 = this;
|
|
25400
25405
|
const entry = { ...key, ...val, body: [], size: 0 };
|
|
25401
25406
|
return new Writable({
|
|
25402
25407
|
write(chunk, encoding, callback) {
|
|
@@ -25404,7 +25409,7 @@ var require_memory_cache_store = __commonJS({
|
|
|
25404
25409
|
chunk = Buffer.from(chunk, encoding);
|
|
25405
25410
|
}
|
|
25406
25411
|
entry.size += chunk.byteLength;
|
|
25407
|
-
if (entry.size >=
|
|
25412
|
+
if (entry.size >= store2.#maxEntrySize) {
|
|
25408
25413
|
this.destroy();
|
|
25409
25414
|
} else {
|
|
25410
25415
|
entry.body.push(chunk);
|
|
@@ -25412,42 +25417,42 @@ var require_memory_cache_store = __commonJS({
|
|
|
25412
25417
|
callback(null);
|
|
25413
25418
|
},
|
|
25414
25419
|
final(callback) {
|
|
25415
|
-
let entries =
|
|
25420
|
+
let entries = store2.#entries.get(topLevelKey);
|
|
25416
25421
|
if (!entries) {
|
|
25417
25422
|
entries = [];
|
|
25418
|
-
|
|
25423
|
+
store2.#entries.set(topLevelKey, entries);
|
|
25419
25424
|
}
|
|
25420
25425
|
const previousEntry = findEntry(key, entries, Date.now());
|
|
25421
25426
|
if (previousEntry) {
|
|
25422
25427
|
const index = entries.indexOf(previousEntry);
|
|
25423
25428
|
entries.splice(index, 1, entry);
|
|
25424
|
-
|
|
25429
|
+
store2.#size -= previousEntry.size;
|
|
25425
25430
|
} else {
|
|
25426
25431
|
entries.push(entry);
|
|
25427
|
-
|
|
25428
|
-
}
|
|
25429
|
-
|
|
25430
|
-
if (
|
|
25431
|
-
if (!
|
|
25432
|
-
|
|
25433
|
-
size:
|
|
25434
|
-
maxSize:
|
|
25435
|
-
count:
|
|
25436
|
-
maxCount:
|
|
25432
|
+
store2.#count += 1;
|
|
25433
|
+
}
|
|
25434
|
+
store2.#size += entry.size;
|
|
25435
|
+
if (store2.#size > store2.#maxSize || store2.#count > store2.#maxCount) {
|
|
25436
|
+
if (!store2.#hasEmittedMaxSizeEvent) {
|
|
25437
|
+
store2.emit("maxSizeExceeded", {
|
|
25438
|
+
size: store2.#size,
|
|
25439
|
+
maxSize: store2.#maxSize,
|
|
25440
|
+
count: store2.#count,
|
|
25441
|
+
maxCount: store2.#maxCount
|
|
25437
25442
|
});
|
|
25438
|
-
|
|
25443
|
+
store2.#hasEmittedMaxSizeEvent = true;
|
|
25439
25444
|
}
|
|
25440
|
-
for (const [key2, entries2] of
|
|
25445
|
+
for (const [key2, entries2] of store2.#entries) {
|
|
25441
25446
|
for (const entry2 of entries2.splice(0, entries2.length / 2)) {
|
|
25442
|
-
|
|
25443
|
-
|
|
25447
|
+
store2.#size -= entry2.size;
|
|
25448
|
+
store2.#count -= 1;
|
|
25444
25449
|
}
|
|
25445
25450
|
if (entries2.length === 0) {
|
|
25446
|
-
|
|
25451
|
+
store2.#entries.delete(key2);
|
|
25447
25452
|
}
|
|
25448
25453
|
}
|
|
25449
|
-
if (
|
|
25450
|
-
|
|
25454
|
+
if (store2.#size < store2.#maxSize && store2.#count < store2.#maxCount) {
|
|
25455
|
+
store2.#hasEmittedMaxSizeEvent = false;
|
|
25451
25456
|
}
|
|
25452
25457
|
}
|
|
25453
25458
|
callback(null);
|
|
@@ -25818,7 +25823,7 @@ var require_cache2 = __commonJS({
|
|
|
25818
25823
|
}
|
|
25819
25824
|
module.exports = (opts = {}) => {
|
|
25820
25825
|
const {
|
|
25821
|
-
store = new MemoryCacheStore(),
|
|
25826
|
+
store: store2 = new MemoryCacheStore(),
|
|
25822
25827
|
methods = ["GET"],
|
|
25823
25828
|
cacheByDefault = void 0,
|
|
25824
25829
|
type = "shared",
|
|
@@ -25827,7 +25832,7 @@ var require_cache2 = __commonJS({
|
|
|
25827
25832
|
if (typeof opts !== "object" || opts === null) {
|
|
25828
25833
|
throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? "null" : typeof opts}`);
|
|
25829
25834
|
}
|
|
25830
|
-
assertCacheStore(
|
|
25835
|
+
assertCacheStore(store2, "opts.store");
|
|
25831
25836
|
assertCacheMethods(methods, "opts.methods");
|
|
25832
25837
|
assertCacheOrigins(origins, "opts.origins");
|
|
25833
25838
|
if (typeof cacheByDefault !== "undefined" && typeof cacheByDefault !== "number") {
|
|
@@ -25837,7 +25842,7 @@ var require_cache2 = __commonJS({
|
|
|
25837
25842
|
throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`);
|
|
25838
25843
|
}
|
|
25839
25844
|
const globalOpts = {
|
|
25840
|
-
store,
|
|
25845
|
+
store: store2,
|
|
25841
25846
|
methods,
|
|
25842
25847
|
cacheByDefault,
|
|
25843
25848
|
type
|
|
@@ -25876,7 +25881,7 @@ var require_cache2 = __commonJS({
|
|
|
25876
25881
|
return dispatch(opts2, handler);
|
|
25877
25882
|
}
|
|
25878
25883
|
const cacheKey = makeCacheKey(opts2);
|
|
25879
|
-
const result2 =
|
|
25884
|
+
const result2 = store2.get(cacheKey);
|
|
25880
25885
|
if (result2 && typeof result2.then === "function") {
|
|
25881
25886
|
return result2.then((result3) => handleResult2(
|
|
25882
25887
|
dispatch,
|
|
@@ -25909,7 +25914,7 @@ var require_decompress = __commonJS({
|
|
|
25909
25914
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/interceptor/decompress.js"(exports, module) {
|
|
25910
25915
|
"use strict";
|
|
25911
25916
|
var { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = __require("zlib");
|
|
25912
|
-
var { pipeline } = __require("stream");
|
|
25917
|
+
var { pipeline: pipeline2 } = __require("stream");
|
|
25913
25918
|
var DecoratorHandler = require_decorator_handler();
|
|
25914
25919
|
var { runtimeFeatures } = require_runtime_features();
|
|
25915
25920
|
var supportedEncodings = {
|
|
@@ -26018,7 +26023,7 @@ var require_decompress = __commonJS({
|
|
|
26018
26023
|
#setupMultipleDecompressors(controller) {
|
|
26019
26024
|
const lastDecompressor = this.#decompressors[this.#decompressors.length - 1];
|
|
26020
26025
|
this.#setupDecompressorEvents(lastDecompressor, controller);
|
|
26021
|
-
|
|
26026
|
+
pipeline2(this.#decompressors, (err) => {
|
|
26022
26027
|
if (err) {
|
|
26023
26028
|
super.onResponseError(controller, err);
|
|
26024
26029
|
return;
|
|
@@ -26809,12 +26814,12 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
26809
26814
|
assertCacheValue(value);
|
|
26810
26815
|
let size = 0;
|
|
26811
26816
|
const body = [];
|
|
26812
|
-
const
|
|
26817
|
+
const store2 = this;
|
|
26813
26818
|
return new Writable({
|
|
26814
26819
|
decodeStrings: true,
|
|
26815
26820
|
write(chunk, encoding, callback) {
|
|
26816
26821
|
size += chunk.byteLength;
|
|
26817
|
-
if (size <
|
|
26822
|
+
if (size < store2.#maxEntrySize) {
|
|
26818
26823
|
body.push(chunk);
|
|
26819
26824
|
} else {
|
|
26820
26825
|
this.destroy();
|
|
@@ -26822,7 +26827,7 @@ var require_sqlite_cache_store = __commonJS({
|
|
|
26822
26827
|
callback();
|
|
26823
26828
|
},
|
|
26824
26829
|
final(callback) {
|
|
26825
|
-
|
|
26830
|
+
store2.set(key, { ...value, body });
|
|
26826
26831
|
callback();
|
|
26827
26832
|
}
|
|
26828
26833
|
});
|
|
@@ -28758,7 +28763,7 @@ var require_fetch = __commonJS({
|
|
|
28758
28763
|
subresourceSet
|
|
28759
28764
|
} = require_constants3();
|
|
28760
28765
|
var EE = __require("events");
|
|
28761
|
-
var { Readable: Readable2, pipeline, finished, isErrored, isReadable } = __require("stream");
|
|
28766
|
+
var { Readable: Readable2, pipeline: pipeline2, finished, isErrored, isReadable } = __require("stream");
|
|
28762
28767
|
var { addAbortListener, bufferToLowerCasedHeaderName } = require_util();
|
|
28763
28768
|
var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url();
|
|
28764
28769
|
var { getGlobalDispatcher } = require_global2();
|
|
@@ -29749,7 +29754,7 @@ var require_fetch = __commonJS({
|
|
|
29749
29754
|
status: status2,
|
|
29750
29755
|
statusText,
|
|
29751
29756
|
headersList,
|
|
29752
|
-
body: decoders.length ?
|
|
29757
|
+
body: decoders.length ? pipeline2(this.body, ...decoders, (err) => {
|
|
29753
29758
|
if (err) {
|
|
29754
29759
|
this.onError(err);
|
|
29755
29760
|
}
|
|
@@ -32222,9 +32227,9 @@ var require_sender = __commonJS({
|
|
|
32222
32227
|
}
|
|
32223
32228
|
async #run() {
|
|
32224
32229
|
this.#running = true;
|
|
32225
|
-
const
|
|
32226
|
-
while (!
|
|
32227
|
-
const node =
|
|
32230
|
+
const queue2 = this.#queue;
|
|
32231
|
+
while (!queue2.isEmpty()) {
|
|
32232
|
+
const node = queue2.shift();
|
|
32228
32233
|
if (node.promise !== null) {
|
|
32229
32234
|
await node.promise;
|
|
32230
32235
|
}
|
|
@@ -33383,7 +33388,7 @@ ${value}`;
|
|
|
33383
33388
|
var require_eventsource = __commonJS({
|
|
33384
33389
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/web/eventsource/eventsource.js"(exports, module) {
|
|
33385
33390
|
"use strict";
|
|
33386
|
-
var { pipeline } = __require("stream");
|
|
33391
|
+
var { pipeline: pipeline2 } = __require("stream");
|
|
33387
33392
|
var { fetching } = require_fetch();
|
|
33388
33393
|
var { makeRequest } = require_request2();
|
|
33389
33394
|
var { webidl } = require_webidl();
|
|
@@ -33541,7 +33546,7 @@ var require_eventsource = __commonJS({
|
|
|
33541
33546
|
));
|
|
33542
33547
|
}
|
|
33543
33548
|
});
|
|
33544
|
-
|
|
33549
|
+
pipeline2(
|
|
33545
33550
|
response.body.stream,
|
|
33546
33551
|
eventSourceStream,
|
|
33547
33552
|
(error) => {
|
|
@@ -33896,11 +33901,13 @@ function expBackoff(attempt) {
|
|
|
33896
33901
|
const i = Math.min(Math.max(attempt, 0), BACKOFF_MS.length - 1);
|
|
33897
33902
|
return BACKOFF_MS[i];
|
|
33898
33903
|
}
|
|
33899
|
-
var INGEST_BATCH_MAX_EVENTS, BACKOFF_MS, BACKSTOP_SCAN_MS;
|
|
33904
|
+
var INGEST_BATCH_MAX_EVENTS, SESSION_DEBOUNCE_MS, FORCE_SHIP_THRESHOLD, BACKOFF_MS, BACKSTOP_SCAN_MS;
|
|
33900
33905
|
var init_config = __esm({
|
|
33901
33906
|
"../../packages/daemon-core/src/config/index.ts"() {
|
|
33902
33907
|
"use strict";
|
|
33903
33908
|
INGEST_BATCH_MAX_EVENTS = 1e3;
|
|
33909
|
+
SESSION_DEBOUNCE_MS = 7e3;
|
|
33910
|
+
FORCE_SHIP_THRESHOLD = 200;
|
|
33904
33911
|
BACKOFF_MS = [1e3, 2500, 5e3, 1e4, 2e4, 6e4];
|
|
33905
33912
|
BACKSTOP_SCAN_MS = 5 * 6e4;
|
|
33906
33913
|
}
|
|
@@ -34890,7 +34897,7 @@ async function fetchDeviceViewLedgerByClaim(claimCode) {
|
|
|
34890
34897
|
}
|
|
34891
34898
|
function ingestClient() {
|
|
34892
34899
|
if (_ingest) return _ingest;
|
|
34893
|
-
const
|
|
34900
|
+
const logger2 = createLogger("daemon.ingest");
|
|
34894
34901
|
_ingest = new IngestClient({
|
|
34895
34902
|
apiUrl: state.apiUrl,
|
|
34896
34903
|
auth: {
|
|
@@ -34906,7 +34913,7 @@ function ingestClient() {
|
|
|
34906
34913
|
}
|
|
34907
34914
|
}
|
|
34908
34915
|
},
|
|
34909
|
-
logger
|
|
34916
|
+
logger: logger2
|
|
34910
34917
|
});
|
|
34911
34918
|
return _ingest;
|
|
34912
34919
|
}
|
|
@@ -35087,17 +35094,101 @@ var init_ids2 = __esm({
|
|
|
35087
35094
|
});
|
|
35088
35095
|
|
|
35089
35096
|
// ../../packages/daemon-core/src/queue/index.ts
|
|
35097
|
+
async function buildBatches(opts) {
|
|
35098
|
+
const debounceMs = opts.debounceMs ?? SESSION_DEBOUNCE_MS;
|
|
35099
|
+
const maxEvents = opts.maxEvents ?? INGEST_BATCH_MAX_EVENTS;
|
|
35100
|
+
const forceThreshold = opts.forceShipThreshold ?? FORCE_SHIP_THRESHOLD;
|
|
35101
|
+
const bySession = await opts.store.listUnsentBySession();
|
|
35102
|
+
const batches = [];
|
|
35103
|
+
let eventsInCurrentBatch = [];
|
|
35104
|
+
let sessionIdsInCurrentBatch = [];
|
|
35105
|
+
let toolCallsInCurrentBatch = [];
|
|
35106
|
+
for (const [, items] of bySession) {
|
|
35107
|
+
if (items.length === 0) continue;
|
|
35108
|
+
const lastTs = Math.max(...items.map((i) => i.last_event_ts_ms));
|
|
35109
|
+
const quiet = opts.nowMs - lastTs >= debounceMs;
|
|
35110
|
+
if (!quiet && items.length < forceThreshold) continue;
|
|
35111
|
+
for (const item of items) {
|
|
35112
|
+
const itemCalls = item.tool_calls ?? [];
|
|
35113
|
+
if (eventsInCurrentBatch.length >= maxEvents || eventsInCurrentBatch.length > 0 && toolCallsInCurrentBatch.length + itemCalls.length > INGEST_BATCH_MAX_TOOL_CALLS) {
|
|
35114
|
+
batches.push(
|
|
35115
|
+
await finalise({
|
|
35116
|
+
events: eventsInCurrentBatch,
|
|
35117
|
+
sessionIds: sessionIdsInCurrentBatch,
|
|
35118
|
+
toolCalls: toolCallsInCurrentBatch,
|
|
35119
|
+
pipeline: opts.pipeline,
|
|
35120
|
+
deviceId: opts.deviceId,
|
|
35121
|
+
daemonVersion: opts.daemonVersion
|
|
35122
|
+
})
|
|
35123
|
+
);
|
|
35124
|
+
eventsInCurrentBatch = [];
|
|
35125
|
+
sessionIdsInCurrentBatch = [];
|
|
35126
|
+
toolCallsInCurrentBatch = [];
|
|
35127
|
+
}
|
|
35128
|
+
eventsInCurrentBatch.push(item.event);
|
|
35129
|
+
sessionIdsInCurrentBatch.push(item.session_id);
|
|
35130
|
+
toolCallsInCurrentBatch.push(...itemCalls);
|
|
35131
|
+
}
|
|
35132
|
+
}
|
|
35133
|
+
if (eventsInCurrentBatch.length > 0) {
|
|
35134
|
+
batches.push(
|
|
35135
|
+
await finalise({
|
|
35136
|
+
events: eventsInCurrentBatch,
|
|
35137
|
+
sessionIds: sessionIdsInCurrentBatch,
|
|
35138
|
+
toolCalls: toolCallsInCurrentBatch,
|
|
35139
|
+
pipeline: opts.pipeline,
|
|
35140
|
+
deviceId: opts.deviceId,
|
|
35141
|
+
daemonVersion: opts.daemonVersion
|
|
35142
|
+
})
|
|
35143
|
+
);
|
|
35144
|
+
}
|
|
35145
|
+
return batches;
|
|
35146
|
+
}
|
|
35147
|
+
function attachSegmentIds(calls, segments) {
|
|
35148
|
+
const segmentByEvent = /* @__PURE__ */ new Map();
|
|
35149
|
+
for (const seg of segments) {
|
|
35150
|
+
for (const id of seg.source_event_ids) segmentByEvent.set(id, seg.segment_id);
|
|
35151
|
+
}
|
|
35152
|
+
return attachSegmentIdsByMap(calls, segmentByEvent);
|
|
35153
|
+
}
|
|
35090
35154
|
function attachSegmentIdsByMap(calls, segmentByEvent) {
|
|
35091
35155
|
return calls.map((c) => ({
|
|
35092
35156
|
...c,
|
|
35093
35157
|
segment_id: segmentByEvent.get(c.source_event_id) ?? null
|
|
35094
35158
|
}));
|
|
35095
35159
|
}
|
|
35160
|
+
async function finalise(args) {
|
|
35161
|
+
const segments = [];
|
|
35162
|
+
const bySession = /* @__PURE__ */ new Map();
|
|
35163
|
+
for (let i = 0; i < args.events.length; i++) {
|
|
35164
|
+
const sid = args.sessionIds[i] ?? args.events[i]?.session_id ?? "unknown";
|
|
35165
|
+
const arr = bySession.get(sid) ?? [];
|
|
35166
|
+
const ev = args.events[i];
|
|
35167
|
+
if (ev) arr.push(ev);
|
|
35168
|
+
bySession.set(sid, arr);
|
|
35169
|
+
}
|
|
35170
|
+
for (const [, sessionEvents] of bySession) {
|
|
35171
|
+
const segs = await args.pipeline.run(sessionEvents);
|
|
35172
|
+
segments.push(...segs);
|
|
35173
|
+
}
|
|
35174
|
+
return {
|
|
35175
|
+
batch_id: batchId(),
|
|
35176
|
+
device_id: args.deviceId,
|
|
35177
|
+
daemon_version: args.daemonVersion,
|
|
35178
|
+
events: args.events,
|
|
35179
|
+
segments,
|
|
35180
|
+
// Segments are in hand here, so segment attribution happens at the
|
|
35181
|
+
// last responsible moment before the wire.
|
|
35182
|
+
tool_calls: attachSegmentIds(args.toolCalls, segments)
|
|
35183
|
+
};
|
|
35184
|
+
}
|
|
35185
|
+
var INGEST_BATCH_MAX_TOOL_CALLS;
|
|
35096
35186
|
var init_queue = __esm({
|
|
35097
35187
|
"../../packages/daemon-core/src/queue/index.ts"() {
|
|
35098
35188
|
"use strict";
|
|
35099
35189
|
init_config();
|
|
35100
35190
|
init_ids2();
|
|
35191
|
+
INGEST_BATCH_MAX_TOOL_CALLS = 2e4;
|
|
35101
35192
|
}
|
|
35102
35193
|
});
|
|
35103
35194
|
|
|
@@ -37090,7 +37181,7 @@ var init_scan = __esm({
|
|
|
37090
37181
|
init_api();
|
|
37091
37182
|
init_config2();
|
|
37092
37183
|
init_pipeline2();
|
|
37093
|
-
DAEMON_VERSION = true ? "daemon-0.
|
|
37184
|
+
DAEMON_VERSION = true ? "daemon-0.8.1" : "daemon-dev";
|
|
37094
37185
|
BATCH_MAX_EVENTS = INGEST_BATCH_MAX_EVENTS;
|
|
37095
37186
|
BATCH_MAX_TOOL_CALLS = 2e4;
|
|
37096
37187
|
BATCH_BUFFER_HARD_CAP = BATCH_MAX_EVENTS * 2;
|
|
@@ -37327,6 +37418,165 @@ var init_update = __esm({
|
|
|
37327
37418
|
}
|
|
37328
37419
|
});
|
|
37329
37420
|
|
|
37421
|
+
// src/receiver.ts
|
|
37422
|
+
import { createServer } from "http";
|
|
37423
|
+
function queue() {
|
|
37424
|
+
if (!store) store = new FileQueueStore(homePath("sdk-ingest-queue.json"));
|
|
37425
|
+
return store;
|
|
37426
|
+
}
|
|
37427
|
+
function parseBatch(json) {
|
|
37428
|
+
if (typeof json !== "object" || json === null) return { error: "body must be a JSON object" };
|
|
37429
|
+
const b = json;
|
|
37430
|
+
if (!Array.isArray(b.events) || b.events.length === 0)
|
|
37431
|
+
return { error: "events must be a non-empty array" };
|
|
37432
|
+
if (b.events.length > 1e4) return { error: "too many events (max 10000)" };
|
|
37433
|
+
for (const e of b.events) {
|
|
37434
|
+
if (typeof e !== "object" || e === null) return { error: "each event must be an object" };
|
|
37435
|
+
const ev = e;
|
|
37436
|
+
for (const k of ["source_event_id", "session_id", "agent", "ts"]) {
|
|
37437
|
+
if (typeof ev[k] !== "string" || ev[k].length === 0)
|
|
37438
|
+
return { error: `event.${k} is required` };
|
|
37439
|
+
}
|
|
37440
|
+
}
|
|
37441
|
+
const toolCalls = Array.isArray(b.tool_calls) ? b.tool_calls : [];
|
|
37442
|
+
return { events: b.events, toolCalls };
|
|
37443
|
+
}
|
|
37444
|
+
async function enqueue(batch) {
|
|
37445
|
+
const q = queue();
|
|
37446
|
+
for (const event of batch.events) {
|
|
37447
|
+
const calls = batch.toolCalls.filter((tc) => tc.source_event_id === event.source_event_id).map(({ segment_id: _segmentId, ...draft }) => draft);
|
|
37448
|
+
await q.put({
|
|
37449
|
+
source_event_id: event.source_event_id,
|
|
37450
|
+
session_id: event.session_id,
|
|
37451
|
+
agent: event.agent,
|
|
37452
|
+
event,
|
|
37453
|
+
last_event_ts_ms: Date.parse(event.ts) || Date.now(),
|
|
37454
|
+
synced: false,
|
|
37455
|
+
sent_batch_id: null,
|
|
37456
|
+
tool_calls: calls.length > 0 ? calls : void 0
|
|
37457
|
+
});
|
|
37458
|
+
}
|
|
37459
|
+
return batch.events.length;
|
|
37460
|
+
}
|
|
37461
|
+
async function drainLocalQueue(opts) {
|
|
37462
|
+
if (draining) return { batches: 0, events: 0 };
|
|
37463
|
+
draining = true;
|
|
37464
|
+
try {
|
|
37465
|
+
const q = queue();
|
|
37466
|
+
if (await q.countUnsent() === 0) return { batches: 0, events: 0 };
|
|
37467
|
+
const batches = await buildBatches({
|
|
37468
|
+
store: q,
|
|
37469
|
+
pipeline,
|
|
37470
|
+
deviceId: opts.deviceId,
|
|
37471
|
+
daemonVersion: opts.daemonVersion,
|
|
37472
|
+
nowMs: Date.now()
|
|
37473
|
+
});
|
|
37474
|
+
let events = 0;
|
|
37475
|
+
for (const batch of batches) {
|
|
37476
|
+
const shipped = {
|
|
37477
|
+
...batch,
|
|
37478
|
+
events: batch.events.map(({ content_excerpt: _excerpt, ...rest }) => rest)
|
|
37479
|
+
};
|
|
37480
|
+
await uploadBatch(shipped);
|
|
37481
|
+
await q.markSent(
|
|
37482
|
+
batch.events.map((e) => e.source_event_id),
|
|
37483
|
+
batch.batch_id
|
|
37484
|
+
);
|
|
37485
|
+
events += batch.events.length;
|
|
37486
|
+
}
|
|
37487
|
+
return { batches: batches.length, events };
|
|
37488
|
+
} finally {
|
|
37489
|
+
draining = false;
|
|
37490
|
+
}
|
|
37491
|
+
}
|
|
37492
|
+
function localQueueDepth() {
|
|
37493
|
+
return queue().countUnsent();
|
|
37494
|
+
}
|
|
37495
|
+
function startLocalIngestReceiver(opts = {}) {
|
|
37496
|
+
const port = opts.port ?? (Number(process.env.MODELSTAT_LOCAL_INGEST_PORT) || DEFAULT_LOCAL_INGEST_PORT);
|
|
37497
|
+
return new Promise((resolve6) => {
|
|
37498
|
+
const server = createServer((req, res) => void handle(req, res));
|
|
37499
|
+
let settled = false;
|
|
37500
|
+
server.on("error", (err) => {
|
|
37501
|
+
if (settled) return;
|
|
37502
|
+
settled = true;
|
|
37503
|
+
logger.warn(
|
|
37504
|
+
`local ingest receiver disabled \u2014 SDK local_daemon mode unavailable: ${err.code ?? err.message} on 127.0.0.1:${port}`
|
|
37505
|
+
);
|
|
37506
|
+
resolve6(null);
|
|
37507
|
+
});
|
|
37508
|
+
server.listen(port, "127.0.0.1", () => {
|
|
37509
|
+
settled = true;
|
|
37510
|
+
const addr = server.address();
|
|
37511
|
+
const boundPort = typeof addr === "object" && addr ? addr.port : port;
|
|
37512
|
+
logger.info(`local ingest receiver on http://127.0.0.1:${boundPort}/v1/ingest`);
|
|
37513
|
+
resolve6({
|
|
37514
|
+
port: boundPort,
|
|
37515
|
+
close: () => new Promise((r) => server.close(() => r()))
|
|
37516
|
+
});
|
|
37517
|
+
});
|
|
37518
|
+
});
|
|
37519
|
+
}
|
|
37520
|
+
async function handle(req, res) {
|
|
37521
|
+
const send = (code, body) => {
|
|
37522
|
+
res.writeHead(code, { "content-type": "application/json" });
|
|
37523
|
+
res.end(JSON.stringify(body));
|
|
37524
|
+
};
|
|
37525
|
+
const path = (req.url ?? "").split("?")[0];
|
|
37526
|
+
if (req.method === "GET" && path === "/healthz") return send(200, { ok: true });
|
|
37527
|
+
if (req.method !== "POST" || path !== "/v1/ingest" && path !== "/v1/ingest/raw") {
|
|
37528
|
+
return send(404, { error: "not found" });
|
|
37529
|
+
}
|
|
37530
|
+
let size = 0;
|
|
37531
|
+
const chunks = [];
|
|
37532
|
+
try {
|
|
37533
|
+
for await (const chunk of req) {
|
|
37534
|
+
size += chunk.length;
|
|
37535
|
+
if (size > MAX_BODY_BYTES) {
|
|
37536
|
+
send(413, { error: "batch too large" });
|
|
37537
|
+
req.destroy();
|
|
37538
|
+
return;
|
|
37539
|
+
}
|
|
37540
|
+
chunks.push(chunk);
|
|
37541
|
+
}
|
|
37542
|
+
} catch {
|
|
37543
|
+
return send(400, { error: "read error" });
|
|
37544
|
+
}
|
|
37545
|
+
let json;
|
|
37546
|
+
try {
|
|
37547
|
+
json = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
37548
|
+
} catch {
|
|
37549
|
+
return send(400, { error: "invalid json" });
|
|
37550
|
+
}
|
|
37551
|
+
const parsed = parseBatch(json);
|
|
37552
|
+
if ("error" in parsed) return send(400, parsed);
|
|
37553
|
+
try {
|
|
37554
|
+
const accepted = await enqueue(parsed);
|
|
37555
|
+
return send(200, { accepted, queued: true });
|
|
37556
|
+
} catch (e) {
|
|
37557
|
+
logger.warn(`local ingest enqueue failed: ${e.message}`);
|
|
37558
|
+
return send(500, { error: "enqueue failed" });
|
|
37559
|
+
}
|
|
37560
|
+
}
|
|
37561
|
+
var logger, DEFAULT_LOCAL_INGEST_PORT, MAX_BODY_BYTES, store, pipeline, draining;
|
|
37562
|
+
var init_receiver = __esm({
|
|
37563
|
+
"src/receiver.ts"() {
|
|
37564
|
+
"use strict";
|
|
37565
|
+
init_logger();
|
|
37566
|
+
init_node();
|
|
37567
|
+
init_queue();
|
|
37568
|
+
init_api();
|
|
37569
|
+
init_paths();
|
|
37570
|
+
init_pipeline2();
|
|
37571
|
+
logger = createLogger("daemon.local-ingest");
|
|
37572
|
+
DEFAULT_LOCAL_INGEST_PORT = 4319;
|
|
37573
|
+
MAX_BODY_BYTES = 16 * 1024 * 1024;
|
|
37574
|
+
store = null;
|
|
37575
|
+
pipeline = { run: (events) => buildSegments(events) };
|
|
37576
|
+
draining = false;
|
|
37577
|
+
}
|
|
37578
|
+
});
|
|
37579
|
+
|
|
37330
37580
|
// src/reconcile.ts
|
|
37331
37581
|
import { stat as stat3 } from "fs/promises";
|
|
37332
37582
|
function utcDay(ts) {
|
|
@@ -37704,19 +37954,19 @@ function createPolicyRefresher(opts) {
|
|
|
37704
37954
|
...opts.fetch ? { fetch: opts.fetch } : {},
|
|
37705
37955
|
...opts.logger ? { logger: opts.logger } : {}
|
|
37706
37956
|
};
|
|
37707
|
-
const
|
|
37957
|
+
const store2 = new RemoteConfigStore(env, [policiesKind]);
|
|
37708
37958
|
let timer = null;
|
|
37709
37959
|
const apply = () => {
|
|
37710
|
-
const bundle =
|
|
37960
|
+
const bundle = store2.get("policies");
|
|
37711
37961
|
setRemoteRedactionPatterns(compilePolicyPatterns(bundle));
|
|
37712
37962
|
};
|
|
37713
37963
|
const refresh = async () => {
|
|
37714
|
-
await
|
|
37964
|
+
await store2.refresh("policies");
|
|
37715
37965
|
apply();
|
|
37716
37966
|
};
|
|
37717
37967
|
return {
|
|
37718
37968
|
async start() {
|
|
37719
|
-
await
|
|
37969
|
+
await store2.initFromCache();
|
|
37720
37970
|
apply();
|
|
37721
37971
|
void refresh().catch(() => {
|
|
37722
37972
|
});
|
|
@@ -39743,6 +39993,25 @@ async function runDaemon(opts = {}) {
|
|
|
39743
39993
|
setPhase("error", `summariser preflight failed: ${err.message}`);
|
|
39744
39994
|
throw err;
|
|
39745
39995
|
}
|
|
39996
|
+
const localIngest = await startLocalIngestReceiver();
|
|
39997
|
+
const LOCAL_DRAIN_INTERVAL_MS = 5e3;
|
|
39998
|
+
let localDrainTimer = null;
|
|
39999
|
+
if (localIngest) {
|
|
40000
|
+
const drainTick = async () => {
|
|
40001
|
+
try {
|
|
40002
|
+
const { events } = await drainLocalQueue({
|
|
40003
|
+
deviceId: state.deviceId,
|
|
40004
|
+
daemonVersion: DAEMON_VERSION2
|
|
40005
|
+
});
|
|
40006
|
+
if (events > 0) bumpStat("sdk_events_uploaded", events);
|
|
40007
|
+
setStat("sdk_queue", await localQueueDepth());
|
|
40008
|
+
} catch (e) {
|
|
40009
|
+
setMessage(`SDK ingest upload deferred: ${describeErrorWithCause(e)}`);
|
|
40010
|
+
}
|
|
40011
|
+
};
|
|
40012
|
+
localDrainTimer = setInterval(() => void drainTick(), LOCAL_DRAIN_INTERVAL_MS);
|
|
40013
|
+
localDrainTimer.unref();
|
|
40014
|
+
}
|
|
39746
40015
|
const { reconcileProcessingVersion: reconcileProcessingVersion2 } = await Promise.resolve().then(() => (init_processing_version(), processing_version_exports));
|
|
39747
40016
|
const pv = reconcileProcessingVersion2(state);
|
|
39748
40017
|
if (pv.changed) {
|
|
@@ -39809,6 +40078,8 @@ async function runDaemon(opts = {}) {
|
|
|
39809
40078
|
setPhase("offline", "Shutting down");
|
|
39810
40079
|
await sendHeartbeat();
|
|
39811
40080
|
await watcher.close();
|
|
40081
|
+
if (localDrainTimer) clearInterval(localDrainTimer);
|
|
40082
|
+
await localIngest?.close();
|
|
39812
40083
|
try {
|
|
39813
40084
|
const { disposeLlama: disposeLlama2 } = await Promise.resolve().then(() => (init_node(), node_exports));
|
|
39814
40085
|
await disposeLlama2();
|
|
@@ -39832,11 +40103,12 @@ var init_daemon = __esm({
|
|
|
39832
40103
|
init_config2();
|
|
39833
40104
|
init_lock();
|
|
39834
40105
|
init_machine_key();
|
|
40106
|
+
init_receiver();
|
|
39835
40107
|
init_reconcile();
|
|
39836
40108
|
init_scan();
|
|
39837
40109
|
init_single_flight();
|
|
39838
40110
|
init_update();
|
|
39839
|
-
DAEMON_VERSION2 = true ? "daemon-0.
|
|
40111
|
+
DAEMON_VERSION2 = true ? "daemon-0.8.1" : "daemon-dev";
|
|
39840
40112
|
HEARTBEAT_INTERVAL_MS = 1e4;
|
|
39841
40113
|
SCAN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
39842
40114
|
DISCOVERY_INTERVAL_MS = 6e4;
|
|
@@ -40440,7 +40712,7 @@ function tryOpenBrowser(url) {
|
|
|
40440
40712
|
return false;
|
|
40441
40713
|
}
|
|
40442
40714
|
}
|
|
40443
|
-
var DAEMON_VERSION3 = true ? "daemon-0.
|
|
40715
|
+
var DAEMON_VERSION3 = true ? "daemon-0.8.1" : "daemon-dev";
|
|
40444
40716
|
function osFamily() {
|
|
40445
40717
|
const p = platform6();
|
|
40446
40718
|
if (p === "darwin") return "macos";
|