@cryptiklemur/lattice 5.13.0 → 5.13.2
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.
|
@@ -380,6 +380,7 @@ function pushToExistingStream(session, options) {
|
|
|
380
380
|
session.clientId = clientId;
|
|
381
381
|
session.turnStartTime = Date.now();
|
|
382
382
|
session.turnDoneSent = false;
|
|
383
|
+
session.sawNewTurnContent = false;
|
|
383
384
|
session.activeToolBlocks = {};
|
|
384
385
|
const prompt = resolvePromptText(text);
|
|
385
386
|
const userMsg = buildSDKUserMessage(prompt, attachments, sessionId);
|
|
@@ -675,6 +676,7 @@ export function startChatStream(options) {
|
|
|
675
676
|
ended: false,
|
|
676
677
|
accumulatedText: "",
|
|
677
678
|
specId: options.specId,
|
|
679
|
+
sawNewTurnContent: false,
|
|
678
680
|
analyzer: new ContextAnalyzer(function (msg) {
|
|
679
681
|
const ss = sessionStreams.get(sessionId);
|
|
680
682
|
if (ss)
|
|
@@ -695,14 +697,13 @@ export function startChatStream(options) {
|
|
|
695
697
|
}
|
|
696
698
|
log.chat("Session %s pushing first message to queue", sessionId);
|
|
697
699
|
mq.push(firstMsg);
|
|
700
|
+
let retrying = false;
|
|
698
701
|
try {
|
|
699
702
|
log.chat("Session %s entering stream loop", sessionId);
|
|
700
703
|
let msgCount = 0;
|
|
701
704
|
for await (const msg of stream) {
|
|
702
705
|
msgCount++;
|
|
703
|
-
|
|
704
|
-
log.chat("Session %s msg #%d type=%s", sessionId, msgCount, msg.type);
|
|
705
|
-
}
|
|
706
|
+
log.chat("Session %s msg #%d type=%s", sessionId, msgCount, msg.type);
|
|
706
707
|
processMessage(sessionStream, msg);
|
|
707
708
|
}
|
|
708
709
|
log.chat("Session %s stream ended normally after %d messages", sessionId, msgCount);
|
|
@@ -713,8 +714,9 @@ export function startChatStream(options) {
|
|
|
713
714
|
if (errMsg.includes("aborted") || errMsg.includes("AbortError")) {
|
|
714
715
|
log.chat("Session %s stream aborted", sessionId);
|
|
715
716
|
}
|
|
716
|
-
else if (errMsg.includes("Sent before connected")) {
|
|
717
|
-
log.chat("Session %s
|
|
717
|
+
else if (errMsg.includes("Sent before connected") && shouldResume) {
|
|
718
|
+
log.chat("Session %s WebSocket not ready after resume, retrying in 500ms", sessionId);
|
|
719
|
+
retrying = true;
|
|
718
720
|
}
|
|
719
721
|
else {
|
|
720
722
|
console.error("[lattice] SDK stream error: " + errMsg);
|
|
@@ -726,6 +728,12 @@ export function startChatStream(options) {
|
|
|
726
728
|
pendingStreams.delete(sessionId);
|
|
727
729
|
sessionStreams.delete(sessionId);
|
|
728
730
|
persistStreamState();
|
|
731
|
+
if (retrying) {
|
|
732
|
+
log.chat("Session %s cleaning up for retry", sessionId);
|
|
733
|
+
await new Promise(function (resolve) { setTimeout(resolve, 500); });
|
|
734
|
+
startChatStream(options);
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
729
737
|
broadcast({ type: "session:busy", sessionId, busy: false }, sessionStream.clientId);
|
|
730
738
|
const toCleanup = [];
|
|
731
739
|
pendingPermissions.forEach(function (entry, reqId) {
|
|
@@ -798,6 +806,7 @@ function processMessage(ss, msg) {
|
|
|
798
806
|
}
|
|
799
807
|
if (msg.type === "assistant") {
|
|
800
808
|
const assistantMsg = msg;
|
|
809
|
+
log.chat("Session %s assistant message: model=%s", sessionId, assistantMsg.message.model || "unknown");
|
|
801
810
|
const msgUsage = assistantMsg.message.usage;
|
|
802
811
|
if (msgUsage && msgUsage.input_tokens != null) {
|
|
803
812
|
const ctxWindow = guessContextWindow(assistantMsg.message.model || "");
|
|
@@ -822,6 +831,9 @@ function processMessage(ss, msg) {
|
|
|
822
831
|
const partial = msg;
|
|
823
832
|
const evt = partial.event;
|
|
824
833
|
if (evt.type === "content_block_start") {
|
|
834
|
+
const blockInfo = evt.content_block;
|
|
835
|
+
log.chat("Session %s content_block_start: type=%s name=%s", sessionId, blockInfo.type, blockInfo.name || "text");
|
|
836
|
+
ss.sawNewTurnContent = true;
|
|
825
837
|
const block = evt.content_block;
|
|
826
838
|
const idx = evt.index;
|
|
827
839
|
if (block.type === "tool_use" && block.id && block.name) {
|
|
@@ -953,6 +965,11 @@ function processMessage(ss, msg) {
|
|
|
953
965
|
}
|
|
954
966
|
if (msg.type === "result") {
|
|
955
967
|
const resultMsg = msg;
|
|
968
|
+
log.chat("Session %s result: cost=$%s, sawContent=%s", sessionId, String(resultMsg.total_cost_usd || 0), String(ss.sawNewTurnContent));
|
|
969
|
+
if (!ss.sawNewTurnContent) {
|
|
970
|
+
log.chat("Session %s ignoring replayed result (no new turn content seen)", sessionId);
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
956
973
|
const dur = Date.now() - ss.turnStartTime;
|
|
957
974
|
const cost = resultMsg.total_cost_usd || 0;
|
|
958
975
|
if (resultMsg.usage) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cryptiklemur/lattice",
|
|
3
|
-
"version": "5.13.
|
|
3
|
+
"version": "5.13.2",
|
|
4
4
|
"description": "Multi-machine agentic dashboard for Claude Code. Monitor sessions, manage MCP servers and skills, orchestrate across mesh-networked nodes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Aaron Scherer <me@aaronscherer.me>",
|