ahp-inspector 1.2.0 → 1.3.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/index.js +283 -123
- package/package.json +1 -1
- package/ui-dist/assets/index-BAvWUkL4.css +1 -0
- package/ui-dist/assets/index-CJtScnuN.js +81 -0
- package/ui-dist/assets/index-CJtScnuN.js.map +1 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/index-BkKI8Byu.js +0 -14
- package/ui-dist/assets/index-BkKI8Byu.js.map +0 -1
- package/ui-dist/assets/index-CW0QHwfy.css +0 -1
package/dist/index.js
CHANGED
|
@@ -2351,12 +2351,19 @@ var TailReader = class {
|
|
|
2351
2351
|
this.#lastOffset = 0;
|
|
2352
2352
|
return;
|
|
2353
2353
|
}
|
|
2354
|
+
sink.onInitialReadStart?.({ totalBytes: sizeAtStart });
|
|
2354
2355
|
if (sizeAtStart === 0) {
|
|
2355
2356
|
this.#lastOffset = 0;
|
|
2357
|
+
sink.onInitialReadComplete?.({ loadedBytes: 0, totalBytes: 0 });
|
|
2356
2358
|
return;
|
|
2357
2359
|
}
|
|
2358
|
-
await this.#readRange(0, sizeAtStart, sink)
|
|
2359
|
-
|
|
2360
|
+
const result = await this.#readRange(0, sizeAtStart, sink, (loadedBytes) => {
|
|
2361
|
+
sink.onInitialReadProgress?.({ loadedBytes, totalBytes: sizeAtStart });
|
|
2362
|
+
});
|
|
2363
|
+
this.#lastOffset = result.nextOffset;
|
|
2364
|
+
if (result.completed && result.nextOffset >= sizeAtStart) {
|
|
2365
|
+
sink.onInitialReadComplete?.({ loadedBytes: sizeAtStart, totalBytes: sizeAtStart });
|
|
2366
|
+
}
|
|
2360
2367
|
}
|
|
2361
2368
|
/**
|
|
2362
2369
|
* Subscribe to file growth, rotation, and errors. Returns a disposer that
|
|
@@ -2410,8 +2417,8 @@ var TailReader = class {
|
|
|
2410
2417
|
}
|
|
2411
2418
|
if (nextSize === this.#lastOffset) return;
|
|
2412
2419
|
const start = this.#lastOffset;
|
|
2413
|
-
await this.#readRange(start, nextSize, sink);
|
|
2414
|
-
this.#lastOffset =
|
|
2420
|
+
const result = await this.#readRange(start, nextSize, sink);
|
|
2421
|
+
this.#lastOffset = result.nextOffset;
|
|
2415
2422
|
} finally {
|
|
2416
2423
|
this.#readInFlight = false;
|
|
2417
2424
|
if (this.#readAgainAfterCurrent && !this.#disposed) {
|
|
@@ -2433,11 +2440,11 @@ var TailReader = class {
|
|
|
2433
2440
|
this.#lastOffset = 0;
|
|
2434
2441
|
sink.onReset({ newSize, reason });
|
|
2435
2442
|
if (newSize > 0) {
|
|
2436
|
-
await this.#readRange(0, newSize, sink);
|
|
2437
|
-
this.#lastOffset =
|
|
2443
|
+
const result = await this.#readRange(0, newSize, sink);
|
|
2444
|
+
this.#lastOffset = result.nextOffset;
|
|
2438
2445
|
}
|
|
2439
2446
|
}
|
|
2440
|
-
#readRange(start, end, sink) {
|
|
2447
|
+
#readRange(start, end, sink, onProgress) {
|
|
2441
2448
|
return new Promise((resolve3) => {
|
|
2442
2449
|
const stream2 = createReadStream(this.#path, {
|
|
2443
2450
|
start,
|
|
@@ -2453,11 +2460,12 @@ var TailReader = class {
|
|
|
2453
2460
|
})();
|
|
2454
2461
|
sink.onChunk(bytes, cursor);
|
|
2455
2462
|
cursor += bytes.byteLength;
|
|
2463
|
+
onProgress?.(cursor);
|
|
2456
2464
|
});
|
|
2457
|
-
stream2.on("end", () => resolve3());
|
|
2465
|
+
stream2.on("end", () => resolve3({ completed: true, nextOffset: cursor }));
|
|
2458
2466
|
stream2.on("error", (err) => {
|
|
2459
2467
|
sink.onError(err, false);
|
|
2460
|
-
resolve3();
|
|
2468
|
+
resolve3({ completed: false, nextOffset: cursor });
|
|
2461
2469
|
});
|
|
2462
2470
|
});
|
|
2463
2471
|
}
|
|
@@ -2529,6 +2537,7 @@ var Correlator = class {
|
|
|
2529
2537
|
#store;
|
|
2530
2538
|
#pendingRequests = /* @__PURE__ */ new Map();
|
|
2531
2539
|
#pendingResponses = /* @__PURE__ */ new Map();
|
|
2540
|
+
#changedIndexes = /* @__PURE__ */ new Set();
|
|
2532
2541
|
#unsubscribe;
|
|
2533
2542
|
pairIdx = [];
|
|
2534
2543
|
latencyMs = [];
|
|
@@ -2548,6 +2557,11 @@ var Correlator = class {
|
|
|
2548
2557
|
statusOf(idx) {
|
|
2549
2558
|
return this.status[idx] ?? "n/a";
|
|
2550
2559
|
}
|
|
2560
|
+
drainChangedIndexes() {
|
|
2561
|
+
const indexes = [...this.#changedIndexes];
|
|
2562
|
+
this.#changedIndexes.clear();
|
|
2563
|
+
return indexes;
|
|
2564
|
+
}
|
|
2551
2565
|
/**
|
|
2552
2566
|
* Advance time. Any request still pending older than `timeoutMs` becomes
|
|
2553
2567
|
* 'unmatched'. Cheap O(pendingRequests).
|
|
@@ -2557,6 +2571,7 @@ var Correlator = class {
|
|
|
2557
2571
|
const ts = this.#store.ts[idx];
|
|
2558
2572
|
if (ts !== void 0 && nowMs - ts >= timeoutMs) {
|
|
2559
2573
|
this.status[idx] = "unmatched";
|
|
2574
|
+
this.#changedIndexes.add(idx);
|
|
2560
2575
|
this.#pendingRequests.delete(key);
|
|
2561
2576
|
}
|
|
2562
2577
|
}
|
|
@@ -2569,6 +2584,7 @@ var Correlator = class {
|
|
|
2569
2584
|
reset() {
|
|
2570
2585
|
this.#pendingRequests.clear();
|
|
2571
2586
|
this.#pendingResponses.clear();
|
|
2587
|
+
this.#changedIndexes.clear();
|
|
2572
2588
|
this.pairIdx.length = 0;
|
|
2573
2589
|
this.latencyMs.length = 0;
|
|
2574
2590
|
this.status.length = 0;
|
|
@@ -2600,9 +2616,11 @@ var Correlator = class {
|
|
|
2600
2616
|
const displaced = this.#pendingRequests.get(key);
|
|
2601
2617
|
if (displaced !== void 0) {
|
|
2602
2618
|
this.status[displaced] = "orphan";
|
|
2619
|
+
this.#changedIndexes.add(displaced);
|
|
2603
2620
|
}
|
|
2604
2621
|
this.#pendingRequests.set(key, idx);
|
|
2605
2622
|
this.status[idx] = "pending";
|
|
2623
|
+
this.#changedIndexes.add(idx);
|
|
2606
2624
|
}
|
|
2607
2625
|
#onResponse(idx, ev) {
|
|
2608
2626
|
const key = correlationKeyForResponse(ev);
|
|
@@ -2615,6 +2633,7 @@ var Correlator = class {
|
|
|
2615
2633
|
const displaced = this.#pendingResponses.get(key);
|
|
2616
2634
|
if (displaced !== void 0) {
|
|
2617
2635
|
this.status[displaced] = "orphan";
|
|
2636
|
+
this.#changedIndexes.add(displaced);
|
|
2618
2637
|
}
|
|
2619
2638
|
this.#pendingResponses.set(key, idx);
|
|
2620
2639
|
}
|
|
@@ -2629,6 +2648,8 @@ var Correlator = class {
|
|
|
2629
2648
|
const s = isError ? "error" : "ok";
|
|
2630
2649
|
this.status[reqIdx] = s;
|
|
2631
2650
|
this.status[respIdx] = s;
|
|
2651
|
+
this.#changedIndexes.add(reqIdx);
|
|
2652
|
+
this.#changedIndexes.add(respIdx);
|
|
2632
2653
|
}
|
|
2633
2654
|
};
|
|
2634
2655
|
function isErrorResponse(ev) {
|
|
@@ -2739,7 +2760,7 @@ var IS_CLIENT_DISPATCHABLE = {
|
|
|
2739
2760
|
["root/configChanged" /* RootConfigChanged */]: true,
|
|
2740
2761
|
["session/ready" /* SessionReady */]: false,
|
|
2741
2762
|
["session/creationFailed" /* SessionCreationFailed */]: false,
|
|
2742
|
-
["session/turnStarted" /* SessionTurnStarted */]:
|
|
2763
|
+
["session/turnStarted" /* SessionTurnStarted */]: false,
|
|
2743
2764
|
["session/delta" /* SessionDelta */]: false,
|
|
2744
2765
|
["session/responsePart" /* SessionResponsePart */]: false,
|
|
2745
2766
|
["session/toolCallStart" /* SessionToolCallStart */]: false,
|
|
@@ -2767,13 +2788,19 @@ var IS_CLIENT_DISPATCHABLE = {
|
|
|
2767
2788
|
["session/inputCompleted" /* SessionInputCompleted */]: true,
|
|
2768
2789
|
["session/customizationsChanged" /* SessionCustomizationsChanged */]: false,
|
|
2769
2790
|
["session/customizationToggled" /* SessionCustomizationToggled */]: true,
|
|
2791
|
+
["session/customizationUpdated" /* SessionCustomizationUpdated */]: false,
|
|
2770
2792
|
["session/truncated" /* SessionTruncated */]: true,
|
|
2771
2793
|
["session/isReadChanged" /* SessionIsReadChanged */]: true,
|
|
2772
2794
|
["session/isArchivedChanged" /* SessionIsArchivedChanged */]: true,
|
|
2773
2795
|
["session/activityChanged" /* SessionActivityChanged */]: false,
|
|
2774
|
-
["session/
|
|
2796
|
+
["session/changesetsChanged" /* SessionChangesetsChanged */]: false,
|
|
2775
2797
|
["session/configChanged" /* SessionConfigChanged */]: true,
|
|
2776
2798
|
["session/metaChanged" /* SessionMetaChanged */]: false,
|
|
2799
|
+
["changeset/statusChanged" /* ChangesetStatusChanged */]: false,
|
|
2800
|
+
["changeset/fileSet" /* ChangesetFileSet */]: false,
|
|
2801
|
+
["changeset/fileRemoved" /* ChangesetFileRemoved */]: false,
|
|
2802
|
+
["changeset/operationsChanged" /* ChangesetOperationsChanged */]: false,
|
|
2803
|
+
["changeset/cleared" /* ChangesetCleared */]: false,
|
|
2777
2804
|
["terminal/data" /* TerminalData */]: false,
|
|
2778
2805
|
["terminal/input" /* TerminalInput */]: true,
|
|
2779
2806
|
["terminal/resized" /* TerminalResized */]: true,
|
|
@@ -2787,11 +2814,39 @@ var IS_CLIENT_DISPATCHABLE = {
|
|
|
2787
2814
|
["terminal/commandFinished" /* TerminalCommandFinished */]: false
|
|
2788
2815
|
};
|
|
2789
2816
|
|
|
2790
|
-
// ../protocol/src/
|
|
2817
|
+
// ../protocol/src/common/reducer-helpers.ts
|
|
2791
2818
|
function softAssertNever(value, log) {
|
|
2792
2819
|
const msg = `Unhandled action type: ${JSON.stringify(value)}`;
|
|
2793
2820
|
(log ?? console.warn)(msg);
|
|
2794
2821
|
}
|
|
2822
|
+
|
|
2823
|
+
// ../protocol/src/channels-root/reducer.ts
|
|
2824
|
+
function rootReducer(state, action, log) {
|
|
2825
|
+
switch (action.type) {
|
|
2826
|
+
case "root/agentsChanged" /* RootAgentsChanged */:
|
|
2827
|
+
return { ...state, agents: action.agents };
|
|
2828
|
+
case "root/activeSessionsChanged" /* RootActiveSessionsChanged */:
|
|
2829
|
+
return { ...state, activeSessions: action.activeSessions };
|
|
2830
|
+
case "root/terminalsChanged" /* RootTerminalsChanged */:
|
|
2831
|
+
return { ...state, terminals: action.terminals };
|
|
2832
|
+
case "root/configChanged" /* RootConfigChanged */:
|
|
2833
|
+
if (!state.config) {
|
|
2834
|
+
return state;
|
|
2835
|
+
}
|
|
2836
|
+
return {
|
|
2837
|
+
...state,
|
|
2838
|
+
config: {
|
|
2839
|
+
...state.config,
|
|
2840
|
+
values: action.replace ? { ...action.config } : { ...state.config.values, ...action.config }
|
|
2841
|
+
}
|
|
2842
|
+
};
|
|
2843
|
+
default:
|
|
2844
|
+
softAssertNever(action, log);
|
|
2845
|
+
return state;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
// ../protocol/src/channels-session/reducer.ts
|
|
2795
2850
|
function tcBase(tc) {
|
|
2796
2851
|
return {
|
|
2797
2852
|
toolCallId: tc.toolCallId,
|
|
@@ -2952,30 +3007,6 @@ function updateResponsePart(state, turnId, partId, updater) {
|
|
|
2952
3007
|
activeTurn: { ...activeTurn, responseParts }
|
|
2953
3008
|
};
|
|
2954
3009
|
}
|
|
2955
|
-
function rootReducer(state, action, log) {
|
|
2956
|
-
switch (action.type) {
|
|
2957
|
-
case "root/agentsChanged" /* RootAgentsChanged */:
|
|
2958
|
-
return { ...state, agents: action.agents };
|
|
2959
|
-
case "root/activeSessionsChanged" /* RootActiveSessionsChanged */:
|
|
2960
|
-
return { ...state, activeSessions: action.activeSessions };
|
|
2961
|
-
case "root/terminalsChanged" /* RootTerminalsChanged */:
|
|
2962
|
-
return { ...state, terminals: action.terminals };
|
|
2963
|
-
case "root/configChanged" /* RootConfigChanged */:
|
|
2964
|
-
if (!state.config) {
|
|
2965
|
-
return state;
|
|
2966
|
-
}
|
|
2967
|
-
return {
|
|
2968
|
-
...state,
|
|
2969
|
-
config: {
|
|
2970
|
-
...state.config,
|
|
2971
|
-
values: action.replace ? { ...action.config } : { ...state.config.values, ...action.config }
|
|
2972
|
-
}
|
|
2973
|
-
};
|
|
2974
|
-
default:
|
|
2975
|
-
softAssertNever(action, log);
|
|
2976
|
-
return state;
|
|
2977
|
-
}
|
|
2978
|
-
}
|
|
2979
3010
|
function sessionReducer(state, action, log) {
|
|
2980
3011
|
switch (action.type) {
|
|
2981
3012
|
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
@@ -3259,26 +3290,46 @@ function sessionReducer(state, action, log) {
|
|
|
3259
3290
|
...state,
|
|
3260
3291
|
summary: { ...state.summary, activity: action.activity }
|
|
3261
3292
|
};
|
|
3262
|
-
case "session/
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
case "session/configChanged" /* SessionConfigChanged */:
|
|
3293
|
+
case "session/changesetsChanged" /* SessionChangesetsChanged */: {
|
|
3294
|
+
const { changesets: _omit, ...summaryWithoutChangesets } = state.summary;
|
|
3295
|
+
const newSummary = action.changesets ? { ...summaryWithoutChangesets, changesets: action.changesets } : summaryWithoutChangesets;
|
|
3296
|
+
return { ...state, summary: newSummary };
|
|
3297
|
+
}
|
|
3298
|
+
case "session/configChanged" /* SessionConfigChanged */: {
|
|
3268
3299
|
if (!state.config) {
|
|
3300
|
+
if (!action.schema) {
|
|
3301
|
+
return state;
|
|
3302
|
+
}
|
|
3303
|
+
return {
|
|
3304
|
+
...state,
|
|
3305
|
+
config: {
|
|
3306
|
+
schema: action.schema,
|
|
3307
|
+
values: action.config ? { ...action.config } : {}
|
|
3308
|
+
},
|
|
3309
|
+
summary: {
|
|
3310
|
+
...state.summary,
|
|
3311
|
+
modifiedAt: Date.now()
|
|
3312
|
+
}
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
const values = action.config !== void 0 ? action.replace ? { ...action.config } : { ...state.config.values, ...action.config } : state.config.values;
|
|
3316
|
+
const schema = action.schema ?? state.config.schema;
|
|
3317
|
+
if (values === state.config.values && schema === state.config.schema) {
|
|
3269
3318
|
return state;
|
|
3270
3319
|
}
|
|
3271
3320
|
return {
|
|
3272
3321
|
...state,
|
|
3273
3322
|
config: {
|
|
3274
3323
|
...state.config,
|
|
3275
|
-
|
|
3324
|
+
schema,
|
|
3325
|
+
values
|
|
3276
3326
|
},
|
|
3277
3327
|
summary: {
|
|
3278
3328
|
...state.summary,
|
|
3279
3329
|
modifiedAt: Date.now()
|
|
3280
3330
|
}
|
|
3281
3331
|
};
|
|
3332
|
+
}
|
|
3282
3333
|
case "session/metaChanged" /* SessionMetaChanged */:
|
|
3283
3334
|
return { ...state, _meta: action._meta };
|
|
3284
3335
|
case "session/serverToolsChanged" /* SessionServerToolsChanged */:
|
|
@@ -3312,6 +3363,36 @@ function sessionReducer(state, action, log) {
|
|
|
3312
3363
|
updated[idx] = { ...list[idx], enabled: action.enabled };
|
|
3313
3364
|
return { ...state, customizations: updated };
|
|
3314
3365
|
}
|
|
3366
|
+
case "session/customizationUpdated" /* SessionCustomizationUpdated */: {
|
|
3367
|
+
const list = state.customizations ?? [];
|
|
3368
|
+
const idx = list.findIndex((c) => c.customization.uri === action.customization.uri);
|
|
3369
|
+
if (idx < 0) {
|
|
3370
|
+
const inserted = {
|
|
3371
|
+
customization: action.customization,
|
|
3372
|
+
enabled: action.enabled ?? false
|
|
3373
|
+
};
|
|
3374
|
+
if (action.status !== void 0) {
|
|
3375
|
+
inserted.status = action.status;
|
|
3376
|
+
}
|
|
3377
|
+
if (action.statusMessage !== void 0) {
|
|
3378
|
+
inserted.statusMessage = action.statusMessage;
|
|
3379
|
+
}
|
|
3380
|
+
return { ...state, customizations: [...list, inserted] };
|
|
3381
|
+
}
|
|
3382
|
+
const updated = [...list];
|
|
3383
|
+
const next = { ...list[idx], customization: action.customization };
|
|
3384
|
+
if (action.enabled !== void 0) {
|
|
3385
|
+
next.enabled = action.enabled;
|
|
3386
|
+
}
|
|
3387
|
+
if (action.status !== void 0) {
|
|
3388
|
+
next.status = action.status;
|
|
3389
|
+
}
|
|
3390
|
+
if (action.statusMessage !== void 0) {
|
|
3391
|
+
next.statusMessage = action.statusMessage;
|
|
3392
|
+
}
|
|
3393
|
+
updated[idx] = next;
|
|
3394
|
+
return { ...state, customizations: updated };
|
|
3395
|
+
}
|
|
3315
3396
|
// ── Truncation ────────────────────────────────────────────────────────
|
|
3316
3397
|
case "session/truncated" /* SessionTruncated */: {
|
|
3317
3398
|
let turns;
|
|
@@ -3437,6 +3518,8 @@ function sessionReducer(state, action, log) {
|
|
|
3437
3518
|
return state;
|
|
3438
3519
|
}
|
|
3439
3520
|
}
|
|
3521
|
+
|
|
3522
|
+
// ../protocol/src/channels-terminal/reducer.ts
|
|
3440
3523
|
function terminalReducer(state, action, log) {
|
|
3441
3524
|
switch (action.type) {
|
|
3442
3525
|
case "terminal/data" /* TerminalData */: {
|
|
@@ -3541,13 +3624,19 @@ var ACTION_INTRODUCED_IN = {
|
|
|
3541
3624
|
["session/inputCompleted" /* SessionInputCompleted */]: "0.1.0",
|
|
3542
3625
|
["session/customizationsChanged" /* SessionCustomizationsChanged */]: "0.1.0",
|
|
3543
3626
|
["session/customizationToggled" /* SessionCustomizationToggled */]: "0.1.0",
|
|
3627
|
+
["session/customizationUpdated" /* SessionCustomizationUpdated */]: "0.1.0",
|
|
3544
3628
|
["session/truncated" /* SessionTruncated */]: "0.1.0",
|
|
3545
3629
|
["session/isReadChanged" /* SessionIsReadChanged */]: "0.1.0",
|
|
3546
3630
|
["session/isArchivedChanged" /* SessionIsArchivedChanged */]: "0.1.0",
|
|
3547
3631
|
["session/activityChanged" /* SessionActivityChanged */]: "0.1.0",
|
|
3548
|
-
["session/
|
|
3632
|
+
["session/changesetsChanged" /* SessionChangesetsChanged */]: "0.2.0",
|
|
3549
3633
|
["session/configChanged" /* SessionConfigChanged */]: "0.1.0",
|
|
3550
3634
|
["session/metaChanged" /* SessionMetaChanged */]: "0.1.0",
|
|
3635
|
+
["changeset/statusChanged" /* ChangesetStatusChanged */]: "0.2.0",
|
|
3636
|
+
["changeset/fileSet" /* ChangesetFileSet */]: "0.2.0",
|
|
3637
|
+
["changeset/fileRemoved" /* ChangesetFileRemoved */]: "0.2.0",
|
|
3638
|
+
["changeset/operationsChanged" /* ChangesetOperationsChanged */]: "0.2.0",
|
|
3639
|
+
["changeset/cleared" /* ChangesetCleared */]: "0.2.0",
|
|
3551
3640
|
["root/terminalsChanged" /* RootTerminalsChanged */]: "0.1.0",
|
|
3552
3641
|
["root/configChanged" /* RootConfigChanged */]: "0.1.0",
|
|
3553
3642
|
["terminal/data" /* TerminalData */]: "0.1.0",
|
|
@@ -3562,12 +3651,6 @@ var ACTION_INTRODUCED_IN = {
|
|
|
3562
3651
|
["terminal/commandExecuted" /* TerminalCommandExecuted */]: "0.1.0",
|
|
3563
3652
|
["terminal/commandFinished" /* TerminalCommandFinished */]: "0.1.0"
|
|
3564
3653
|
};
|
|
3565
|
-
var NOTIFICATION_INTRODUCED_IN = {
|
|
3566
|
-
["notify/sessionAdded" /* SessionAdded */]: "0.1.0",
|
|
3567
|
-
["notify/sessionRemoved" /* SessionRemoved */]: "0.1.0",
|
|
3568
|
-
["notify/sessionSummaryChanged" /* SessionSummaryChanged */]: "0.1.0",
|
|
3569
|
-
["notify/authRequired" /* AuthRequired */]: "0.1.0"
|
|
3570
|
-
};
|
|
3571
3654
|
|
|
3572
3655
|
// ../core/src/replay.ts
|
|
3573
3656
|
var ROOT_RESOURCE = "agenthost:/root";
|
|
@@ -3747,7 +3830,7 @@ function installSnapshot(ctx, value, eventIdx) {
|
|
|
3747
3830
|
});
|
|
3748
3831
|
}
|
|
3749
3832
|
function applyEnvelope(ctx, envelope, eventIdx, eventTs) {
|
|
3750
|
-
const target = inferActionTarget(envelope.action);
|
|
3833
|
+
const target = inferActionTarget(envelope.action, envelope.channel);
|
|
3751
3834
|
if (!target) {
|
|
3752
3835
|
addDiagnostic(ctx, {
|
|
3753
3836
|
code: "unknown-action",
|
|
@@ -3838,7 +3921,8 @@ function recordClientIntent(ctx, event, eventIdx) {
|
|
|
3838
3921
|
const action = isRecord(params) && isRecord(params.action) ? params.action : null;
|
|
3839
3922
|
const clientSeq = isRecord(params) && typeof params.clientSeq === "number" ? params.clientSeq : null;
|
|
3840
3923
|
const actionType = actionTypeOf(action);
|
|
3841
|
-
const
|
|
3924
|
+
const channel = isRecord(params) && typeof params.channel === "string" ? params.channel : void 0;
|
|
3925
|
+
const resource = action ? inferActionTarget(action, channel) : null;
|
|
3842
3926
|
const intent = {
|
|
3843
3927
|
eventIdx,
|
|
3844
3928
|
ts: event.ts,
|
|
@@ -3896,7 +3980,7 @@ function readSnapshot(value) {
|
|
|
3896
3980
|
};
|
|
3897
3981
|
}
|
|
3898
3982
|
function readActionEnvelope(value) {
|
|
3899
|
-
if (!isRecord(value) || typeof value.serverSeq !== "number" || !isRecord(value.action)) {
|
|
3983
|
+
if (!isRecord(value) || typeof value.channel !== "string" || typeof value.serverSeq !== "number" || !isRecord(value.action)) {
|
|
3900
3984
|
return null;
|
|
3901
3985
|
}
|
|
3902
3986
|
if (typeof value.action.type !== "string") {
|
|
@@ -3904,6 +3988,7 @@ function readActionEnvelope(value) {
|
|
|
3904
3988
|
}
|
|
3905
3989
|
const origin = isRecord(value.origin) && typeof value.origin.clientId === "string" && typeof value.origin.clientSeq === "number" ? { clientId: value.origin.clientId, clientSeq: value.origin.clientSeq } : void 0;
|
|
3906
3990
|
return {
|
|
3991
|
+
channel: value.channel,
|
|
3907
3992
|
action: value.action,
|
|
3908
3993
|
serverSeq: value.serverSeq,
|
|
3909
3994
|
origin,
|
|
@@ -3925,20 +4010,20 @@ function inferSnapshotKind(snapshot) {
|
|
|
3925
4010
|
}
|
|
3926
4011
|
return "unknown";
|
|
3927
4012
|
}
|
|
3928
|
-
function inferActionTarget(action) {
|
|
4013
|
+
function inferActionTarget(action, channel) {
|
|
3929
4014
|
const type = actionTypeOf(action);
|
|
3930
4015
|
if (!type) {
|
|
3931
4016
|
return null;
|
|
3932
4017
|
}
|
|
3933
4018
|
if (type.startsWith("root/")) {
|
|
3934
|
-
return { kind: "root", uri: ROOT_RESOURCE };
|
|
4019
|
+
return { kind: "root", uri: channel ?? ROOT_RESOURCE };
|
|
3935
4020
|
}
|
|
3936
4021
|
if (type.startsWith("session/")) {
|
|
3937
|
-
const session = isRecord(action) && typeof action.session === "string" ? action.session : null;
|
|
4022
|
+
const session = channel ?? (isRecord(action) && typeof action.session === "string" ? action.session : null);
|
|
3938
4023
|
return session ? { kind: "session", uri: session } : null;
|
|
3939
4024
|
}
|
|
3940
4025
|
if (type.startsWith("terminal/")) {
|
|
3941
|
-
const terminal = isRecord(action) && typeof action.terminal === "string" ? action.terminal : null;
|
|
4026
|
+
const terminal = channel ?? (isRecord(action) && typeof action.terminal === "string" ? action.terminal : null);
|
|
3942
4027
|
return terminal ? { kind: "terminal", uri: terminal } : null;
|
|
3943
4028
|
}
|
|
3944
4029
|
return null;
|
|
@@ -4103,12 +4188,14 @@ function readKnownAction(value) {
|
|
|
4103
4188
|
}
|
|
4104
4189
|
function readActionEnvelope2(value) {
|
|
4105
4190
|
if (!isRecord2(value)) return null;
|
|
4191
|
+
if (typeof value.channel !== "string") return null;
|
|
4106
4192
|
if (typeof value.serverSeq !== "number") return null;
|
|
4107
4193
|
const action = asRecord(value.action);
|
|
4108
4194
|
if (!action || typeof action.type !== "string") return null;
|
|
4109
4195
|
const origin = isRecord2(value.origin) && typeof value.origin.clientId === "string" && typeof value.origin.clientSeq === "number" ? { clientId: value.origin.clientId, clientSeq: value.origin.clientSeq } : void 0;
|
|
4110
4196
|
const known = readKnownAction(action);
|
|
4111
4197
|
return {
|
|
4198
|
+
channel: value.channel,
|
|
4112
4199
|
action: known ?? action,
|
|
4113
4200
|
serverSeq: value.serverSeq,
|
|
4114
4201
|
origin,
|
|
@@ -4194,7 +4281,7 @@ function summarizeResponse(view) {
|
|
|
4194
4281
|
}
|
|
4195
4282
|
function summarizeAction(view) {
|
|
4196
4283
|
if (isKnownAction(view.action)) {
|
|
4197
|
-
return summarizeKnownAction(view.action);
|
|
4284
|
+
return summarizeKnownAction(view.action, view.envelope?.channel ?? null);
|
|
4198
4285
|
}
|
|
4199
4286
|
return summarizeUnknownAction(view.action);
|
|
4200
4287
|
}
|
|
@@ -4207,7 +4294,7 @@ function summarizeProtocolNotification(view) {
|
|
|
4207
4294
|
function summarizeLog(view) {
|
|
4208
4295
|
return `log ${clip(view.message ?? "details unavailable")}`;
|
|
4209
4296
|
}
|
|
4210
|
-
function summarizeKnownAction(action) {
|
|
4297
|
+
function summarizeKnownAction(action, channel) {
|
|
4211
4298
|
switch (action.type) {
|
|
4212
4299
|
case "session/delta" /* SessionDelta */:
|
|
4213
4300
|
return `delta "${clip(action.content)}"`;
|
|
@@ -4216,13 +4303,13 @@ function summarizeKnownAction(action) {
|
|
|
4216
4303
|
case "session/toolCallStart" /* SessionToolCallStart */:
|
|
4217
4304
|
return `tool start ${action.toolName}${action.displayName ? ` (${clip(action.displayName, 32)})` : ""}`;
|
|
4218
4305
|
case "session/toolCallDelta" /* SessionToolCallDelta */:
|
|
4219
|
-
return
|
|
4306
|
+
return summarizeToolCallDelta(action);
|
|
4220
4307
|
case "session/toolCallReady" /* SessionToolCallReady */:
|
|
4221
4308
|
return `tool ready ${action.toolCallId} ${stringOrMd(action.invocationMessage, 48)}`;
|
|
4222
4309
|
case "session/toolCallComplete" /* SessionToolCallComplete */:
|
|
4223
4310
|
return `tool result ${action.toolCallId} success=${action.result.success}`;
|
|
4224
4311
|
case "session/toolCallContentChanged" /* SessionToolCallContentChanged */:
|
|
4225
|
-
return
|
|
4312
|
+
return summarizeToolCallContentChanged(action);
|
|
4226
4313
|
case "session/turnStarted" /* SessionTurnStarted */:
|
|
4227
4314
|
return `turn start ${shortId(action.turnId)}`;
|
|
4228
4315
|
case "session/turnComplete" /* SessionTurnComplete */:
|
|
@@ -4240,15 +4327,23 @@ function summarizeKnownAction(action) {
|
|
|
4240
4327
|
case "session/reasoning" /* SessionReasoning */:
|
|
4241
4328
|
return `reasoning "${clip(action.content, 60)}"`;
|
|
4242
4329
|
case "session/ready" /* SessionReady */:
|
|
4243
|
-
return `session ready ${shortId(
|
|
4330
|
+
return channel ? `session ready ${shortId(channel)}` : "session ready";
|
|
4244
4331
|
case "terminal/data" /* TerminalData */:
|
|
4245
|
-
return `terminal data ${shortId(action.
|
|
4332
|
+
return channel ? `terminal data ${shortId(channel)} +${action.data.length}b` : `terminal data +${action.data.length}b`;
|
|
4246
4333
|
case "terminal/commandFinished" /* TerminalCommandFinished */:
|
|
4247
4334
|
return `terminal cmd done exit=${action.exitCode ?? "?"}`;
|
|
4248
4335
|
default:
|
|
4249
4336
|
return innerActionTypeAndDetail(toUnknownPayload(action));
|
|
4250
4337
|
}
|
|
4251
4338
|
}
|
|
4339
|
+
function summarizeToolCallDelta(action) {
|
|
4340
|
+
const content = typeof action.content === "string" ? action.content : null;
|
|
4341
|
+
return content === null ? `tool delta ${action.toolCallId}` : `tool delta ${action.toolCallId} +${content.length}b`;
|
|
4342
|
+
}
|
|
4343
|
+
function summarizeToolCallContentChanged(action) {
|
|
4344
|
+
const content = Array.isArray(action.content) ? action.content : null;
|
|
4345
|
+
return content === null ? `tool content ${action.toolCallId}` : `tool content ${action.toolCallId} (${content.length} parts)`;
|
|
4346
|
+
}
|
|
4252
4347
|
function summarizeUnknownAction(action) {
|
|
4253
4348
|
if (!action.type) return "action details unavailable";
|
|
4254
4349
|
const t = action.type;
|
|
@@ -4680,6 +4775,9 @@ async function createAppState(opts) {
|
|
|
4680
4775
|
const searchIdx = new SearchIndex();
|
|
4681
4776
|
let seq = 0;
|
|
4682
4777
|
let byteOffset = 0;
|
|
4778
|
+
let initialReadLoadedBytes = 0;
|
|
4779
|
+
let initialReadTotalBytes;
|
|
4780
|
+
let initialReadPhase = "idle";
|
|
4683
4781
|
function emit(payload) {
|
|
4684
4782
|
for (const l of listeners) {
|
|
4685
4783
|
try {
|
|
@@ -4688,6 +4786,22 @@ async function createAppState(opts) {
|
|
|
4688
4786
|
}
|
|
4689
4787
|
}
|
|
4690
4788
|
}
|
|
4789
|
+
function currentLoadProgress(phase = initialReadPhase) {
|
|
4790
|
+
const totalBytes = initialReadTotalBytes;
|
|
4791
|
+
const percent = totalBytes !== void 0 && totalBytes > 0 ? Math.min(100, Math.round(initialReadLoadedBytes / totalBytes * 100)) : void 0;
|
|
4792
|
+
return {
|
|
4793
|
+
kind: "load-progress",
|
|
4794
|
+
phase,
|
|
4795
|
+
loadedRows: rows.length,
|
|
4796
|
+
loadedBytes: initialReadLoadedBytes,
|
|
4797
|
+
...totalBytes !== void 0 ? { totalBytes } : {},
|
|
4798
|
+
...percent !== void 0 ? { percent } : {}
|
|
4799
|
+
};
|
|
4800
|
+
}
|
|
4801
|
+
function emitLoadProgress(phase) {
|
|
4802
|
+
initialReadPhase = phase;
|
|
4803
|
+
emit(currentLoadProgress());
|
|
4804
|
+
}
|
|
4691
4805
|
let lastSeenServerSeq = null;
|
|
4692
4806
|
function buildRow(idx) {
|
|
4693
4807
|
const ev = store.at(idx);
|
|
@@ -4717,6 +4831,30 @@ async function createAppState(opts) {
|
|
|
4717
4831
|
};
|
|
4718
4832
|
return projectRow(ev, idx, status, latency, extras, pairMethod);
|
|
4719
4833
|
}
|
|
4834
|
+
function buildPatchUpdates(indexes) {
|
|
4835
|
+
const updates = [];
|
|
4836
|
+
for (const idx of indexes) {
|
|
4837
|
+
const prev = rows[idx];
|
|
4838
|
+
if (!prev) continue;
|
|
4839
|
+
const status = correlator.statusOf(idx);
|
|
4840
|
+
const latencyMs = correlator.latencyOf(idx);
|
|
4841
|
+
const pairIdx = correlator.pairOf(idx);
|
|
4842
|
+
if (prev.status === status && prev.latencyMs === latencyMs && prev.pairIdx === pairIdx) {
|
|
4843
|
+
continue;
|
|
4844
|
+
}
|
|
4845
|
+
const latencyBand = bandFor(latencyMs);
|
|
4846
|
+
rows[idx] = { ...prev, status, latencyMs, latencyBand, pairIdx };
|
|
4847
|
+
updates.push({
|
|
4848
|
+
idx,
|
|
4849
|
+
status,
|
|
4850
|
+
latencyMs,
|
|
4851
|
+
latencyBand,
|
|
4852
|
+
...prev.summary !== void 0 ? { summary: prev.summary } : {},
|
|
4853
|
+
pairIdx
|
|
4854
|
+
});
|
|
4855
|
+
}
|
|
4856
|
+
return updates;
|
|
4857
|
+
}
|
|
4720
4858
|
const offStore = store.subscribe((range) => {
|
|
4721
4859
|
const newRows = [];
|
|
4722
4860
|
for (let i = range.from; i < range.to; i++) {
|
|
@@ -4728,30 +4866,27 @@ async function createAppState(opts) {
|
|
|
4728
4866
|
if (ev) searchIdx.append(ev);
|
|
4729
4867
|
}
|
|
4730
4868
|
}
|
|
4731
|
-
const
|
|
4732
|
-
|
|
4733
|
-
const prev = rows[i];
|
|
4734
|
-
if (!prev) continue;
|
|
4735
|
-
const status = correlator.statusOf(i);
|
|
4736
|
-
const latencyMs = correlator.latencyOf(i);
|
|
4737
|
-
const pairIdx = correlator.pairOf(i);
|
|
4738
|
-
if (prev.status !== status || prev.latencyMs !== latencyMs || prev.pairIdx !== pairIdx) {
|
|
4739
|
-
const latencyBand = bandFor(latencyMs);
|
|
4740
|
-
rows[i] = { ...prev, status, latencyMs, latencyBand, pairIdx };
|
|
4741
|
-
updates.push({
|
|
4742
|
-
idx: i,
|
|
4743
|
-
status,
|
|
4744
|
-
latencyMs,
|
|
4745
|
-
latencyBand,
|
|
4746
|
-
...prev.summary !== void 0 ? { summary: prev.summary } : {},
|
|
4747
|
-
pairIdx
|
|
4748
|
-
});
|
|
4749
|
-
}
|
|
4750
|
-
}
|
|
4869
|
+
const changedIndexes = correlator.drainChangedIndexes().filter((idx) => idx < range.from);
|
|
4870
|
+
const updates = buildPatchUpdates(changedIndexes);
|
|
4751
4871
|
if (newRows.length > 0) emit({ kind: "append", rows: newRows, from: range.from });
|
|
4752
4872
|
if (updates.length > 0) emit({ kind: "patch", updates });
|
|
4753
4873
|
});
|
|
4754
4874
|
const watcher = opts.host.watchLog(handle, {
|
|
4875
|
+
onInitialReadStart(info) {
|
|
4876
|
+
initialReadLoadedBytes = 0;
|
|
4877
|
+
initialReadTotalBytes = info.totalBytes;
|
|
4878
|
+
emitLoadProgress("loading");
|
|
4879
|
+
},
|
|
4880
|
+
onInitialReadProgress(info) {
|
|
4881
|
+
initialReadLoadedBytes = info.loadedBytes;
|
|
4882
|
+
initialReadTotalBytes = info.totalBytes;
|
|
4883
|
+
emitLoadProgress("loading");
|
|
4884
|
+
},
|
|
4885
|
+
onInitialReadComplete(info) {
|
|
4886
|
+
initialReadLoadedBytes = info.loadedBytes;
|
|
4887
|
+
initialReadTotalBytes = info.totalBytes;
|
|
4888
|
+
emitLoadProgress("complete");
|
|
4889
|
+
},
|
|
4755
4890
|
onChunk(chunk, _byteOffset) {
|
|
4756
4891
|
const text = decoder.decode(chunk, { stream: true });
|
|
4757
4892
|
const newlineSize = text.includes("\r\n") ? 2 : 1;
|
|
@@ -4793,6 +4928,9 @@ async function createAppState(opts) {
|
|
|
4793
4928
|
rows.length = 0;
|
|
4794
4929
|
searchIdx.reset();
|
|
4795
4930
|
lastSeenServerSeq = null;
|
|
4931
|
+
initialReadLoadedBytes = 0;
|
|
4932
|
+
initialReadTotalBytes = void 0;
|
|
4933
|
+
emitLoadProgress("idle");
|
|
4796
4934
|
emit({ kind: "rotation", newSize: info.newSize, reason: info.reason });
|
|
4797
4935
|
},
|
|
4798
4936
|
onError(err, fatal) {
|
|
@@ -4806,26 +4944,7 @@ async function createAppState(opts) {
|
|
|
4806
4944
|
function runFlush(nowMs) {
|
|
4807
4945
|
const now = nowMs ?? Date.now();
|
|
4808
4946
|
correlator.flush(now, unmatchedTimeoutMs);
|
|
4809
|
-
const updates =
|
|
4810
|
-
for (let i = 0; i < store.size(); i++) {
|
|
4811
|
-
const prev = rows[i];
|
|
4812
|
-
if (!prev) continue;
|
|
4813
|
-
const status = correlator.statusOf(i);
|
|
4814
|
-
const latencyMs = correlator.latencyOf(i);
|
|
4815
|
-
const pairIdx = correlator.pairOf(i);
|
|
4816
|
-
if (prev.status !== status || prev.latencyMs !== latencyMs || prev.pairIdx !== pairIdx) {
|
|
4817
|
-
const latencyBand = bandFor(latencyMs);
|
|
4818
|
-
rows[i] = { ...prev, status, latencyMs, latencyBand, pairIdx };
|
|
4819
|
-
updates.push({
|
|
4820
|
-
idx: i,
|
|
4821
|
-
status,
|
|
4822
|
-
latencyMs,
|
|
4823
|
-
latencyBand,
|
|
4824
|
-
...prev.summary !== void 0 ? { summary: prev.summary } : {},
|
|
4825
|
-
pairIdx
|
|
4826
|
-
});
|
|
4827
|
-
}
|
|
4828
|
-
}
|
|
4947
|
+
const updates = buildPatchUpdates(correlator.drainChangedIndexes());
|
|
4829
4948
|
if (updates.length > 0) emit({ kind: "patch", updates });
|
|
4830
4949
|
}
|
|
4831
4950
|
const flushIntervalMs = opts.flushIntervalMs ?? 1e3;
|
|
@@ -4835,7 +4954,7 @@ async function createAppState(opts) {
|
|
|
4835
4954
|
meta,
|
|
4836
4955
|
searchIndex: searchIdx,
|
|
4837
4956
|
snapshot() {
|
|
4838
|
-
return { meta, rows: rows.slice() };
|
|
4957
|
+
return { meta, rows: rows.slice(), loadProgress: currentLoadProgress() };
|
|
4839
4958
|
},
|
|
4840
4959
|
subscribe(l) {
|
|
4841
4960
|
listeners.add(l);
|
|
@@ -7881,30 +8000,17 @@ function registerLogRoutes(app, sessions) {
|
|
|
7881
8000
|
}
|
|
7882
8001
|
return streamSSE(c, async (stream2) => {
|
|
7883
8002
|
const a = initial;
|
|
7884
|
-
const snap = a.appState.snapshot();
|
|
7885
|
-
await stream2.writeSSE({
|
|
7886
|
-
event: "snapshot-begin",
|
|
7887
|
-
data: JSON.stringify({ meta: snap.meta, total: snap.rows.length })
|
|
7888
|
-
});
|
|
7889
|
-
for (let i = 0; i < snap.rows.length; i += SNAPSHOT_CHUNK) {
|
|
7890
|
-
if (stream2.aborted || stream2.closed) return;
|
|
7891
|
-
const chunk = snap.rows.slice(i, i + SNAPSHOT_CHUNK);
|
|
7892
|
-
await stream2.writeSSE({
|
|
7893
|
-
event: "snapshot-chunk",
|
|
7894
|
-
data: JSON.stringify({ rows: chunk, from: i })
|
|
7895
|
-
});
|
|
7896
|
-
await stream2.sleep(0);
|
|
7897
|
-
}
|
|
7898
|
-
if (stream2.aborted || stream2.closed) return;
|
|
7899
|
-
await stream2.writeSSE({ event: "snapshot-end", data: "{}" });
|
|
7900
8003
|
const queue = [];
|
|
8004
|
+
let queueStart = 0;
|
|
7901
8005
|
let pumping = false;
|
|
8006
|
+
let snapshotStreaming = true;
|
|
8007
|
+
const queuedFrameCount = () => queue.length - queueStart;
|
|
7902
8008
|
const pump = async () => {
|
|
7903
|
-
if (pumping) return;
|
|
8009
|
+
if (pumping || snapshotStreaming) return;
|
|
7904
8010
|
pumping = true;
|
|
7905
8011
|
try {
|
|
7906
|
-
while (
|
|
7907
|
-
const msg = queue
|
|
8012
|
+
while (queuedFrameCount() > 0 && !stream2.aborted && !stream2.closed) {
|
|
8013
|
+
const msg = queue[queueStart++];
|
|
7908
8014
|
if (!msg) break;
|
|
7909
8015
|
try {
|
|
7910
8016
|
await stream2.writeSSE({ event: msg.kind, data: JSON.stringify(msg) });
|
|
@@ -7913,6 +8019,10 @@ function registerLogRoutes(app, sessions) {
|
|
|
7913
8019
|
}
|
|
7914
8020
|
}
|
|
7915
8021
|
} finally {
|
|
8022
|
+
if (queueStart === queue.length) {
|
|
8023
|
+
queue.length = 0;
|
|
8024
|
+
queueStart = 0;
|
|
8025
|
+
}
|
|
7916
8026
|
pumping = false;
|
|
7917
8027
|
}
|
|
7918
8028
|
};
|
|
@@ -7920,6 +8030,56 @@ function registerLogRoutes(app, sessions) {
|
|
|
7920
8030
|
queue.push(msg);
|
|
7921
8031
|
void pump();
|
|
7922
8032
|
});
|
|
8033
|
+
const snap = a.appState.snapshot();
|
|
8034
|
+
await stream2.writeSSE({
|
|
8035
|
+
event: "snapshot-begin",
|
|
8036
|
+
data: JSON.stringify({ meta: snap.meta, total: snap.rows.length })
|
|
8037
|
+
});
|
|
8038
|
+
for (let i = 0; i < snap.rows.length; i += SNAPSHOT_CHUNK) {
|
|
8039
|
+
if (stream2.aborted || stream2.closed) {
|
|
8040
|
+
off();
|
|
8041
|
+
return;
|
|
8042
|
+
}
|
|
8043
|
+
const chunk = snap.rows.slice(i, i + SNAPSHOT_CHUNK);
|
|
8044
|
+
await stream2.writeSSE({
|
|
8045
|
+
event: "snapshot-chunk",
|
|
8046
|
+
data: JSON.stringify({ rows: chunk, from: i })
|
|
8047
|
+
});
|
|
8048
|
+
await stream2.sleep(0);
|
|
8049
|
+
}
|
|
8050
|
+
if (stream2.aborted || stream2.closed) {
|
|
8051
|
+
off();
|
|
8052
|
+
return;
|
|
8053
|
+
}
|
|
8054
|
+
await stream2.writeSSE({ event: "snapshot-end", data: "{}" });
|
|
8055
|
+
if (snap.loadProgress.phase !== "idle") {
|
|
8056
|
+
await stream2.writeSSE({
|
|
8057
|
+
event: snap.loadProgress.kind,
|
|
8058
|
+
data: JSON.stringify(snap.loadProgress)
|
|
8059
|
+
});
|
|
8060
|
+
}
|
|
8061
|
+
snapshotStreaming = false;
|
|
8062
|
+
if (queuedFrameCount() > 0) {
|
|
8063
|
+
const queuedRows = queue.slice(queueStart).reduce((total, msg) => total + (msg.kind === "append" ? msg.rows.length : 0), 0);
|
|
8064
|
+
const backlog = {
|
|
8065
|
+
kind: "stream-backlog",
|
|
8066
|
+
queuedFrames: queuedFrameCount(),
|
|
8067
|
+
queuedRows
|
|
8068
|
+
};
|
|
8069
|
+
await stream2.writeSSE({ event: backlog.kind, data: JSON.stringify(backlog) });
|
|
8070
|
+
await pump();
|
|
8071
|
+
const clearedBacklog = {
|
|
8072
|
+
kind: "stream-backlog",
|
|
8073
|
+
queuedFrames: 0,
|
|
8074
|
+
queuedRows: 0
|
|
8075
|
+
};
|
|
8076
|
+
await stream2.writeSSE({
|
|
8077
|
+
event: clearedBacklog.kind,
|
|
8078
|
+
data: JSON.stringify(clearedBacklog)
|
|
8079
|
+
});
|
|
8080
|
+
} else {
|
|
8081
|
+
await pump();
|
|
8082
|
+
}
|
|
7923
8083
|
let endRequested = false;
|
|
7924
8084
|
const offChange = sessions.onChange(async () => {
|
|
7925
8085
|
if (endRequested) return;
|