@junctionpanel/server 0.1.77 → 0.1.79
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/server/server/agent/providers/gemini-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/gemini-agent.js +272 -56
- package/dist/server/server/agent/providers/gemini-agent.js.map +1 -1
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +124 -68
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/shared/messages.d.ts +48 -24
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +2 -1
- package/dist/server/shared/messages.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-agent.d.ts","sourceRoot":"","sources":["../../../../../src/server/agent/providers/gemini-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAShD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EACV,oBAAoB,EACpB,WAAW,EAGX,oBAAoB,EACpB,sBAAsB,EAEtB,sBAAsB,EACtB,gBAAgB,EAIhB,YAAY,EACZ,kBAAkB,EAElB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,0BAA0B,EAE1B,wBAAwB,EAExB,oBAAoB,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,8BAA8B,CAAC;AAqBtC,QAAA,MAAM,YAAY,mDAAoD,CAAC;AAavE,KAAK,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAGlD,KAAK,wBAAwB,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AA+B7D,KAAK,mBAAmB,GAAG,OAAO,GAAG,oBAAoB,CAAC;AAwB1D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoD/B,CAAC;AA6EH,QAAA,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCASjB,CAAC;AAEjB,KAAK,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAGzE,KAAK,yBAAyB,GAAG;IAC/B,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini-agent.d.ts","sourceRoot":"","sources":["../../../../../src/server/agent/providers/gemini-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -412,6 +412,25 @@ function asRecord(value) {
|
|
|
412
412
|
}
|
|
413
413
|
return value;
|
|
414
414
|
}
|
|
415
|
+
function parseGeminiErrorPayload(value) {
|
|
416
|
+
const directRecord = asRecord(value);
|
|
417
|
+
if (directRecord) {
|
|
418
|
+
return directRecord;
|
|
419
|
+
}
|
|
420
|
+
if (typeof value !== "string") {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
const trimmed = value.trim();
|
|
424
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
try {
|
|
428
|
+
return asRecord(JSON.parse(trimmed));
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
415
434
|
function formatGeminiAcpError(error) {
|
|
416
435
|
if (error instanceof acp.RequestError) {
|
|
417
436
|
const directMessage = nonEmptyString(error.message);
|
|
@@ -426,9 +445,45 @@ function formatGeminiAcpError(error) {
|
|
|
426
445
|
}
|
|
427
446
|
return message;
|
|
428
447
|
}
|
|
429
|
-
const
|
|
448
|
+
const rawMessage = stringifyUnknown(error);
|
|
449
|
+
const errorPayload = parseGeminiErrorPayload(rawMessage) ?? parseGeminiErrorPayload(error);
|
|
450
|
+
const payloadMessage = nonEmptyString(errorPayload?.message);
|
|
451
|
+
const message = payloadMessage ?? nonEmptyString(rawMessage);
|
|
452
|
+
const normalizedMessage = message?.toLowerCase() ?? "";
|
|
453
|
+
if (message &&
|
|
454
|
+
normalizedMessage.includes("no capacity available for model")) {
|
|
455
|
+
return `${message} Retry in a moment or switch to a Flash/Auto Gemini model.`;
|
|
456
|
+
}
|
|
430
457
|
return message ?? "Gemini ACP request failed";
|
|
431
458
|
}
|
|
459
|
+
function appendGeminiStreamText(current, incoming) {
|
|
460
|
+
if (incoming.length === 0) {
|
|
461
|
+
return current;
|
|
462
|
+
}
|
|
463
|
+
if (current.length === 0) {
|
|
464
|
+
return incoming;
|
|
465
|
+
}
|
|
466
|
+
if (incoming.length > current.length && incoming.startsWith(current)) {
|
|
467
|
+
return incoming;
|
|
468
|
+
}
|
|
469
|
+
const maxOverlap = Math.min(current.length, Math.max(incoming.length - 1, 0));
|
|
470
|
+
for (let overlapLength = maxOverlap; overlapLength > 0; overlapLength -= 1) {
|
|
471
|
+
if (current.endsWith(incoming.slice(0, overlapLength))) {
|
|
472
|
+
return current + incoming.slice(overlapLength);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return current + incoming;
|
|
476
|
+
}
|
|
477
|
+
function shouldPreferRecordedGeminiTurnOutput(modelId) {
|
|
478
|
+
const normalizedModelId = modelId?.trim().toLowerCase() ?? "";
|
|
479
|
+
return (normalizedModelId.includes("gemini-3.1-pro-preview") ||
|
|
480
|
+
normalizedModelId.includes("gemini-3.1-pro-preview-customtools"));
|
|
481
|
+
}
|
|
482
|
+
function shouldDeferGeminiTextStreaming(modelId) {
|
|
483
|
+
const normalizedModelId = modelId?.trim().toLowerCase() ?? "";
|
|
484
|
+
return (shouldPreferRecordedGeminiTurnOutput(normalizedModelId) ||
|
|
485
|
+
normalizedModelId.includes("auto-gemini-3"));
|
|
486
|
+
}
|
|
432
487
|
export function normalizeGeminiMode(modeId) {
|
|
433
488
|
if (!modeId) {
|
|
434
489
|
return DEFAULT_GEMINI_MODE;
|
|
@@ -849,6 +904,16 @@ function getGeminiRecordedTurnMessages(session, turnStartedAt) {
|
|
|
849
904
|
function hasGeminiRecordedAssistantMessage(messages) {
|
|
850
905
|
return messages.some((message) => message.type === "gemini");
|
|
851
906
|
}
|
|
907
|
+
function buildGeminiRecordedTurnOutputItems(messages) {
|
|
908
|
+
const items = [];
|
|
909
|
+
for (const message of messages) {
|
|
910
|
+
if (message.type !== "gemini") {
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
items.push(...buildGeminiRecordedMessageTimelineItems(message).filter((item) => item.type === "assistant_message" || item.type === "reasoning"));
|
|
914
|
+
}
|
|
915
|
+
return items;
|
|
916
|
+
}
|
|
852
917
|
function countGeminiRecordedHistoryEvents(session) {
|
|
853
918
|
let count = 0;
|
|
854
919
|
for (const message of session.messages) {
|
|
@@ -1513,6 +1578,7 @@ class GeminiAgentSession {
|
|
|
1513
1578
|
this.pendingPermissions = new Map();
|
|
1514
1579
|
this.toolStates = new Map();
|
|
1515
1580
|
this.activeTurnQueue = null;
|
|
1581
|
+
this.activeTurnState = null;
|
|
1516
1582
|
this.historyEvents = [];
|
|
1517
1583
|
this.historyReadyPromise = null;
|
|
1518
1584
|
this.resolveHistoryReady = null;
|
|
@@ -1544,6 +1610,44 @@ class GeminiAgentSession {
|
|
|
1544
1610
|
await this.openConnection();
|
|
1545
1611
|
this.initialized = true;
|
|
1546
1612
|
}
|
|
1613
|
+
beginActiveTurn(queue, startedAt) {
|
|
1614
|
+
const turnState = {
|
|
1615
|
+
startedAt,
|
|
1616
|
+
queue,
|
|
1617
|
+
terminalState: "open",
|
|
1618
|
+
deferTextStreaming: shouldDeferGeminiTextStreaming(this.currentModelId),
|
|
1619
|
+
liveAssistantText: "",
|
|
1620
|
+
liveReasoningText: "",
|
|
1621
|
+
deferredOutputItems: [],
|
|
1622
|
+
};
|
|
1623
|
+
this.activeTurnState = turnState;
|
|
1624
|
+
return turnState;
|
|
1625
|
+
}
|
|
1626
|
+
finalizeActiveTurn(turnState, terminalState) {
|
|
1627
|
+
if (turnState.terminalState !== "open") {
|
|
1628
|
+
return false;
|
|
1629
|
+
}
|
|
1630
|
+
turnState.terminalState = terminalState;
|
|
1631
|
+
return true;
|
|
1632
|
+
}
|
|
1633
|
+
trackLiveTurnOutput(turnState, item) {
|
|
1634
|
+
if (!turnState || turnState.terminalState !== "open") {
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
if (item.type === "assistant_message") {
|
|
1638
|
+
turnState.liveAssistantText = appendGeminiStreamText(turnState.liveAssistantText, item.text);
|
|
1639
|
+
if (turnState.deferTextStreaming) {
|
|
1640
|
+
turnState.deferredOutputItems.push(item);
|
|
1641
|
+
}
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
if (item.type === "reasoning") {
|
|
1645
|
+
turnState.liveReasoningText = appendGeminiStreamText(turnState.liveReasoningText, item.text);
|
|
1646
|
+
if (turnState.deferTextStreaming) {
|
|
1647
|
+
turnState.deferredOutputItems.push(item);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1547
1651
|
async run(prompt, options) {
|
|
1548
1652
|
const timeline = [];
|
|
1549
1653
|
let finalText = "";
|
|
@@ -1553,7 +1657,7 @@ class GeminiAgentSession {
|
|
|
1553
1657
|
if (event.type === "timeline") {
|
|
1554
1658
|
timeline.push(event.item);
|
|
1555
1659
|
if (event.item.type === "assistant_message") {
|
|
1556
|
-
finalText
|
|
1660
|
+
finalText = appendGeminiStreamText(finalText, event.item.text);
|
|
1557
1661
|
}
|
|
1558
1662
|
}
|
|
1559
1663
|
else if (event.type === "turn_completed") {
|
|
@@ -1585,48 +1689,60 @@ class GeminiAgentSession {
|
|
|
1585
1689
|
const queue = new AsyncEventQueue();
|
|
1586
1690
|
this.activeTurnQueue = queue;
|
|
1587
1691
|
this.currentRunInterrupted = false;
|
|
1692
|
+
const connection = this.connection;
|
|
1588
1693
|
const turnStartedAt = new Date();
|
|
1694
|
+
const turnState = this.beginActiveTurn(queue, turnStartedAt);
|
|
1589
1695
|
queue.push({
|
|
1590
1696
|
type: "turn_started",
|
|
1591
1697
|
provider: GEMINI_PROVIDER,
|
|
1592
1698
|
});
|
|
1593
|
-
void
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
.then(async (response) => {
|
|
1599
|
-
if (response.stopReason === "cancelled") {
|
|
1600
|
-
queue.push({
|
|
1601
|
-
type: "turn_canceled",
|
|
1602
|
-
provider: GEMINI_PROVIDER,
|
|
1603
|
-
reason: "Interrupted",
|
|
1699
|
+
void (async () => {
|
|
1700
|
+
try {
|
|
1701
|
+
const response = await connection.prompt({
|
|
1702
|
+
sessionId: this.sessionId,
|
|
1703
|
+
prompt: toGeminiPromptBlocks(prompt),
|
|
1604
1704
|
});
|
|
1705
|
+
if (response.stopReason === "cancelled") {
|
|
1706
|
+
if (!this.finalizeActiveTurn(turnState, "canceled")) {
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
queue.push({
|
|
1710
|
+
type: "turn_canceled",
|
|
1711
|
+
provider: GEMINI_PROVIDER,
|
|
1712
|
+
reason: "Interrupted",
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
else {
|
|
1716
|
+
if (!this.finalizeActiveTurn(turnState, "completed")) {
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1719
|
+
const recordedTurnCompletion = await this.readRecordedTurnCompletion(turnStartedAt);
|
|
1720
|
+
await this.emitRecordedTurnOutput(turnState, recordedTurnCompletion);
|
|
1721
|
+
queue.push({
|
|
1722
|
+
type: "turn_completed",
|
|
1723
|
+
provider: GEMINI_PROVIDER,
|
|
1724
|
+
...(recordedTurnCompletion?.summary
|
|
1725
|
+
? {
|
|
1726
|
+
usage: recordedTurnCompletion.summary.usage,
|
|
1727
|
+
modelId: recordedTurnCompletion.summary.modelId,
|
|
1728
|
+
}
|
|
1729
|
+
: {}),
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
queue.close();
|
|
1605
1733
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1734
|
+
catch (error) {
|
|
1735
|
+
if (!this.finalizeActiveTurn(turnState, "failed")) {
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1609
1738
|
queue.push({
|
|
1610
|
-
type: "
|
|
1739
|
+
type: "turn_failed",
|
|
1611
1740
|
provider: GEMINI_PROVIDER,
|
|
1612
|
-
|
|
1613
|
-
? {
|
|
1614
|
-
usage: recordedTurnSummary.usage,
|
|
1615
|
-
modelId: recordedTurnSummary.modelId,
|
|
1616
|
-
}
|
|
1617
|
-
: {}),
|
|
1741
|
+
error: formatGeminiAcpError(error),
|
|
1618
1742
|
});
|
|
1743
|
+
queue.close();
|
|
1619
1744
|
}
|
|
1620
|
-
|
|
1621
|
-
})
|
|
1622
|
-
.catch((error) => {
|
|
1623
|
-
queue.push({
|
|
1624
|
-
type: "turn_failed",
|
|
1625
|
-
provider: GEMINI_PROVIDER,
|
|
1626
|
-
error: formatGeminiAcpError(error),
|
|
1627
|
-
});
|
|
1628
|
-
queue.close();
|
|
1629
|
-
});
|
|
1745
|
+
})();
|
|
1630
1746
|
try {
|
|
1631
1747
|
while (true) {
|
|
1632
1748
|
const nextEvent = await queue.shift();
|
|
@@ -1640,6 +1756,9 @@ class GeminiAgentSession {
|
|
|
1640
1756
|
if (this.activeTurnQueue === queue) {
|
|
1641
1757
|
this.activeTurnQueue = null;
|
|
1642
1758
|
}
|
|
1759
|
+
if (this.activeTurnState === turnState) {
|
|
1760
|
+
this.activeTurnState = null;
|
|
1761
|
+
}
|
|
1643
1762
|
this.currentRunInterrupted = false;
|
|
1644
1763
|
}
|
|
1645
1764
|
}
|
|
@@ -1802,6 +1921,7 @@ class GeminiAgentSession {
|
|
|
1802
1921
|
}
|
|
1803
1922
|
this.activeTurnQueue?.close();
|
|
1804
1923
|
this.activeTurnQueue = null;
|
|
1924
|
+
this.activeTurnState = null;
|
|
1805
1925
|
if (this.child?.stdin) {
|
|
1806
1926
|
this.child.stdin.end();
|
|
1807
1927
|
}
|
|
@@ -1830,6 +1950,7 @@ class GeminiAgentSession {
|
|
|
1830
1950
|
if (this.closePromise === params.closePromise) {
|
|
1831
1951
|
this.closePromise = Promise.resolve();
|
|
1832
1952
|
}
|
|
1953
|
+
this.activeTurnState = null;
|
|
1833
1954
|
}
|
|
1834
1955
|
async setModel(modelId) {
|
|
1835
1956
|
await this.initialize();
|
|
@@ -1933,13 +2054,26 @@ class GeminiAgentSession {
|
|
|
1933
2054
|
this.connection = null;
|
|
1934
2055
|
}
|
|
1935
2056
|
if (!this.closed) {
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
2057
|
+
const activeTurnState = this.activeTurnState;
|
|
2058
|
+
if (activeTurnState && this.activeTurnQueue) {
|
|
2059
|
+
const terminalState = this.currentRunInterrupted ? "canceled" : "failed";
|
|
2060
|
+
if (this.finalizeActiveTurn(activeTurnState, terminalState)) {
|
|
2061
|
+
if (terminalState === "canceled") {
|
|
2062
|
+
this.activeTurnQueue.push({
|
|
2063
|
+
type: "turn_canceled",
|
|
2064
|
+
provider: GEMINI_PROVIDER,
|
|
2065
|
+
reason: "Interrupted",
|
|
2066
|
+
});
|
|
2067
|
+
}
|
|
2068
|
+
else {
|
|
2069
|
+
this.activeTurnQueue.push({
|
|
2070
|
+
type: "turn_failed",
|
|
2071
|
+
provider: GEMINI_PROVIDER,
|
|
2072
|
+
error: message,
|
|
2073
|
+
});
|
|
2074
|
+
}
|
|
2075
|
+
this.activeTurnQueue.close();
|
|
2076
|
+
}
|
|
1943
2077
|
}
|
|
1944
2078
|
this.logger.warn({ code, signal, stderr }, "Gemini ACP process closed");
|
|
1945
2079
|
}
|
|
@@ -2138,6 +2272,45 @@ class GeminiAgentSession {
|
|
|
2138
2272
|
this.currentModeId = notification.update.currentModeId;
|
|
2139
2273
|
return;
|
|
2140
2274
|
}
|
|
2275
|
+
const activeTurnState = this.activeTurnState;
|
|
2276
|
+
if (notification.update.sessionUpdate === "agent_message_chunk") {
|
|
2277
|
+
if (notification.update.content.type !== "text") {
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
const text = notification.update.content.text;
|
|
2281
|
+
if (text.length === 0) {
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
if (activeTurnState && activeTurnState.terminalState !== "open") {
|
|
2285
|
+
return;
|
|
2286
|
+
}
|
|
2287
|
+
this.trackLiveTurnOutput(activeTurnState, {
|
|
2288
|
+
type: "assistant_message",
|
|
2289
|
+
text,
|
|
2290
|
+
});
|
|
2291
|
+
if (activeTurnState?.deferTextStreaming) {
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
if (notification.update.sessionUpdate === "agent_thought_chunk") {
|
|
2296
|
+
if (notification.update.content.type !== "text") {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
const text = notification.update.content.text;
|
|
2300
|
+
if (text.length === 0) {
|
|
2301
|
+
return;
|
|
2302
|
+
}
|
|
2303
|
+
if (activeTurnState && activeTurnState.terminalState !== "open") {
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
this.trackLiveTurnOutput(activeTurnState, {
|
|
2307
|
+
type: "reasoning",
|
|
2308
|
+
text,
|
|
2309
|
+
});
|
|
2310
|
+
if (activeTurnState?.deferTextStreaming) {
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2141
2314
|
const includeUserMessages = this.historyCaptureActive;
|
|
2142
2315
|
const events = sessionUpdateToEvents(notification.update, this.toolStates, {
|
|
2143
2316
|
includeUserMessages,
|
|
@@ -2158,13 +2331,48 @@ class GeminiAgentSession {
|
|
|
2158
2331
|
return;
|
|
2159
2332
|
}
|
|
2160
2333
|
for (const event of events) {
|
|
2334
|
+
if (activeTurnState?.terminalState !== "open" &&
|
|
2335
|
+
event.type === "timeline" &&
|
|
2336
|
+
(event.item.type === "assistant_message" || event.item.type === "reasoning")) {
|
|
2337
|
+
continue;
|
|
2338
|
+
}
|
|
2161
2339
|
this.emitLiveEvent(event);
|
|
2162
2340
|
}
|
|
2163
2341
|
}
|
|
2164
2342
|
emitLiveEvent(event) {
|
|
2165
2343
|
this.activeTurnQueue?.push(event);
|
|
2166
2344
|
}
|
|
2167
|
-
async
|
|
2345
|
+
async emitRecordedTurnOutput(turnState, completion) {
|
|
2346
|
+
const recordedOutputItems = completion
|
|
2347
|
+
? buildGeminiRecordedTurnOutputItems(completion.messages)
|
|
2348
|
+
: [];
|
|
2349
|
+
const preferRecordedOutput = shouldPreferRecordedGeminiTurnOutput(completion?.summary?.modelId) ||
|
|
2350
|
+
turnState.deferTextStreaming;
|
|
2351
|
+
const outputItems = recordedOutputItems.length > 0
|
|
2352
|
+
? recordedOutputItems.filter((item) => {
|
|
2353
|
+
if (preferRecordedOutput) {
|
|
2354
|
+
return true;
|
|
2355
|
+
}
|
|
2356
|
+
if (item.type === "assistant_message") {
|
|
2357
|
+
return turnState.liveAssistantText.length === 0;
|
|
2358
|
+
}
|
|
2359
|
+
if (item.type === "reasoning") {
|
|
2360
|
+
return turnState.liveReasoningText.length === 0;
|
|
2361
|
+
}
|
|
2362
|
+
return false;
|
|
2363
|
+
})
|
|
2364
|
+
: turnState.deferTextStreaming
|
|
2365
|
+
? turnState.deferredOutputItems
|
|
2366
|
+
: [];
|
|
2367
|
+
for (const item of outputItems) {
|
|
2368
|
+
turnState.queue.push({
|
|
2369
|
+
type: "timeline",
|
|
2370
|
+
provider: GEMINI_PROVIDER,
|
|
2371
|
+
item,
|
|
2372
|
+
});
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
async readRecordedTurnCompletion(turnStartedAt) {
|
|
2168
2376
|
if (!this.sessionId) {
|
|
2169
2377
|
return null;
|
|
2170
2378
|
}
|
|
@@ -2177,10 +2385,10 @@ class GeminiAgentSession {
|
|
|
2177
2385
|
(this.hasObservedRecordedSession && !this.recordedSessionFilePath
|
|
2178
2386
|
? GEMINI_RECORDED_SESSION_DISCOVERY_TIMEOUT_MS
|
|
2179
2387
|
: GEMINI_HISTORY_FALLBACK_IDLE_MS);
|
|
2180
|
-
let
|
|
2388
|
+
let latestSummaryFingerprint = null;
|
|
2181
2389
|
let observedSummary = false;
|
|
2182
|
-
let
|
|
2183
|
-
let
|
|
2390
|
+
let latestTurnFingerprint = null;
|
|
2391
|
+
let observedTurn = false;
|
|
2184
2392
|
let sawRecordedSession = false;
|
|
2185
2393
|
while (Date.now() <= deadline) {
|
|
2186
2394
|
let recordedSession = null;
|
|
@@ -2202,24 +2410,32 @@ class GeminiAgentSession {
|
|
|
2202
2410
|
this.hasObservedRecordedSession = true;
|
|
2203
2411
|
const turnMessages = getGeminiRecordedTurnMessages(recordedSession, turnStartedAt);
|
|
2204
2412
|
const nextSummary = summarizeGeminiRecordedMessages(turnMessages);
|
|
2413
|
+
const turnFingerprint = JSON.stringify(turnMessages);
|
|
2205
2414
|
if (nextSummary) {
|
|
2206
|
-
const
|
|
2207
|
-
if (observedSummary &&
|
|
2208
|
-
|
|
2415
|
+
const nextSummaryFingerprint = JSON.stringify(nextSummary);
|
|
2416
|
+
if (observedSummary &&
|
|
2417
|
+
nextSummaryFingerprint === latestSummaryFingerprint &&
|
|
2418
|
+
observedTurn &&
|
|
2419
|
+
turnFingerprint === latestTurnFingerprint) {
|
|
2420
|
+
return {
|
|
2421
|
+
summary: nextSummary,
|
|
2422
|
+
messages: turnMessages,
|
|
2423
|
+
};
|
|
2209
2424
|
}
|
|
2210
|
-
|
|
2425
|
+
latestSummaryFingerprint = nextSummaryFingerprint;
|
|
2211
2426
|
observedSummary = true;
|
|
2212
|
-
|
|
2213
|
-
|
|
2427
|
+
latestTurnFingerprint = turnFingerprint;
|
|
2428
|
+
observedTurn = true;
|
|
2214
2429
|
}
|
|
2215
2430
|
else if (hasGeminiRecordedAssistantMessage(turnMessages)) {
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2431
|
+
if (observedTurn && turnFingerprint === latestTurnFingerprint) {
|
|
2432
|
+
return {
|
|
2433
|
+
summary: null,
|
|
2434
|
+
messages: turnMessages,
|
|
2435
|
+
};
|
|
2220
2436
|
}
|
|
2221
|
-
|
|
2222
|
-
|
|
2437
|
+
observedTurn = true;
|
|
2438
|
+
latestTurnFingerprint = turnFingerprint;
|
|
2223
2439
|
}
|
|
2224
2440
|
}
|
|
2225
2441
|
else if (!sawRecordedSession && Date.now() >= discoveryDeadline) {
|