@respan/cli 0.6.2 → 0.6.4
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/hooks/gemini-cli.cjs +15 -21
- package/dist/hooks/gemini-cli.js +22 -26
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -721,17 +721,6 @@ function processChunk(hookData) {
|
|
|
721
721
|
}
|
|
722
722
|
}
|
|
723
723
|
}
|
|
724
|
-
const grounding = candidates[0].groundingMetadata ?? llmResp.groundingMetadata;
|
|
725
|
-
if (grounding && typeof grounding === "object") {
|
|
726
|
-
const queries = grounding.webSearchQueries ?? grounding.searchQueries ?? [];
|
|
727
|
-
if (queries.length > 0) {
|
|
728
|
-
chunkToolDetails.push({
|
|
729
|
-
name: "google_web_search",
|
|
730
|
-
args: { queries },
|
|
731
|
-
output: truncate(queries.join(", "), MAX_CHARS)
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
724
|
}
|
|
736
725
|
const messages = hookData.llm_request?.messages ?? [];
|
|
737
726
|
const currentMsgCount = messages.length;
|
|
@@ -741,8 +730,17 @@ function processChunk(hookData) {
|
|
|
741
730
|
let toolCallDetected = false;
|
|
742
731
|
if (savedMsgCount > 0 && currentMsgCount > savedMsgCount) {
|
|
743
732
|
const newMsgs = messages.slice(savedMsgCount);
|
|
744
|
-
const
|
|
745
|
-
|
|
733
|
+
const hasRealUserMsg = newMsgs.some((m) => {
|
|
734
|
+
if (String(m.role ?? "") !== "user") return false;
|
|
735
|
+
const parts = m.parts ?? m.content;
|
|
736
|
+
if (Array.isArray(parts)) {
|
|
737
|
+
return !parts.some(
|
|
738
|
+
(p) => typeof p === "object" && p !== null && (p.functionResponse || p.toolResponse)
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
return true;
|
|
742
|
+
});
|
|
743
|
+
if (hasRealUserMsg) {
|
|
746
744
|
debug(`New user message detected (msgs ${savedMsgCount} \u2192 ${currentMsgCount}), starting fresh turn`);
|
|
747
745
|
clearStreamState(sessionId);
|
|
748
746
|
state = { accumulated_text: "", last_tokens: 0, first_chunk_time: "" };
|
|
@@ -760,13 +758,7 @@ function processChunk(hookData) {
|
|
|
760
758
|
state.last_tokens = completionTokens || state.last_tokens;
|
|
761
759
|
if (thoughtsTokens > 0) state.thoughts_tokens = thoughtsTokens;
|
|
762
760
|
}
|
|
763
|
-
|
|
764
|
-
if (groundingDetails.length) {
|
|
765
|
-
state.tool_details = [...state.tool_details ?? [], ...groundingDetails];
|
|
766
|
-
state.tool_turns = (state.tool_turns ?? 0) + groundingDetails.length;
|
|
767
|
-
debug(`Grounding search detected: ${groundingDetails.length} queries`);
|
|
768
|
-
}
|
|
769
|
-
if (chunkText || groundingDetails.length) {
|
|
761
|
+
if (chunkText) {
|
|
770
762
|
saveStreamState(sessionId, state);
|
|
771
763
|
debug(`Accumulated chunk: +${chunkText.length} chars, total=${state.accumulated_text.length}`);
|
|
772
764
|
}
|
|
@@ -782,8 +774,10 @@ function processChunk(hookData) {
|
|
|
782
774
|
process.stdout.write("{}\n");
|
|
783
775
|
return;
|
|
784
776
|
}
|
|
777
|
+
const hasPendingTools = (state.pending_tools ?? []).length > 0;
|
|
778
|
+
const hadToolsThisTurn = (state.tool_turns ?? 0) > 0 || hasPendingTools;
|
|
785
779
|
const hasNewText = state.accumulated_text.length > (state.last_send_text_len ?? 0);
|
|
786
|
-
const shouldSend =
|
|
780
|
+
const shouldSend = hasNewText && state.accumulated_text && (isFinished || !hadToolsThisTurn && !toolCallDetected && !chunkText);
|
|
787
781
|
process.stdout.write("{}\n");
|
|
788
782
|
if (!shouldSend) {
|
|
789
783
|
if (toolCallDetected) saveStreamState(sessionId, state);
|
package/dist/hooks/gemini-cli.js
CHANGED
|
@@ -449,18 +449,6 @@ function processChunk(hookData) {
|
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
|
-
// Detect server-side grounding (google_web_search) from groundingMetadata
|
|
453
|
-
const grounding = (candidates[0].groundingMetadata ?? llmResp.groundingMetadata);
|
|
454
|
-
if (grounding && typeof grounding === 'object') {
|
|
455
|
-
const queries = (grounding.webSearchQueries ?? grounding.searchQueries ?? []);
|
|
456
|
-
if (queries.length > 0) {
|
|
457
|
-
chunkToolDetails.push({
|
|
458
|
-
name: 'google_web_search',
|
|
459
|
-
args: { queries },
|
|
460
|
-
output: truncate(queries.join(', '), MAX_CHARS),
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
452
|
}
|
|
465
453
|
const messages = (hookData.llm_request?.messages ?? []);
|
|
466
454
|
const currentMsgCount = messages.length;
|
|
@@ -471,8 +459,19 @@ function processChunk(hookData) {
|
|
|
471
459
|
let toolCallDetected = false;
|
|
472
460
|
if (savedMsgCount > 0 && currentMsgCount > savedMsgCount) {
|
|
473
461
|
const newMsgs = messages.slice(savedMsgCount);
|
|
474
|
-
|
|
475
|
-
|
|
462
|
+
// Distinguish real user messages from tool-result messages injected by Gemini.
|
|
463
|
+
// Tool results contain functionResponse / toolResponse objects in their parts.
|
|
464
|
+
const hasRealUserMsg = newMsgs.some((m) => {
|
|
465
|
+
if (String(m.role ?? '') !== 'user')
|
|
466
|
+
return false;
|
|
467
|
+
const parts = (m.parts ?? m.content);
|
|
468
|
+
if (Array.isArray(parts)) {
|
|
469
|
+
// If any part has functionResponse/toolResponse, it's a tool result, not a user message
|
|
470
|
+
return !parts.some((p) => typeof p === 'object' && p !== null && (p.functionResponse || p.toolResponse));
|
|
471
|
+
}
|
|
472
|
+
return true; // plain text user message
|
|
473
|
+
});
|
|
474
|
+
if (hasRealUserMsg) {
|
|
476
475
|
debug(`New user message detected (msgs ${savedMsgCount} → ${currentMsgCount}), starting fresh turn`);
|
|
477
476
|
clearStreamState(sessionId);
|
|
478
477
|
state = { accumulated_text: '', last_tokens: 0, first_chunk_time: '' };
|
|
@@ -494,14 +493,7 @@ function processChunk(hookData) {
|
|
|
494
493
|
if (thoughtsTokens > 0)
|
|
495
494
|
state.thoughts_tokens = thoughtsTokens;
|
|
496
495
|
}
|
|
497
|
-
|
|
498
|
-
const groundingDetails = chunkToolDetails.filter(d => d.name === 'google_web_search');
|
|
499
|
-
if (groundingDetails.length) {
|
|
500
|
-
state.tool_details = [...(state.tool_details ?? []), ...groundingDetails];
|
|
501
|
-
state.tool_turns = (state.tool_turns ?? 0) + groundingDetails.length;
|
|
502
|
-
debug(`Grounding search detected: ${groundingDetails.length} queries`);
|
|
503
|
-
}
|
|
504
|
-
if (chunkText || groundingDetails.length) {
|
|
496
|
+
if (chunkText) {
|
|
505
497
|
saveStreamState(sessionId, state);
|
|
506
498
|
debug(`Accumulated chunk: +${chunkText.length} chars, total=${state.accumulated_text.length}`);
|
|
507
499
|
}
|
|
@@ -518,12 +510,16 @@ function processChunk(hookData) {
|
|
|
518
510
|
process.stdout.write('{}\n');
|
|
519
511
|
return;
|
|
520
512
|
}
|
|
521
|
-
// Detect completion and send
|
|
513
|
+
// Detect completion and send.
|
|
514
|
+
// If tools have been used this turn, only send on STOP to avoid
|
|
515
|
+
// splitting a multi-tool turn into separate traces.
|
|
516
|
+
const hasPendingTools = (state.pending_tools ?? []).length > 0;
|
|
517
|
+
const hadToolsThisTurn = (state.tool_turns ?? 0) > 0 || hasPendingTools;
|
|
522
518
|
const hasNewText = state.accumulated_text.length > (state.last_send_text_len ?? 0);
|
|
523
|
-
const shouldSend = (
|
|
524
|
-
&& hasNewText
|
|
519
|
+
const shouldSend = (hasNewText
|
|
525
520
|
&& state.accumulated_text
|
|
526
|
-
&& (
|
|
521
|
+
&& (isFinished
|
|
522
|
+
|| (!hadToolsThisTurn && !toolCallDetected && !chunkText)));
|
|
527
523
|
process.stdout.write('{}\n');
|
|
528
524
|
if (!shouldSend) {
|
|
529
525
|
if (toolCallDetected)
|
package/oclif.manifest.json
CHANGED