ragent-cli 1.11.15 → 1.11.16
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 +380 -232
- package/dist/sbom.json +5 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ var require_package = __commonJS({
|
|
|
31
31
|
"package.json"(exports2, module2) {
|
|
32
32
|
module2.exports = {
|
|
33
33
|
name: "ragent-cli",
|
|
34
|
-
version: "1.11.
|
|
34
|
+
version: "1.11.16",
|
|
35
35
|
description: "CLI agent for rAgent Live \u2014 browser-first terminal control plane for AI coding agents",
|
|
36
36
|
main: "dist/index.js",
|
|
37
37
|
bin: {
|
|
@@ -435,6 +435,10 @@ var blockCounter = 0;
|
|
|
435
435
|
function genBlockId(prefix) {
|
|
436
436
|
return `${prefix}-${Date.now()}-${(++blockCounter).toString(36)}`;
|
|
437
437
|
}
|
|
438
|
+
function makeStableBlockIdGen(turnId) {
|
|
439
|
+
let n = 0;
|
|
440
|
+
return (prefix) => `${turnId}-${prefix}-${n++}`;
|
|
441
|
+
}
|
|
438
442
|
function now() {
|
|
439
443
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
440
444
|
}
|
|
@@ -1422,6 +1426,7 @@ var GeminiCliParserV2 = class {
|
|
|
1422
1426
|
return this.parseLegacySchemaItem(item, turnId, timestamp, pendingLegacyCalls);
|
|
1423
1427
|
}
|
|
1424
1428
|
parseNewSchemaItem(item, turnId, timestamp) {
|
|
1429
|
+
const nextBlockId = makeStableBlockIdGen(turnId);
|
|
1425
1430
|
const statusLevel = geminiStatusLevelFromType(item.type);
|
|
1426
1431
|
if (statusLevel) {
|
|
1427
1432
|
const text2 = geminiTextFromNewItem(item);
|
|
@@ -1440,7 +1445,7 @@ var GeminiCliParserV2 = class {
|
|
|
1440
1445
|
{
|
|
1441
1446
|
op: "insert_block",
|
|
1442
1447
|
turnId,
|
|
1443
|
-
block: makeStatusBlock(
|
|
1448
|
+
block: makeStatusBlock(nextBlockId("status"), "notice", text2, statusLevel)
|
|
1444
1449
|
},
|
|
1445
1450
|
{
|
|
1446
1451
|
op: "complete_turn",
|
|
@@ -1466,7 +1471,7 @@ ${description}` : subject || description;
|
|
|
1466
1471
|
op: "insert_block",
|
|
1467
1472
|
turnId,
|
|
1468
1473
|
block: makeReasoningBlock(
|
|
1469
|
-
|
|
1474
|
+
nextBlockId("reason"),
|
|
1470
1475
|
reasoningText,
|
|
1471
1476
|
"summary"
|
|
1472
1477
|
)
|
|
@@ -1477,14 +1482,14 @@ ${description}` : subject || description;
|
|
|
1477
1482
|
blocks.push({
|
|
1478
1483
|
op: "insert_block",
|
|
1479
1484
|
turnId,
|
|
1480
|
-
block: makeTextBlock(
|
|
1485
|
+
block: makeTextBlock(nextBlockId("txt"), text, true)
|
|
1481
1486
|
});
|
|
1482
1487
|
}
|
|
1483
1488
|
if (role === "assistant" && Array.isArray(item.toolCalls)) {
|
|
1484
1489
|
for (const tc of item.toolCalls) {
|
|
1485
1490
|
if (!tc.name) continue;
|
|
1486
|
-
const callId = tc.id ??
|
|
1487
|
-
const blockId =
|
|
1491
|
+
const callId = tc.id ?? nextBlockId("call");
|
|
1492
|
+
const blockId = nextBlockId("tool");
|
|
1488
1493
|
const state = mapGeminiToolStatus(tc.status);
|
|
1489
1494
|
const isComplete = state === "completed" || state === "error" || state === "cancelled";
|
|
1490
1495
|
blocks.push({
|
|
@@ -1527,6 +1532,7 @@ ${description}` : subject || description;
|
|
|
1527
1532
|
parseLegacySchemaItem(item, turnId, timestamp, pendingLegacyCalls) {
|
|
1528
1533
|
const role = geminiRoleFromLegacy(item.role);
|
|
1529
1534
|
if (!role) return [];
|
|
1535
|
+
const nextBlockId = makeStableBlockIdGen(turnId);
|
|
1530
1536
|
const parts = geminiPartsFromLegacyItem(item);
|
|
1531
1537
|
const currentTurnBlocks = [];
|
|
1532
1538
|
const priorTurnUpdates = [];
|
|
@@ -1536,12 +1542,12 @@ ${description}` : subject || description;
|
|
|
1536
1542
|
currentTurnBlocks.push({
|
|
1537
1543
|
op: "insert_block",
|
|
1538
1544
|
turnId,
|
|
1539
|
-
block: makeTextBlock(
|
|
1545
|
+
block: makeTextBlock(nextBlockId("txt"), text, true)
|
|
1540
1546
|
});
|
|
1541
1547
|
}
|
|
1542
1548
|
if (part.functionCall?.name) {
|
|
1543
|
-
const callId =
|
|
1544
|
-
const blockId =
|
|
1549
|
+
const callId = nextBlockId("call");
|
|
1550
|
+
const blockId = nextBlockId("tool");
|
|
1545
1551
|
pendingLegacyCalls.set(part.functionCall.name, { turnId, blockId });
|
|
1546
1552
|
currentTurnBlocks.push({
|
|
1547
1553
|
op: "insert_block",
|
|
@@ -1577,13 +1583,13 @@ ${description}` : subject || description;
|
|
|
1577
1583
|
});
|
|
1578
1584
|
}
|
|
1579
1585
|
} else {
|
|
1580
|
-
const blockId =
|
|
1586
|
+
const blockId = nextBlockId("tool");
|
|
1581
1587
|
currentTurnBlocks.push({
|
|
1582
1588
|
op: "insert_block",
|
|
1583
1589
|
turnId,
|
|
1584
1590
|
block: makeToolBlock(
|
|
1585
1591
|
blockId,
|
|
1586
|
-
|
|
1592
|
+
nextBlockId("call"),
|
|
1587
1593
|
part.functionResponse.name,
|
|
1588
1594
|
"completed",
|
|
1589
1595
|
void 0,
|
|
@@ -1640,7 +1646,8 @@ var AntigravityCliParserV2 = class {
|
|
|
1640
1646
|
if (!obj.source || !obj.type) return [];
|
|
1641
1647
|
const ops = [];
|
|
1642
1648
|
const timestamp = obj.created_at || now();
|
|
1643
|
-
const turnId = `step-${obj.step_index}
|
|
1649
|
+
const turnId = `step-${obj.step_index}`;
|
|
1650
|
+
const nextBlockId = makeStableBlockIdGen(turnId);
|
|
1644
1651
|
const normalizedType = obj.type.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1645
1652
|
const pendingIndex = this.pendingTools.findIndex(
|
|
1646
1653
|
(t) => t.normalizedName === normalizedType
|
|
@@ -1689,7 +1696,7 @@ var AntigravityCliParserV2 = class {
|
|
|
1689
1696
|
ops.push({
|
|
1690
1697
|
op: "insert_block",
|
|
1691
1698
|
turnId,
|
|
1692
|
-
block: makeTextBlock(
|
|
1699
|
+
block: makeTextBlock(nextBlockId("txt"), obj.content, true)
|
|
1693
1700
|
});
|
|
1694
1701
|
}
|
|
1695
1702
|
ops.push({
|
|
@@ -1713,13 +1720,13 @@ var AntigravityCliParserV2 = class {
|
|
|
1713
1720
|
ops.push({
|
|
1714
1721
|
op: "insert_block",
|
|
1715
1722
|
turnId,
|
|
1716
|
-
block: makeTextBlock(
|
|
1723
|
+
block: makeTextBlock(nextBlockId("txt"), obj.content, true)
|
|
1717
1724
|
});
|
|
1718
1725
|
}
|
|
1719
1726
|
if (obj.tool_calls && obj.tool_calls.length > 0) {
|
|
1720
1727
|
for (const tc of obj.tool_calls) {
|
|
1721
|
-
const callId =
|
|
1722
|
-
const blockId =
|
|
1728
|
+
const callId = nextBlockId("call");
|
|
1729
|
+
const blockId = nextBlockId("tool");
|
|
1723
1730
|
const normalizedName = tc.name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1724
1731
|
this.pendingTools.push({
|
|
1725
1732
|
blockId,
|
|
@@ -1760,7 +1767,7 @@ var AntigravityCliParserV2 = class {
|
|
|
1760
1767
|
ops.push({
|
|
1761
1768
|
op: "insert_block",
|
|
1762
1769
|
turnId,
|
|
1763
|
-
block: makeTextBlock(
|
|
1770
|
+
block: makeTextBlock(nextBlockId("txt"), obj.content, true)
|
|
1764
1771
|
});
|
|
1765
1772
|
}
|
|
1766
1773
|
ops.push({
|
|
@@ -1776,6 +1783,7 @@ var AntigravityCliParserV2 = class {
|
|
|
1776
1783
|
return ops;
|
|
1777
1784
|
}
|
|
1778
1785
|
parseDocument(document) {
|
|
1786
|
+
this.pendingTools = [];
|
|
1779
1787
|
const ops = [];
|
|
1780
1788
|
for (const line of document.split("\n")) {
|
|
1781
1789
|
const trimmed = line.trim();
|
|
@@ -1992,8 +2000,10 @@ function setBlock(turns, turnId, blockId, block) {
|
|
|
1992
2000
|
}
|
|
1993
2001
|
var MAX_SNAPSHOT_TURNS = 1e3;
|
|
1994
2002
|
var MAX_SNAPSHOT_SIZE_CHARS = 45e4;
|
|
2003
|
+
var SNAPSHOT_FIELD_RESERVE = 64;
|
|
1995
2004
|
function trimSnapshot(snapshot, maxTurns = MAX_SNAPSHOT_TURNS) {
|
|
1996
2005
|
let currentSnapshot = snapshot;
|
|
2006
|
+
const originalLength = snapshot.turnOrder.length;
|
|
1997
2007
|
if (currentSnapshot.turnOrder.length > maxTurns) {
|
|
1998
2008
|
const keptOrder = currentSnapshot.turnOrder.slice(-maxTurns);
|
|
1999
2009
|
const keptTurns = {};
|
|
@@ -2009,10 +2019,8 @@ function trimSnapshot(snapshot, maxTurns = MAX_SNAPSHOT_TURNS) {
|
|
|
2009
2019
|
};
|
|
2010
2020
|
}
|
|
2011
2021
|
let serialized = JSON.stringify(currentSnapshot);
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
}
|
|
2015
|
-
while (currentSnapshot.turnOrder.length > 1 && serialized.length > MAX_SNAPSHOT_SIZE_CHARS) {
|
|
2022
|
+
const sizeBudget = MAX_SNAPSHOT_SIZE_CHARS - SNAPSHOT_FIELD_RESERVE;
|
|
2023
|
+
while (currentSnapshot.turnOrder.length > 1 && serialized.length > sizeBudget) {
|
|
2016
2024
|
const keptOrder = currentSnapshot.turnOrder.slice(1);
|
|
2017
2025
|
const keptTurns = {};
|
|
2018
2026
|
for (const id of keptOrder) {
|
|
@@ -2027,6 +2035,11 @@ function trimSnapshot(snapshot, maxTurns = MAX_SNAPSHOT_TURNS) {
|
|
|
2027
2035
|
};
|
|
2028
2036
|
serialized = JSON.stringify(currentSnapshot);
|
|
2029
2037
|
}
|
|
2038
|
+
const droppedThisCall = originalLength - currentSnapshot.turnOrder.length;
|
|
2039
|
+
const truncatedTurns = (snapshot.truncatedTurns ?? 0) + droppedThisCall;
|
|
2040
|
+
if (truncatedTurns > 0 && currentSnapshot.truncatedTurns !== truncatedTurns) {
|
|
2041
|
+
currentSnapshot = { ...currentSnapshot, truncatedTurns };
|
|
2042
|
+
}
|
|
2030
2043
|
return currentSnapshot;
|
|
2031
2044
|
}
|
|
2032
2045
|
|
|
@@ -2562,6 +2575,155 @@ function releaseSessionSource(sessionId) {
|
|
|
2562
2575
|
sessionSourceLocks.delete(sessionId);
|
|
2563
2576
|
}
|
|
2564
2577
|
|
|
2578
|
+
// src/websocket.ts
|
|
2579
|
+
var import_ws = __toESM(require("ws"));
|
|
2580
|
+
var BACKPRESSURE_HIGH_WATER = 256 * 1024;
|
|
2581
|
+
var BACKPRESSURE_LOW_WATER = 64 * 1024;
|
|
2582
|
+
var MAX_PENDING_QUEUE = 500;
|
|
2583
|
+
var DRAIN_INTERVAL_MS = 50;
|
|
2584
|
+
function sanitizeForJson(str) {
|
|
2585
|
+
return str.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
|
|
2586
|
+
}
|
|
2587
|
+
var DANGEROUS_OSC_RE = /\x1b\](?:52|7|8);[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
2588
|
+
function stripDangerousEscapes(str) {
|
|
2589
|
+
return str.replace(DANGEROUS_OSC_RE, "");
|
|
2590
|
+
}
|
|
2591
|
+
var SECRET_PATTERNS = [
|
|
2592
|
+
/AKIA[0-9A-Z]{16}/g,
|
|
2593
|
+
// AWS access key
|
|
2594
|
+
/gh[ps]_[A-Za-z0-9_]{36,}/g,
|
|
2595
|
+
// GitHub token
|
|
2596
|
+
/sk_(?:live|test)_[A-Za-z0-9]{24,}/g,
|
|
2597
|
+
// Stripe secret key
|
|
2598
|
+
/eyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g
|
|
2599
|
+
// JWT
|
|
2600
|
+
];
|
|
2601
|
+
var redactionEnabled = true;
|
|
2602
|
+
function setRedactionEnabled(enabled) {
|
|
2603
|
+
redactionEnabled = enabled;
|
|
2604
|
+
}
|
|
2605
|
+
function redactSecrets(str) {
|
|
2606
|
+
if (!redactionEnabled) return str;
|
|
2607
|
+
let result = str;
|
|
2608
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
2609
|
+
pattern.lastIndex = 0;
|
|
2610
|
+
result = result.replace(pattern, "[REDACTED]");
|
|
2611
|
+
}
|
|
2612
|
+
return result;
|
|
2613
|
+
}
|
|
2614
|
+
var streamingTails = /* @__PURE__ */ new Map();
|
|
2615
|
+
var MAX_STREAMING_TAIL = 1024;
|
|
2616
|
+
var SECRET_PREFIX_RE = /(?:AKIA[0-9A-Z]*|gh[ps]_[A-Za-z0-9_]*|sk_(?:live|test)_[A-Za-z0-9]*|eyJ[A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]*){0,2})$/;
|
|
2617
|
+
function redactStreamingChunk(sessionId, chunk) {
|
|
2618
|
+
if (!redactionEnabled) return chunk;
|
|
2619
|
+
const prevTail = streamingTails.get(sessionId) ?? "";
|
|
2620
|
+
const combined = prevTail + chunk;
|
|
2621
|
+
const redacted = redactSecrets(combined);
|
|
2622
|
+
const prefix = SECRET_PREFIX_RE.exec(redacted);
|
|
2623
|
+
if (prefix && prefix.index + prefix[0].length === redacted.length && redacted.length - prefix.index <= MAX_STREAMING_TAIL) {
|
|
2624
|
+
streamingTails.set(sessionId, redacted.slice(prefix.index));
|
|
2625
|
+
return redacted.slice(0, prefix.index);
|
|
2626
|
+
}
|
|
2627
|
+
streamingTails.delete(sessionId);
|
|
2628
|
+
return redacted;
|
|
2629
|
+
}
|
|
2630
|
+
function flushStreamingRedaction(sessionId) {
|
|
2631
|
+
const tail = streamingTails.get(sessionId) ?? "";
|
|
2632
|
+
streamingTails.delete(sessionId);
|
|
2633
|
+
return redactionEnabled ? redactSecrets(tail) : tail;
|
|
2634
|
+
}
|
|
2635
|
+
var pendingQueue = [];
|
|
2636
|
+
var drainTimer = null;
|
|
2637
|
+
var drainWs = null;
|
|
2638
|
+
var droppedFrames = 0;
|
|
2639
|
+
var PRESSURE_HIGH = 0.75;
|
|
2640
|
+
var PRESSURE_LOW = 0.25;
|
|
2641
|
+
var pressureIsHigh = false;
|
|
2642
|
+
function getQueuePressure() {
|
|
2643
|
+
const level = pendingQueue.length / MAX_PENDING_QUEUE;
|
|
2644
|
+
if (level >= PRESSURE_HIGH) pressureIsHigh = true;
|
|
2645
|
+
else if (level < PRESSURE_LOW) pressureIsHigh = false;
|
|
2646
|
+
return { level, isHigh: pressureIsHigh };
|
|
2647
|
+
}
|
|
2648
|
+
function getDroppedFrameCount() {
|
|
2649
|
+
return droppedFrames;
|
|
2650
|
+
}
|
|
2651
|
+
function drainQueue() {
|
|
2652
|
+
if (!drainWs || drainWs.readyState !== import_ws.default.OPEN) {
|
|
2653
|
+
stopDrainTimer();
|
|
2654
|
+
return;
|
|
2655
|
+
}
|
|
2656
|
+
while (pendingQueue.length > 0 && drainWs.bufferedAmount < BACKPRESSURE_LOW_WATER) {
|
|
2657
|
+
const frame = pendingQueue.shift();
|
|
2658
|
+
drainWs.send(frame);
|
|
2659
|
+
}
|
|
2660
|
+
if (pendingQueue.length === 0) {
|
|
2661
|
+
stopDrainTimer();
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
function startDrainTimer(ws) {
|
|
2665
|
+
drainWs = ws;
|
|
2666
|
+
if (!drainTimer) {
|
|
2667
|
+
drainTimer = setInterval(drainQueue, DRAIN_INTERVAL_MS);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
function stopDrainTimer() {
|
|
2671
|
+
if (drainTimer) {
|
|
2672
|
+
clearInterval(drainTimer);
|
|
2673
|
+
drainTimer = null;
|
|
2674
|
+
}
|
|
2675
|
+
drainWs = null;
|
|
2676
|
+
}
|
|
2677
|
+
function sendToGroup(ws, group, data) {
|
|
2678
|
+
if (!group || ws.readyState !== import_ws.default.OPEN) return;
|
|
2679
|
+
const sanitized = sanitizePayload(data);
|
|
2680
|
+
const frame = JSON.stringify({
|
|
2681
|
+
type: "sendToGroup",
|
|
2682
|
+
group,
|
|
2683
|
+
dataType: "json",
|
|
2684
|
+
data: sanitized,
|
|
2685
|
+
noEcho: true
|
|
2686
|
+
});
|
|
2687
|
+
if (ws.bufferedAmount > BACKPRESSURE_HIGH_WATER) {
|
|
2688
|
+
if (pendingQueue.length >= MAX_PENDING_QUEUE) {
|
|
2689
|
+
pendingQueue.shift();
|
|
2690
|
+
droppedFrames++;
|
|
2691
|
+
if (droppedFrames % 100 === 1) {
|
|
2692
|
+
console.warn(`[rAgent] Backpressure: dropped ${droppedFrames} frames (queue full at ${MAX_PENDING_QUEUE})`);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
pendingQueue.push(frame);
|
|
2696
|
+
startDrainTimer(ws);
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
if (pendingQueue.length > 0) {
|
|
2700
|
+
pendingQueue.push(frame);
|
|
2701
|
+
drainWs = ws;
|
|
2702
|
+
drainQueue();
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
ws.send(frame);
|
|
2706
|
+
}
|
|
2707
|
+
function sanitizeValue(value) {
|
|
2708
|
+
if (typeof value === "string") {
|
|
2709
|
+
return redactSecrets(stripDangerousEscapes(sanitizeForJson(value)));
|
|
2710
|
+
}
|
|
2711
|
+
if (Array.isArray(value)) {
|
|
2712
|
+
return value.map((item) => sanitizeValue(item));
|
|
2713
|
+
}
|
|
2714
|
+
if (value !== null && typeof value === "object") {
|
|
2715
|
+
return sanitizePayload(value);
|
|
2716
|
+
}
|
|
2717
|
+
return value;
|
|
2718
|
+
}
|
|
2719
|
+
function sanitizePayload(obj) {
|
|
2720
|
+
const result = {};
|
|
2721
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2722
|
+
result[key] = sanitizeValue(value);
|
|
2723
|
+
}
|
|
2724
|
+
return result;
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2565
2727
|
// src/transcript-watcher.ts
|
|
2566
2728
|
var log7 = createLogger("transcript-watcher");
|
|
2567
2729
|
var cachedTicksPerSecond = null;
|
|
@@ -3056,7 +3218,7 @@ function getNewestPath(paths, options) {
|
|
|
3056
3218
|
} catch {
|
|
3057
3219
|
return null;
|
|
3058
3220
|
}
|
|
3059
|
-
}).filter((entry) => entry !== null).filter((entry) => options?.minMtimeMs === void 0 || entry.mtimeMs >= options.minMtimeMs).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
3221
|
+
}).filter((entry) => entry !== null).filter((entry) => options?.minMtimeMs === void 0 || entry.mtimeMs >= options.minMtimeMs).filter((entry) => !options?.excludePaths?.has(entry.target)).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
3060
3222
|
return ranked[0]?.target ?? null;
|
|
3061
3223
|
}
|
|
3062
3224
|
function discoverTranscriptForPid(pid, agentType) {
|
|
@@ -3204,10 +3366,10 @@ function discoverViaProc(rootPid, agentType) {
|
|
|
3204
3366
|
}
|
|
3205
3367
|
return getNewestPath(candidates);
|
|
3206
3368
|
}
|
|
3207
|
-
function discoverViaProcessCwd(pid, minMtimeMs) {
|
|
3369
|
+
function discoverViaProcessCwd(pid, minMtimeMs, excludePaths) {
|
|
3208
3370
|
try {
|
|
3209
3371
|
const processCwd = fs2.readlinkSync(`/proc/${pid}/cwd`);
|
|
3210
|
-
return processCwd ? discoverViaCwd(processCwd, pid, minMtimeMs) : null;
|
|
3372
|
+
return processCwd ? discoverViaCwd(processCwd, pid, minMtimeMs, excludePaths) : null;
|
|
3211
3373
|
} catch {
|
|
3212
3374
|
return null;
|
|
3213
3375
|
}
|
|
@@ -3235,7 +3397,7 @@ function resolveUserHome(pid) {
|
|
|
3235
3397
|
return null;
|
|
3236
3398
|
}
|
|
3237
3399
|
}
|
|
3238
|
-
function discoverCodexTranscriptFromHome(pid, minMtimeMs) {
|
|
3400
|
+
function discoverCodexTranscriptFromHome(pid, minMtimeMs, excludePaths) {
|
|
3239
3401
|
const userHome = resolveUserHome(pid);
|
|
3240
3402
|
if (!userHome) return null;
|
|
3241
3403
|
const sessionsDir = path2.join(userHome, ".codex", "sessions");
|
|
@@ -3262,9 +3424,9 @@ function discoverCodexTranscriptFromHome(pid, minMtimeMs) {
|
|
|
3262
3424
|
}
|
|
3263
3425
|
}
|
|
3264
3426
|
}
|
|
3265
|
-
return getNewestPath(matches, { minMtimeMs });
|
|
3427
|
+
return getNewestPath(matches, { minMtimeMs, excludePaths });
|
|
3266
3428
|
}
|
|
3267
|
-
function discoverGeminiTranscriptFromHome(pid) {
|
|
3429
|
+
function discoverGeminiTranscriptFromHome(pid, minMtimeMs, excludePaths) {
|
|
3268
3430
|
const userHome = resolveUserHome(pid);
|
|
3269
3431
|
if (!userHome) return null;
|
|
3270
3432
|
const tmpDir = path2.join(userHome, ".gemini", "tmp");
|
|
@@ -3291,9 +3453,9 @@ function discoverGeminiTranscriptFromHome(pid) {
|
|
|
3291
3453
|
}
|
|
3292
3454
|
}
|
|
3293
3455
|
}
|
|
3294
|
-
return getNewestPath(matches);
|
|
3456
|
+
return getNewestPath(matches, { minMtimeMs, excludePaths });
|
|
3295
3457
|
}
|
|
3296
|
-
function discoverAntigravityTranscriptFromHome(pid, minMtimeMs) {
|
|
3458
|
+
function discoverAntigravityTranscriptFromHome(pid, minMtimeMs, excludePaths) {
|
|
3297
3459
|
const userHome = resolveUserHome(pid);
|
|
3298
3460
|
if (!userHome) return null;
|
|
3299
3461
|
const brainDir = path2.join(userHome, ".gemini", "antigravity-cli", "brain");
|
|
@@ -3311,9 +3473,9 @@ function discoverAntigravityTranscriptFromHome(pid, minMtimeMs) {
|
|
|
3311
3473
|
}
|
|
3312
3474
|
} catch {
|
|
3313
3475
|
}
|
|
3314
|
-
return getNewestPath(matches, { minMtimeMs });
|
|
3476
|
+
return getNewestPath(matches, { minMtimeMs, excludePaths });
|
|
3315
3477
|
}
|
|
3316
|
-
function discoverAntigravityViaCwd(paneCwd, pid) {
|
|
3478
|
+
function discoverAntigravityViaCwd(paneCwd, pid, excludePaths) {
|
|
3317
3479
|
const userHome = resolveUserHome(pid);
|
|
3318
3480
|
if (!userHome) return null;
|
|
3319
3481
|
const historyFile = path2.join(userHome, ".gemini", "antigravity-cli", "history.jsonl");
|
|
@@ -3346,7 +3508,7 @@ function discoverAntigravityViaCwd(paneCwd, pid) {
|
|
|
3346
3508
|
"logs",
|
|
3347
3509
|
"transcript.jsonl"
|
|
3348
3510
|
);
|
|
3349
|
-
if (fs2.existsSync(transcriptPath)) {
|
|
3511
|
+
if (fs2.existsSync(transcriptPath) && !excludePaths?.has(transcriptPath)) {
|
|
3350
3512
|
return transcriptPath;
|
|
3351
3513
|
}
|
|
3352
3514
|
}
|
|
@@ -3359,7 +3521,7 @@ function discoverAntigravityViaCwd(paneCwd, pid) {
|
|
|
3359
3521
|
}
|
|
3360
3522
|
return null;
|
|
3361
3523
|
}
|
|
3362
|
-
function discoverViaCwd(paneCwd, pid, minMtimeMs) {
|
|
3524
|
+
function discoverViaCwd(paneCwd, pid, minMtimeMs, excludePaths) {
|
|
3363
3525
|
const userHome = resolveUserHome(pid);
|
|
3364
3526
|
if (!userHome) return null;
|
|
3365
3527
|
const claudeProjectsDir = path2.join(userHome, ".claude", "projects");
|
|
@@ -3373,60 +3535,67 @@ function discoverViaCwd(paneCwd, pid, minMtimeMs) {
|
|
|
3373
3535
|
if (projectDirs.length === 0) return null;
|
|
3374
3536
|
try {
|
|
3375
3537
|
const jsonlFiles = projectDirs.flatMap((projectDir) => fs2.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).map((f) => path2.join(projectDir, f)));
|
|
3376
|
-
return getNewestPath(jsonlFiles, { minMtimeMs });
|
|
3538
|
+
return getNewestPath(jsonlFiles, { minMtimeMs, excludePaths });
|
|
3377
3539
|
} catch {
|
|
3378
3540
|
return null;
|
|
3379
3541
|
}
|
|
3380
3542
|
}
|
|
3381
|
-
function discoverTranscriptFile(sessionId, agentType, forceRefresh = false) {
|
|
3543
|
+
function discoverTranscriptFile(sessionId, agentType, forceRefresh = false, excludePaths) {
|
|
3382
3544
|
const now2 = Date.now();
|
|
3383
3545
|
const cacheKey = `${sessionId}:${agentType || ""}`;
|
|
3384
|
-
|
|
3546
|
+
const exclusionScoped = Boolean(excludePaths && excludePaths.size > 0);
|
|
3547
|
+
if (!forceRefresh && !exclusionScoped) {
|
|
3385
3548
|
const cached = transcriptDiscoveryCache.get(cacheKey);
|
|
3386
3549
|
if (cached && cached.expiresAt > now2) {
|
|
3387
3550
|
return cached.value;
|
|
3388
3551
|
}
|
|
3389
3552
|
}
|
|
3390
|
-
const result = discoverTranscriptFileImpl(sessionId, agentType);
|
|
3553
|
+
const { path: result, viaProc } = discoverTranscriptFileImpl(sessionId, agentType, excludePaths);
|
|
3391
3554
|
const isProcessSession = sessionId.startsWith("process:");
|
|
3392
|
-
const ttl = result ? isProcessSession ? 3600 * 1e3 : 5e3 : 5e3;
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3555
|
+
const ttl = result ? isProcessSession && viaProc ? 3600 * 1e3 : 5e3 : 5e3;
|
|
3556
|
+
if (!exclusionScoped) {
|
|
3557
|
+
transcriptDiscoveryCache.set(cacheKey, {
|
|
3558
|
+
value: result,
|
|
3559
|
+
expiresAt: Date.now() + ttl
|
|
3560
|
+
});
|
|
3561
|
+
}
|
|
3397
3562
|
return result;
|
|
3398
3563
|
}
|
|
3399
|
-
function
|
|
3564
|
+
function discoverTranscriptFileDetailed(sessionId, agentType, excludePaths) {
|
|
3565
|
+
return discoverTranscriptFileImpl(sessionId, agentType, excludePaths);
|
|
3566
|
+
}
|
|
3567
|
+
function discoverTranscriptFileImpl(sessionId, agentType, excludePaths) {
|
|
3400
3568
|
const processPid = parseProcessPid(sessionId);
|
|
3401
3569
|
if (processPid) {
|
|
3402
3570
|
const t0 = performance.now();
|
|
3403
3571
|
const procResult = discoverViaProc(processPid, agentType);
|
|
3404
3572
|
if (procResult) {
|
|
3405
3573
|
console.log(`[DISCOVER] discoverViaProc found file for PID ${processPid} in ${(performance.now() - t0).toFixed(2)} ms`);
|
|
3406
|
-
return procResult;
|
|
3574
|
+
return { path: procResult, viaProc: true };
|
|
3407
3575
|
}
|
|
3408
3576
|
if (agentType === "Claude Code") {
|
|
3409
3577
|
const t1 = performance.now();
|
|
3410
3578
|
const startMs = getProcessStartEpochMs(processPid);
|
|
3411
|
-
const cwdResult = discoverViaProcessCwd(processPid, startMs ? startMs - 6e4 : void 0);
|
|
3579
|
+
const cwdResult = discoverViaProcessCwd(processPid, startMs ? startMs - 6e4 : void 0, excludePaths);
|
|
3412
3580
|
console.log(`[DISCOVER] Claude Code discovery for PID ${processPid} took ${(performance.now() - t1).toFixed(2)} ms`);
|
|
3413
|
-
if (cwdResult) return cwdResult;
|
|
3581
|
+
if (cwdResult) return { path: cwdResult, viaProc: false };
|
|
3414
3582
|
}
|
|
3415
3583
|
if (agentType === "Codex CLI") {
|
|
3416
3584
|
const t1 = performance.now();
|
|
3417
3585
|
const startMs = getProcessStartEpochMs(processPid);
|
|
3418
3586
|
const command = getProcessCommand(processPid);
|
|
3419
3587
|
if (commandMatchesAgent(command, agentType)) {
|
|
3420
|
-
const codexResult = discoverCodexTranscriptFromHome(processPid, startMs ? startMs - 6e4 : void 0);
|
|
3588
|
+
const codexResult = discoverCodexTranscriptFromHome(processPid, startMs ? startMs - 6e4 : void 0, excludePaths);
|
|
3421
3589
|
console.log(`[DISCOVER] Codex CLI discovery for PID ${processPid} took ${(performance.now() - t1).toFixed(2)} ms`);
|
|
3422
|
-
if (codexResult) return codexResult;
|
|
3590
|
+
if (codexResult) return { path: codexResult, viaProc: false };
|
|
3423
3591
|
}
|
|
3424
3592
|
}
|
|
3425
3593
|
if (agentType === "Gemini CLI") {
|
|
3426
3594
|
const t1 = performance.now();
|
|
3427
|
-
const
|
|
3595
|
+
const startMs = getProcessStartEpochMs(processPid);
|
|
3596
|
+
const geminiResult = discoverGeminiTranscriptFromHome(processPid, startMs ? startMs - 6e4 : void 0, excludePaths);
|
|
3428
3597
|
console.log(`[DISCOVER] Gemini CLI discovery for PID ${processPid} took ${(performance.now() - t1).toFixed(2)} ms`);
|
|
3429
|
-
if (geminiResult) return geminiResult;
|
|
3598
|
+
if (geminiResult) return { path: geminiResult, viaProc: false };
|
|
3430
3599
|
}
|
|
3431
3600
|
if (agentType === "Antigravity CLI") {
|
|
3432
3601
|
const t1 = performance.now();
|
|
@@ -3434,23 +3603,23 @@ function discoverTranscriptFileImpl(sessionId, agentType) {
|
|
|
3434
3603
|
try {
|
|
3435
3604
|
const processCwd = fs2.readlinkSync(`/proc/${processPid}/cwd`);
|
|
3436
3605
|
if (processCwd) {
|
|
3437
|
-
const cwdResult = discoverAntigravityViaCwd(processCwd, processPid);
|
|
3606
|
+
const cwdResult = discoverAntigravityViaCwd(processCwd, processPid, excludePaths);
|
|
3438
3607
|
if (cwdResult) {
|
|
3439
3608
|
console.log(`[DISCOVER] Antigravity CLI discovery (CWD path) for PID ${processPid} took ${(performance.now() - t1).toFixed(2)} ms`);
|
|
3440
|
-
return cwdResult;
|
|
3609
|
+
return { path: cwdResult, viaProc: false };
|
|
3441
3610
|
}
|
|
3442
3611
|
}
|
|
3443
3612
|
} catch {
|
|
3444
3613
|
}
|
|
3445
|
-
const antigravityResult = discoverAntigravityTranscriptFromHome(processPid, startMs ? startMs - 6e4 : void 0);
|
|
3614
|
+
const antigravityResult = discoverAntigravityTranscriptFromHome(processPid, startMs ? startMs - 6e4 : void 0, excludePaths);
|
|
3446
3615
|
console.log(`[DISCOVER] Antigravity CLI discovery (home path) for PID ${processPid} took ${(performance.now() - t1).toFixed(2)} ms`);
|
|
3447
|
-
if (antigravityResult) return antigravityResult;
|
|
3616
|
+
if (antigravityResult) return { path: antigravityResult, viaProc: false };
|
|
3448
3617
|
}
|
|
3449
|
-
return null;
|
|
3618
|
+
return { path: null, viaProc: false };
|
|
3450
3619
|
}
|
|
3451
3620
|
if (sessionId.startsWith("tmux:")) {
|
|
3452
3621
|
const paneTarget = sessionId.slice("tmux:".length);
|
|
3453
|
-
if (!paneTarget) return null;
|
|
3622
|
+
if (!paneTarget) return { path: null, viaProc: false };
|
|
3454
3623
|
const cleanEnv = { ...process.env };
|
|
3455
3624
|
delete cleanEnv.TMUX;
|
|
3456
3625
|
delete cleanEnv.TMUX_PANE;
|
|
@@ -3465,7 +3634,7 @@ function discoverTranscriptFileImpl(sessionId, agentType) {
|
|
|
3465
3634
|
if (parsedPanePid > 0) {
|
|
3466
3635
|
panePid = parsedPanePid;
|
|
3467
3636
|
const procResult = discoverViaProc(panePid, agentType);
|
|
3468
|
-
if (procResult) return procResult;
|
|
3637
|
+
if (procResult) return { path: procResult, viaProc: true };
|
|
3469
3638
|
}
|
|
3470
3639
|
} catch {
|
|
3471
3640
|
}
|
|
@@ -3476,9 +3645,10 @@ function discoverTranscriptFileImpl(sessionId, agentType) {
|
|
|
3476
3645
|
const cwdResult = discoverViaCwd(
|
|
3477
3646
|
info.cwd,
|
|
3478
3647
|
info.pid,
|
|
3479
|
-
info.startEpochMs ? info.startEpochMs - 6e4 : void 0
|
|
3648
|
+
info.startEpochMs ? info.startEpochMs - 6e4 : void 0,
|
|
3649
|
+
excludePaths
|
|
3480
3650
|
);
|
|
3481
|
-
if (cwdResult) return cwdResult;
|
|
3651
|
+
if (cwdResult) return { path: cwdResult, viaProc: false };
|
|
3482
3652
|
}
|
|
3483
3653
|
try {
|
|
3484
3654
|
const paneCwd = (0, import_child_process2.execFileSync)(
|
|
@@ -3486,7 +3656,10 @@ function discoverTranscriptFileImpl(sessionId, agentType) {
|
|
|
3486
3656
|
["display-message", "-t", paneTarget, "-p", "#{pane_current_path}"],
|
|
3487
3657
|
{ env: cleanEnv, timeout: 5e3, encoding: "utf-8" }
|
|
3488
3658
|
).trim();
|
|
3489
|
-
if (paneCwd)
|
|
3659
|
+
if (paneCwd) {
|
|
3660
|
+
const cwdResult = discoverViaCwd(paneCwd, panePid ?? void 0, void 0, excludePaths);
|
|
3661
|
+
if (cwdResult) return { path: cwdResult, viaProc: false };
|
|
3662
|
+
}
|
|
3490
3663
|
} catch {
|
|
3491
3664
|
}
|
|
3492
3665
|
}
|
|
@@ -3495,20 +3668,23 @@ function discoverTranscriptFileImpl(sessionId, agentType) {
|
|
|
3495
3668
|
const newestForAgent = getNewestPath(
|
|
3496
3669
|
agentInfos.map((info) => discoverCodexTranscriptFromHome(
|
|
3497
3670
|
info.pid,
|
|
3498
|
-
info.startEpochMs ? info.startEpochMs - 6e4 : void 0
|
|
3499
|
-
|
|
3671
|
+
info.startEpochMs ? info.startEpochMs - 6e4 : void 0,
|
|
3672
|
+
excludePaths
|
|
3673
|
+
)).filter((value) => Boolean(value)),
|
|
3674
|
+
{ excludePaths }
|
|
3500
3675
|
);
|
|
3501
|
-
if (newestForAgent) return newestForAgent;
|
|
3676
|
+
if (newestForAgent) return { path: newestForAgent, viaProc: false };
|
|
3502
3677
|
}
|
|
3503
3678
|
if (agentType === "Gemini CLI") {
|
|
3504
|
-
|
|
3679
|
+
const geminiResult = discoverGeminiTranscriptFromHome(panePid ?? void 0, void 0, excludePaths);
|
|
3680
|
+
if (geminiResult) return { path: geminiResult, viaProc: false };
|
|
3505
3681
|
}
|
|
3506
3682
|
if (agentType === "Antigravity CLI") {
|
|
3507
3683
|
const agentInfos = panePid ? findAgentProcessInfos(panePid, agentType) : [];
|
|
3508
3684
|
for (const info of agentInfos) {
|
|
3509
3685
|
if (info.cwd) {
|
|
3510
|
-
const cwdResult = discoverAntigravityViaCwd(info.cwd, info.pid);
|
|
3511
|
-
if (cwdResult) return cwdResult;
|
|
3686
|
+
const cwdResult = discoverAntigravityViaCwd(info.cwd, info.pid, excludePaths);
|
|
3687
|
+
if (cwdResult) return { path: cwdResult, viaProc: false };
|
|
3512
3688
|
}
|
|
3513
3689
|
}
|
|
3514
3690
|
try {
|
|
@@ -3518,28 +3694,31 @@ function discoverTranscriptFileImpl(sessionId, agentType) {
|
|
|
3518
3694
|
{ env: cleanEnv, timeout: 5e3, encoding: "utf-8" }
|
|
3519
3695
|
).trim();
|
|
3520
3696
|
if (paneCwd) {
|
|
3521
|
-
const cwdResult = discoverAntigravityViaCwd(paneCwd, panePid ?? void 0);
|
|
3522
|
-
if (cwdResult) return cwdResult;
|
|
3697
|
+
const cwdResult = discoverAntigravityViaCwd(paneCwd, panePid ?? void 0, excludePaths);
|
|
3698
|
+
if (cwdResult) return { path: cwdResult, viaProc: false };
|
|
3523
3699
|
}
|
|
3524
3700
|
} catch {
|
|
3525
3701
|
}
|
|
3526
3702
|
const newestForAgent = getNewestPath(
|
|
3527
3703
|
agentInfos.map((info) => discoverAntigravityTranscriptFromHome(
|
|
3528
3704
|
info.pid,
|
|
3529
|
-
info.startEpochMs ? info.startEpochMs - 6e4 : void 0
|
|
3530
|
-
|
|
3705
|
+
info.startEpochMs ? info.startEpochMs - 6e4 : void 0,
|
|
3706
|
+
excludePaths
|
|
3707
|
+
)).filter((value) => Boolean(value)),
|
|
3708
|
+
{ excludePaths }
|
|
3531
3709
|
);
|
|
3532
|
-
if (newestForAgent) return newestForAgent;
|
|
3710
|
+
if (newestForAgent) return { path: newestForAgent, viaProc: false };
|
|
3533
3711
|
}
|
|
3534
|
-
return null;
|
|
3712
|
+
return { path: null, viaProc: false };
|
|
3535
3713
|
}
|
|
3536
|
-
return null;
|
|
3714
|
+
return { path: null, viaProc: false };
|
|
3537
3715
|
}
|
|
3538
3716
|
var MAX_PARTIAL_BUFFER = 256 * 1024;
|
|
3539
3717
|
var MAX_REPLAY_TURNS = 1e3;
|
|
3540
3718
|
var POLL_INTERVAL_MS = 800;
|
|
3541
3719
|
var DOC_READ_DEBOUNCE_MS = 200;
|
|
3542
3720
|
var REDISCOVERY_INTERVAL_MS = 5e3;
|
|
3721
|
+
var MARKDOWN_RESYNC_DRAIN_MS = 300;
|
|
3543
3722
|
var ENABLE_RETRY_DELAYS_MS = [1e3, 2e3, 5e3];
|
|
3544
3723
|
var TranscriptWatcher = class {
|
|
3545
3724
|
filePath;
|
|
@@ -3662,6 +3841,9 @@ var TranscriptWatcher = class {
|
|
|
3662
3841
|
return;
|
|
3663
3842
|
}
|
|
3664
3843
|
const ops = this.parserV2.parseDocument(content);
|
|
3844
|
+
if (ops.length === 0 && this.snapshot.turnOrder.length > 0) {
|
|
3845
|
+
return;
|
|
3846
|
+
}
|
|
3665
3847
|
let nextSnapshot = createEmptySnapshot(this.snapshot.sessionId);
|
|
3666
3848
|
if (ops.length > 0) {
|
|
3667
3849
|
nextSnapshot = applyOps(nextSnapshot, ops);
|
|
@@ -3752,6 +3934,12 @@ var TranscriptWatcher = class {
|
|
|
3752
3934
|
}
|
|
3753
3935
|
this.documentFingerprint = fingerprint;
|
|
3754
3936
|
const parsedTurns = this.parser.parseDocument?.(content) ?? [];
|
|
3937
|
+
const v2Ops = this.parserV2?.parseDocument?.(content) ?? [];
|
|
3938
|
+
const parsedNothing = parsedTurns.length === 0 && v2Ops.length === 0;
|
|
3939
|
+
const haveContent = this.turns.length > 0 || this.snapshot.turnOrder.length > 0;
|
|
3940
|
+
if (parsedNothing && haveContent) {
|
|
3941
|
+
return;
|
|
3942
|
+
}
|
|
3755
3943
|
this.seq++;
|
|
3756
3944
|
this.turns = parsedTurns.slice(-MAX_REPLAY_TURNS).map((turn) => ({
|
|
3757
3945
|
turnId: turn.turnId,
|
|
@@ -3762,10 +3950,9 @@ var TranscriptWatcher = class {
|
|
|
3762
3950
|
}));
|
|
3763
3951
|
this.callbacks.onTurnsSnapshot?.(this.turns, this.seq);
|
|
3764
3952
|
if (this.parserV2?.parseDocument && this.callbacks.onSnapshot) {
|
|
3765
|
-
const ops = this.parserV2.parseDocument(content);
|
|
3766
3953
|
let nextSnapshot = createEmptySnapshot(this.snapshot.sessionId);
|
|
3767
|
-
if (
|
|
3768
|
-
nextSnapshot = applyOps(nextSnapshot,
|
|
3954
|
+
if (v2Ops.length > 0) {
|
|
3955
|
+
nextSnapshot = applyOps(nextSnapshot, v2Ops);
|
|
3769
3956
|
}
|
|
3770
3957
|
this.snapshot = trimSnapshot(nextSnapshot);
|
|
3771
3958
|
this.callbacks.onSnapshot(this.snapshot, this.seq);
|
|
@@ -3825,6 +4012,9 @@ function getParser(agentType) {
|
|
|
3825
4012
|
var TranscriptWatcherManager = class {
|
|
3826
4013
|
active = /* @__PURE__ */ new Map();
|
|
3827
4014
|
rediscoveryTimers = /* @__PURE__ */ new Map();
|
|
4015
|
+
/** #542: sessions awaiting a markdown snapshot re-emit after a frame drop. */
|
|
4016
|
+
pendingMarkdownResync = /* @__PURE__ */ new Set();
|
|
4017
|
+
markdownResyncTimer;
|
|
3828
4018
|
/** Pending retry timer per session for #483 (no_transcript / watch_failed). */
|
|
3829
4019
|
enableRetryTimers = /* @__PURE__ */ new Map();
|
|
3830
4020
|
/** Index into ENABLE_RETRY_DELAYS_MS for the next scheduled attempt. */
|
|
@@ -3865,7 +4055,11 @@ var TranscriptWatcherManager = class {
|
|
|
3865
4055
|
const existing = this.active.get(sessionId);
|
|
3866
4056
|
let replacingExisting = false;
|
|
3867
4057
|
if (existing) {
|
|
3868
|
-
const newPath =
|
|
4058
|
+
const newPath = discoverTranscriptFileDetailed(
|
|
4059
|
+
sessionId,
|
|
4060
|
+
agentType,
|
|
4061
|
+
this.ownedPathsExcept(sessionId)
|
|
4062
|
+
).path;
|
|
3869
4063
|
const agentChanged = existing.agentType !== requestedAgentType;
|
|
3870
4064
|
const pathChanged = Boolean(newPath && newPath !== existing.filePath);
|
|
3871
4065
|
const existingPathGone = !fs2.existsSync(existing.filePath);
|
|
@@ -3890,7 +4084,11 @@ var TranscriptWatcherManager = class {
|
|
|
3890
4084
|
this.cancelEnableRetry(sessionId);
|
|
3891
4085
|
return { ok: false, reason: "unsupported_agent" };
|
|
3892
4086
|
}
|
|
3893
|
-
const filePath =
|
|
4087
|
+
const filePath = discoverTranscriptFileDetailed(
|
|
4088
|
+
sessionId,
|
|
4089
|
+
agentType,
|
|
4090
|
+
this.ownedPathsExcept(sessionId)
|
|
4091
|
+
).path;
|
|
3894
4092
|
if (!filePath) {
|
|
3895
4093
|
log7.info("no transcript file found", { sessionId });
|
|
3896
4094
|
this.armEnableRetry(sessionId, agentType);
|
|
@@ -3990,6 +4188,22 @@ var TranscriptWatcherManager = class {
|
|
|
3990
4188
|
this.sendV2SnapshotFn(sessionId, createEmptySnapshot(sessionId), 0);
|
|
3991
4189
|
}
|
|
3992
4190
|
}
|
|
4191
|
+
/**
|
|
4192
|
+
* Paths currently bound to OTHER live sessions. Passed to discovery so two
|
|
4193
|
+
* sessions in one folder (or two same-tool sessions) never resolve to the
|
|
4194
|
+
* same transcript via newest-mtime. The session's own file is never excluded
|
|
4195
|
+
* (so it can keep/rebind it); /proc fd discovery ignores this set entirely.
|
|
4196
|
+
* #540.
|
|
4197
|
+
*/
|
|
4198
|
+
ownedPathsExcept(sessionId) {
|
|
4199
|
+
const owned = /* @__PURE__ */ new Set();
|
|
4200
|
+
for (const [sid, session] of this.active) {
|
|
4201
|
+
if (sid !== sessionId && session.filePath) {
|
|
4202
|
+
owned.add(session.filePath);
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
return owned;
|
|
4206
|
+
}
|
|
3993
4207
|
/** Disable markdown streaming for a session. */
|
|
3994
4208
|
disableMarkdown(sessionId) {
|
|
3995
4209
|
this.cancelEnableRetry(sessionId);
|
|
@@ -4005,6 +4219,7 @@ var TranscriptWatcherManager = class {
|
|
|
4005
4219
|
}
|
|
4006
4220
|
this.active.delete(sessionId);
|
|
4007
4221
|
this.stopRediscovery(sessionId);
|
|
4222
|
+
this.pendingMarkdownResync.delete(sessionId);
|
|
4008
4223
|
log7.info("stopped watching transcript", { sessionId });
|
|
4009
4224
|
}
|
|
4010
4225
|
/** Periodically check if the transcript file has changed (new conversation). */
|
|
@@ -4016,7 +4231,11 @@ var TranscriptWatcherManager = class {
|
|
|
4016
4231
|
this.stopRediscovery(sessionId);
|
|
4017
4232
|
return;
|
|
4018
4233
|
}
|
|
4019
|
-
const newPath =
|
|
4234
|
+
const { path: newPath } = discoverTranscriptFileDetailed(
|
|
4235
|
+
sessionId,
|
|
4236
|
+
agentType,
|
|
4237
|
+
this.ownedPathsExcept(sessionId)
|
|
4238
|
+
);
|
|
4020
4239
|
if (!newPath || newPath === session.filePath) return;
|
|
4021
4240
|
log7.info("transcript file changed", { sessionId, newPath });
|
|
4022
4241
|
session.watcher.stop();
|
|
@@ -4078,8 +4297,62 @@ var TranscriptWatcherManager = class {
|
|
|
4078
4297
|
this.sendV2SnapshotFn(sessionId, snapshot, session.watcher.currentSeq);
|
|
4079
4298
|
}
|
|
4080
4299
|
}
|
|
4300
|
+
/**
|
|
4301
|
+
* #542: re-emit markdown snapshots after the WS dropped frames under
|
|
4302
|
+
* backpressure. The large V2 snapshot is sent as a single un-chunked frame
|
|
4303
|
+
* and is the prime drop victim, but — unlike tmux-pipe terminal streams,
|
|
4304
|
+
* which resync via capture-pane — the markdown channel had no recovery path,
|
|
4305
|
+
* so a dropped snapshot left the read view permanently partial until a
|
|
4306
|
+
* reconnect. Re-emit the V2 snapshot for every session that currently holds
|
|
4307
|
+
* content, draining one per tick so the (large) snapshots don't immediately
|
|
4308
|
+
* re-saturate the queue.
|
|
4309
|
+
*/
|
|
4310
|
+
resyncMarkdownAfterDrop() {
|
|
4311
|
+
if (!this.sendV2SnapshotFn) return;
|
|
4312
|
+
let queued = false;
|
|
4313
|
+
for (const [sessionId, session] of this.active) {
|
|
4314
|
+
if (session.watcher.getSnapshot().turnOrder.length > 0) {
|
|
4315
|
+
this.pendingMarkdownResync.add(sessionId);
|
|
4316
|
+
queued = true;
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
if (!queued || this.markdownResyncTimer) return;
|
|
4320
|
+
this.markdownResyncTimer = setInterval(() => {
|
|
4321
|
+
if (this.pendingMarkdownResync.size === 0) {
|
|
4322
|
+
this.stopMarkdownResync();
|
|
4323
|
+
return;
|
|
4324
|
+
}
|
|
4325
|
+
if (getQueuePressure().isHigh) return;
|
|
4326
|
+
const next = this.pendingMarkdownResync.values().next();
|
|
4327
|
+
if (next.done) {
|
|
4328
|
+
this.stopMarkdownResync();
|
|
4329
|
+
return;
|
|
4330
|
+
}
|
|
4331
|
+
const sessionId = next.value;
|
|
4332
|
+
this.pendingMarkdownResync.delete(sessionId);
|
|
4333
|
+
const session = this.active.get(sessionId);
|
|
4334
|
+
if (session && this.sendV2SnapshotFn) {
|
|
4335
|
+
this.sendV2SnapshotFn(
|
|
4336
|
+
sessionId,
|
|
4337
|
+
session.watcher.getSnapshot(),
|
|
4338
|
+
session.watcher.currentSeq
|
|
4339
|
+
);
|
|
4340
|
+
}
|
|
4341
|
+
}, MARKDOWN_RESYNC_DRAIN_MS);
|
|
4342
|
+
if (typeof this.markdownResyncTimer.unref === "function") {
|
|
4343
|
+
this.markdownResyncTimer.unref();
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
stopMarkdownResync() {
|
|
4347
|
+
if (this.markdownResyncTimer) {
|
|
4348
|
+
clearInterval(this.markdownResyncTimer);
|
|
4349
|
+
this.markdownResyncTimer = void 0;
|
|
4350
|
+
}
|
|
4351
|
+
this.pendingMarkdownResync.clear();
|
|
4352
|
+
}
|
|
4081
4353
|
/** Stop all watchers. */
|
|
4082
4354
|
stopAll() {
|
|
4355
|
+
this.stopMarkdownResync();
|
|
4083
4356
|
for (const [sessionId, session] of this.active) {
|
|
4084
4357
|
session.watcher.stop();
|
|
4085
4358
|
this.stopRediscovery(sessionId);
|
|
@@ -10575,155 +10848,6 @@ var OutputBuffer = class {
|
|
|
10575
10848
|
}
|
|
10576
10849
|
};
|
|
10577
10850
|
|
|
10578
|
-
// src/websocket.ts
|
|
10579
|
-
var import_ws = __toESM(require("ws"));
|
|
10580
|
-
var BACKPRESSURE_HIGH_WATER = 256 * 1024;
|
|
10581
|
-
var BACKPRESSURE_LOW_WATER = 64 * 1024;
|
|
10582
|
-
var MAX_PENDING_QUEUE = 500;
|
|
10583
|
-
var DRAIN_INTERVAL_MS = 50;
|
|
10584
|
-
function sanitizeForJson(str) {
|
|
10585
|
-
return str.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
|
|
10586
|
-
}
|
|
10587
|
-
var DANGEROUS_OSC_RE = /\x1b\](?:52|7|8);[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
10588
|
-
function stripDangerousEscapes(str) {
|
|
10589
|
-
return str.replace(DANGEROUS_OSC_RE, "");
|
|
10590
|
-
}
|
|
10591
|
-
var SECRET_PATTERNS = [
|
|
10592
|
-
/AKIA[0-9A-Z]{16}/g,
|
|
10593
|
-
// AWS access key
|
|
10594
|
-
/gh[ps]_[A-Za-z0-9_]{36,}/g,
|
|
10595
|
-
// GitHub token
|
|
10596
|
-
/sk_(?:live|test)_[A-Za-z0-9]{24,}/g,
|
|
10597
|
-
// Stripe secret key
|
|
10598
|
-
/eyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g
|
|
10599
|
-
// JWT
|
|
10600
|
-
];
|
|
10601
|
-
var redactionEnabled = true;
|
|
10602
|
-
function setRedactionEnabled(enabled) {
|
|
10603
|
-
redactionEnabled = enabled;
|
|
10604
|
-
}
|
|
10605
|
-
function redactSecrets(str) {
|
|
10606
|
-
if (!redactionEnabled) return str;
|
|
10607
|
-
let result = str;
|
|
10608
|
-
for (const pattern of SECRET_PATTERNS) {
|
|
10609
|
-
pattern.lastIndex = 0;
|
|
10610
|
-
result = result.replace(pattern, "[REDACTED]");
|
|
10611
|
-
}
|
|
10612
|
-
return result;
|
|
10613
|
-
}
|
|
10614
|
-
var streamingTails = /* @__PURE__ */ new Map();
|
|
10615
|
-
var MAX_STREAMING_TAIL = 1024;
|
|
10616
|
-
var SECRET_PREFIX_RE = /(?:AKIA[0-9A-Z]*|gh[ps]_[A-Za-z0-9_]*|sk_(?:live|test)_[A-Za-z0-9]*|eyJ[A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]*){0,2})$/;
|
|
10617
|
-
function redactStreamingChunk(sessionId, chunk) {
|
|
10618
|
-
if (!redactionEnabled) return chunk;
|
|
10619
|
-
const prevTail = streamingTails.get(sessionId) ?? "";
|
|
10620
|
-
const combined = prevTail + chunk;
|
|
10621
|
-
const redacted = redactSecrets(combined);
|
|
10622
|
-
const prefix = SECRET_PREFIX_RE.exec(redacted);
|
|
10623
|
-
if (prefix && prefix.index + prefix[0].length === redacted.length && redacted.length - prefix.index <= MAX_STREAMING_TAIL) {
|
|
10624
|
-
streamingTails.set(sessionId, redacted.slice(prefix.index));
|
|
10625
|
-
return redacted.slice(0, prefix.index);
|
|
10626
|
-
}
|
|
10627
|
-
streamingTails.delete(sessionId);
|
|
10628
|
-
return redacted;
|
|
10629
|
-
}
|
|
10630
|
-
function flushStreamingRedaction(sessionId) {
|
|
10631
|
-
const tail = streamingTails.get(sessionId) ?? "";
|
|
10632
|
-
streamingTails.delete(sessionId);
|
|
10633
|
-
return redactionEnabled ? redactSecrets(tail) : tail;
|
|
10634
|
-
}
|
|
10635
|
-
var pendingQueue = [];
|
|
10636
|
-
var drainTimer = null;
|
|
10637
|
-
var drainWs = null;
|
|
10638
|
-
var droppedFrames = 0;
|
|
10639
|
-
var PRESSURE_HIGH = 0.75;
|
|
10640
|
-
var PRESSURE_LOW = 0.25;
|
|
10641
|
-
var pressureIsHigh = false;
|
|
10642
|
-
function getQueuePressure() {
|
|
10643
|
-
const level = pendingQueue.length / MAX_PENDING_QUEUE;
|
|
10644
|
-
if (level >= PRESSURE_HIGH) pressureIsHigh = true;
|
|
10645
|
-
else if (level < PRESSURE_LOW) pressureIsHigh = false;
|
|
10646
|
-
return { level, isHigh: pressureIsHigh };
|
|
10647
|
-
}
|
|
10648
|
-
function getDroppedFrameCount() {
|
|
10649
|
-
return droppedFrames;
|
|
10650
|
-
}
|
|
10651
|
-
function drainQueue() {
|
|
10652
|
-
if (!drainWs || drainWs.readyState !== import_ws.default.OPEN) {
|
|
10653
|
-
stopDrainTimer();
|
|
10654
|
-
return;
|
|
10655
|
-
}
|
|
10656
|
-
while (pendingQueue.length > 0 && drainWs.bufferedAmount < BACKPRESSURE_LOW_WATER) {
|
|
10657
|
-
const frame = pendingQueue.shift();
|
|
10658
|
-
drainWs.send(frame);
|
|
10659
|
-
}
|
|
10660
|
-
if (pendingQueue.length === 0) {
|
|
10661
|
-
stopDrainTimer();
|
|
10662
|
-
}
|
|
10663
|
-
}
|
|
10664
|
-
function startDrainTimer(ws) {
|
|
10665
|
-
drainWs = ws;
|
|
10666
|
-
if (!drainTimer) {
|
|
10667
|
-
drainTimer = setInterval(drainQueue, DRAIN_INTERVAL_MS);
|
|
10668
|
-
}
|
|
10669
|
-
}
|
|
10670
|
-
function stopDrainTimer() {
|
|
10671
|
-
if (drainTimer) {
|
|
10672
|
-
clearInterval(drainTimer);
|
|
10673
|
-
drainTimer = null;
|
|
10674
|
-
}
|
|
10675
|
-
drainWs = null;
|
|
10676
|
-
}
|
|
10677
|
-
function sendToGroup(ws, group, data) {
|
|
10678
|
-
if (!group || ws.readyState !== import_ws.default.OPEN) return;
|
|
10679
|
-
const sanitized = sanitizePayload(data);
|
|
10680
|
-
const frame = JSON.stringify({
|
|
10681
|
-
type: "sendToGroup",
|
|
10682
|
-
group,
|
|
10683
|
-
dataType: "json",
|
|
10684
|
-
data: sanitized,
|
|
10685
|
-
noEcho: true
|
|
10686
|
-
});
|
|
10687
|
-
if (ws.bufferedAmount > BACKPRESSURE_HIGH_WATER) {
|
|
10688
|
-
if (pendingQueue.length >= MAX_PENDING_QUEUE) {
|
|
10689
|
-
pendingQueue.shift();
|
|
10690
|
-
droppedFrames++;
|
|
10691
|
-
if (droppedFrames % 100 === 1) {
|
|
10692
|
-
console.warn(`[rAgent] Backpressure: dropped ${droppedFrames} frames (queue full at ${MAX_PENDING_QUEUE})`);
|
|
10693
|
-
}
|
|
10694
|
-
}
|
|
10695
|
-
pendingQueue.push(frame);
|
|
10696
|
-
startDrainTimer(ws);
|
|
10697
|
-
return;
|
|
10698
|
-
}
|
|
10699
|
-
if (pendingQueue.length > 0) {
|
|
10700
|
-
pendingQueue.push(frame);
|
|
10701
|
-
drainWs = ws;
|
|
10702
|
-
drainQueue();
|
|
10703
|
-
return;
|
|
10704
|
-
}
|
|
10705
|
-
ws.send(frame);
|
|
10706
|
-
}
|
|
10707
|
-
function sanitizeValue(value) {
|
|
10708
|
-
if (typeof value === "string") {
|
|
10709
|
-
return redactSecrets(stripDangerousEscapes(sanitizeForJson(value)));
|
|
10710
|
-
}
|
|
10711
|
-
if (Array.isArray(value)) {
|
|
10712
|
-
return value.map((item) => sanitizeValue(item));
|
|
10713
|
-
}
|
|
10714
|
-
if (value !== null && typeof value === "object") {
|
|
10715
|
-
return sanitizePayload(value);
|
|
10716
|
-
}
|
|
10717
|
-
return value;
|
|
10718
|
-
}
|
|
10719
|
-
function sanitizePayload(obj) {
|
|
10720
|
-
const result = {};
|
|
10721
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
10722
|
-
result[key] = sanitizeValue(value);
|
|
10723
|
-
}
|
|
10724
|
-
return result;
|
|
10725
|
-
}
|
|
10726
|
-
|
|
10727
10851
|
// src/session-streamer.ts
|
|
10728
10852
|
var import_node_child_process2 = require("child_process");
|
|
10729
10853
|
var import_node_fs = require("fs");
|
|
@@ -10838,6 +10962,10 @@ var SessionStreamer = class {
|
|
|
10838
10962
|
sendFn;
|
|
10839
10963
|
onStreamStopped;
|
|
10840
10964
|
sendResetFn;
|
|
10965
|
+
/** #542: invoked once when a new backpressure frame-drop is detected, so the
|
|
10966
|
+
* markdown channel can recover (the terminal channel resyncs via tmux-pipe
|
|
10967
|
+
* capture, but the markdown snapshot had no recovery path). */
|
|
10968
|
+
onFramesDropped;
|
|
10841
10969
|
/**
|
|
10842
10970
|
* Per-session ring buffer for output captured while the WebSocket is disconnected.
|
|
10843
10971
|
* Each entry is a string chunk; oldest entries are evicted when the total byte
|
|
@@ -10851,10 +10979,11 @@ var SessionStreamer = class {
|
|
|
10851
10979
|
lastSeenDroppedFrames = 0;
|
|
10852
10980
|
/** Sessions whose viewers need a capture-pane resync after frame drops. */
|
|
10853
10981
|
pendingDropResync = /* @__PURE__ */ new Set();
|
|
10854
|
-
constructor(sendFn, onStreamStopped, sendResetFn) {
|
|
10982
|
+
constructor(sendFn, onStreamStopped, sendResetFn, onFramesDropped) {
|
|
10855
10983
|
this.sendFn = sendFn;
|
|
10856
10984
|
this.onStreamStopped = onStreamStopped;
|
|
10857
10985
|
this.sendResetFn = sendResetFn;
|
|
10986
|
+
this.onFramesDropped = onFramesDropped;
|
|
10858
10987
|
this.cleanupStaleStreams();
|
|
10859
10988
|
this.startBackpressureResumeTimer();
|
|
10860
10989
|
}
|
|
@@ -10898,6 +11027,7 @@ var SessionStreamer = class {
|
|
|
10898
11027
|
droppedTotal: dropped,
|
|
10899
11028
|
streams: this.pendingDropResync.size
|
|
10900
11029
|
});
|
|
11030
|
+
this.onFramesDropped?.();
|
|
10901
11031
|
}
|
|
10902
11032
|
const next = this.pendingDropResync.values().next();
|
|
10903
11033
|
if (!next.done) {
|
|
@@ -12121,6 +12251,7 @@ var InventoryManager = class {
|
|
|
12121
12251
|
|
|
12122
12252
|
// src/connection-manager.ts
|
|
12123
12253
|
var import_ws3 = __toESM(require("ws"));
|
|
12254
|
+
var import_node_crypto2 = require("crypto");
|
|
12124
12255
|
var log21 = createLogger("connection");
|
|
12125
12256
|
var OPPORTUNISTIC_INVENTORY_SYNC_MS = 1200;
|
|
12126
12257
|
var MIN_INVENTORY_SYNC_GAP_MS = 1500;
|
|
@@ -12131,6 +12262,16 @@ var ConnectionManager = class {
|
|
|
12131
12262
|
reconnectDelay = DEFAULT_RECONNECT_DELAY_MS;
|
|
12132
12263
|
/** Outbound frame counter; reset on every new handshake. See #310. */
|
|
12133
12264
|
txSeq = new SequenceTracker();
|
|
12265
|
+
/**
|
|
12266
|
+
* Per-process stream epoch, announced in the `register` message. The
|
|
12267
|
+
* sessionKey is derived from the (stable) hostId, so it does NOT change when
|
|
12268
|
+
* the CLI process restarts — but `txSeq` resets to 1 on a fresh process. A
|
|
12269
|
+
* portal holding a high lastSeq would then reject every restarted frame as
|
|
12270
|
+
* out-of-order and silently drop it forever. The portal resets its inbound
|
|
12271
|
+
* trackers when this epoch changes, recovering the stream without a manual
|
|
12272
|
+
* refresh. A new value per ConnectionManager == per CLI process. See #543.
|
|
12273
|
+
*/
|
|
12274
|
+
streamEpoch = (0, import_node_crypto2.randomUUID)();
|
|
12134
12275
|
/**
|
|
12135
12276
|
* Inbound frame trackers, keyed by viewerId. The portal's Terminal.tsx
|
|
12136
12277
|
* initializes a fresh txSeq (starting at 1) on every component mount, so a
|
|
@@ -13816,7 +13957,7 @@ function validateProvisionRequest(payload) {
|
|
|
13816
13957
|
}
|
|
13817
13958
|
|
|
13818
13959
|
// src/approval-policy.ts
|
|
13819
|
-
var
|
|
13960
|
+
var import_node_crypto3 = require("crypto");
|
|
13820
13961
|
function hasToken(cmd, token) {
|
|
13821
13962
|
const lower = cmd.toLowerCase();
|
|
13822
13963
|
const t = token.toLowerCase();
|
|
@@ -13923,7 +14064,7 @@ function matchPolicy(command, _policy = DEFAULT_APPROVAL_POLICY, hostId = "", se
|
|
|
13923
14064
|
for (const matcher of MATCHERS) {
|
|
13924
14065
|
if (matcher.test(command)) {
|
|
13925
14066
|
return {
|
|
13926
|
-
requestId: (0,
|
|
14067
|
+
requestId: (0, import_node_crypto3.randomUUID)(),
|
|
13927
14068
|
hostId,
|
|
13928
14069
|
sessionId,
|
|
13929
14070
|
action: matcher.action,
|
|
@@ -14373,6 +14514,9 @@ async function runAgent(rawOptions) {
|
|
|
14373
14514
|
mode,
|
|
14374
14515
|
...viewerId ? { viewerId } : {}
|
|
14375
14516
|
});
|
|
14517
|
+
},
|
|
14518
|
+
() => {
|
|
14519
|
+
transcriptWatcher.resyncMarkdownAfterDrop();
|
|
14376
14520
|
}
|
|
14377
14521
|
);
|
|
14378
14522
|
const conn = new ConnectionManager(sessionStreamer, outputBuffer);
|
|
@@ -14579,7 +14723,11 @@ async function runAgent(rawOptions) {
|
|
|
14579
14723
|
sendToGroup(ws, groups.privateGroup, {
|
|
14580
14724
|
type: "register",
|
|
14581
14725
|
hostName: options.hostName,
|
|
14582
|
-
environment: os10.platform()
|
|
14726
|
+
environment: os10.platform(),
|
|
14727
|
+
// #543: lets the portal detect a CLI process restart (txSeq reset
|
|
14728
|
+
// to 1 under a host-stable sessionKey) and reset its inbound
|
|
14729
|
+
// sequence trackers so restarted frames aren't dropped forever.
|
|
14730
|
+
streamEpoch: conn.streamEpoch
|
|
14583
14731
|
});
|
|
14584
14732
|
conn.replayBufferedOutput((chunk) => {
|
|
14585
14733
|
for (const outputChunk of splitTransportChunks(chunk)) {
|
package/dist/sbom.json
CHANGED
|
@@ -1299,8 +1299,8 @@
|
|
|
1299
1299
|
{
|
|
1300
1300
|
"type": "library",
|
|
1301
1301
|
"name": "ragent-cli",
|
|
1302
|
-
"version": "1.11.
|
|
1303
|
-
"bom-ref": "ragent-live|ragent-cli@1.11.
|
|
1302
|
+
"version": "1.11.16",
|
|
1303
|
+
"bom-ref": "ragent-live|ragent-cli@1.11.16",
|
|
1304
1304
|
"author": "Intellimetrics",
|
|
1305
1305
|
"description": "CLI agent for rAgent Live — browser-first terminal control plane for AI coding agents",
|
|
1306
1306
|
"licenses": [
|
|
@@ -1311,7 +1311,7 @@
|
|
|
1311
1311
|
}
|
|
1312
1312
|
}
|
|
1313
1313
|
],
|
|
1314
|
-
"purl": "pkg:npm/ragent-cli@1.11.
|
|
1314
|
+
"purl": "pkg:npm/ragent-cli@1.11.16",
|
|
1315
1315
|
"externalReferences": [
|
|
1316
1316
|
{
|
|
1317
1317
|
"url": "https://github.com/chadlindell/ragent-live/issues",
|
|
@@ -1436,7 +1436,7 @@
|
|
|
1436
1436
|
"ragent-live|@emnapi/wasi-threads@1.2.1",
|
|
1437
1437
|
"ragent-live|@pkgjs/parseargs@0.11.0",
|
|
1438
1438
|
"ragent-live|@tybys/wasm-util@0.10.1",
|
|
1439
|
-
"ragent-live|ragent-cli@1.11.
|
|
1439
|
+
"ragent-live|ragent-cli@1.11.16"
|
|
1440
1440
|
]
|
|
1441
1441
|
},
|
|
1442
1442
|
{
|
|
@@ -1584,7 +1584,7 @@
|
|
|
1584
1584
|
]
|
|
1585
1585
|
},
|
|
1586
1586
|
{
|
|
1587
|
-
"ref": "ragent-live|ragent-cli@1.11.
|
|
1587
|
+
"ref": "ragent-live|ragent-cli@1.11.16",
|
|
1588
1588
|
"dependsOn": [
|
|
1589
1589
|
"ragent-live|@azure/web-pubsub-client@1.0.4",
|
|
1590
1590
|
"ragent-live|@openai/codex-sdk@0.130.0",
|