@respan/cli 0.6.8 → 0.7.0
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/claude-code.cjs +1 -1
- package/dist/hooks/codex-cli.cjs +1 -1
- package/dist/hooks/gemini-cli.cjs +145 -73
- package/dist/hooks/gemini-cli.js +178 -87
- package/dist/hooks/shared.js +1 -1
- package/oclif.manifest.json +730 -730
- package/package.json +1 -1
package/dist/hooks/codex-cli.cjs
CHANGED
|
@@ -318,7 +318,7 @@ function toOtlpPayload(spans) {
|
|
|
318
318
|
})
|
|
319
319
|
},
|
|
320
320
|
scopeSpans: [{
|
|
321
|
-
scope: { name: "respan-cli-hooks", version: "0.
|
|
321
|
+
scope: { name: "respan-cli-hooks", version: "0.7.0" },
|
|
322
322
|
spans: otlpSpans
|
|
323
323
|
}]
|
|
324
324
|
}]
|
|
@@ -438,7 +438,7 @@ function detectModel(hookData) {
|
|
|
438
438
|
const llmReq = hookData.llm_request ?? {};
|
|
439
439
|
return String(llmReq.model ?? "") || "gemini-cli";
|
|
440
440
|
}
|
|
441
|
-
function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurns, toolDetails, thoughtsTokens) {
|
|
441
|
+
function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurns, toolDetails, thoughtsTokens, textRounds, roundStartTimes) {
|
|
442
442
|
const spans = [];
|
|
443
443
|
const sessionId = String(hookData.session_id ?? "");
|
|
444
444
|
const model = detectModel(hookData);
|
|
@@ -447,7 +447,6 @@ function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurn
|
|
|
447
447
|
const beginTime = startTimeIso || endTime;
|
|
448
448
|
const lat = latencySeconds(beginTime, endTime);
|
|
449
449
|
const promptMessages = extractMessages(hookData);
|
|
450
|
-
const completionMessage = { role: "assistant", content: truncate(outputText, MAX_CHARS) };
|
|
451
450
|
const { workflowName, spanName, customerId } = resolveSpanFields(config, {
|
|
452
451
|
workflowName: "gemini-cli",
|
|
453
452
|
spanName: "gemini-cli"
|
|
@@ -480,50 +479,85 @@ function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurn
|
|
|
480
479
|
metadata,
|
|
481
480
|
...lat !== void 0 ? { latency: lat } : {}
|
|
482
481
|
});
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
482
|
+
const rounds = textRounds.length > 0 ? textRounds : [outputText];
|
|
483
|
+
const roundStarts = roundStartTimes.length > 0 ? roundStartTimes : [beginTime];
|
|
484
|
+
let toolIdx = 0;
|
|
485
|
+
for (let r = 0; r < rounds.length; r++) {
|
|
486
|
+
const roundText = rounds[r];
|
|
487
|
+
const roundStart = roundStarts[r] || beginTime;
|
|
488
|
+
const nextTool = toolIdx < toolDetails.length ? toolDetails[toolIdx] : null;
|
|
489
|
+
const roundEnd = r < rounds.length - 1 && nextTool?.start_time ? nextTool.start_time : endTime;
|
|
490
|
+
const roundLat = latencySeconds(roundStart, roundEnd);
|
|
491
|
+
if (roundText) {
|
|
492
|
+
const genSpan = {
|
|
493
|
+
trace_unique_id: traceUniqueId,
|
|
494
|
+
span_unique_id: `gcli_${safeId}_${turnTs}_gen_${r}`,
|
|
495
|
+
span_parent_id: rootSpanId,
|
|
496
|
+
span_name: "gemini.chat",
|
|
497
|
+
span_workflow_name: workflowName,
|
|
498
|
+
span_path: "gemini_chat",
|
|
499
|
+
model,
|
|
500
|
+
provider_id: "google",
|
|
501
|
+
metadata: {},
|
|
502
|
+
input: r === 0 && promptMessages.length ? JSON.stringify(promptMessages) : "",
|
|
503
|
+
output: truncate(roundText, MAX_CHARS),
|
|
504
|
+
timestamp: roundEnd,
|
|
505
|
+
start_time: roundStart,
|
|
506
|
+
...roundLat !== void 0 ? { latency: roundLat } : {},
|
|
507
|
+
// Only attach tokens to the first round (aggregate usage from Gemini)
|
|
508
|
+
...r === 0 ? {
|
|
509
|
+
prompt_tokens: tokens.prompt_tokens,
|
|
510
|
+
completion_tokens: tokens.completion_tokens,
|
|
511
|
+
total_tokens: tokens.total_tokens
|
|
512
|
+
} : {}
|
|
513
|
+
};
|
|
514
|
+
if (r === 0) {
|
|
515
|
+
if (reqConfig.temperature != null) genSpan.temperature = reqConfig.temperature;
|
|
516
|
+
if (reqConfig.maxOutputTokens != null) genSpan.max_tokens = reqConfig.maxOutputTokens;
|
|
517
|
+
}
|
|
518
|
+
spans.push(genSpan);
|
|
519
|
+
}
|
|
520
|
+
if (r < rounds.length - 1) {
|
|
521
|
+
while (toolIdx < toolDetails.length) {
|
|
522
|
+
const detail = toolDetails[toolIdx];
|
|
523
|
+
const toolName = detail?.name ?? "";
|
|
524
|
+
const toolArgs = detail?.args ?? detail?.input ?? {};
|
|
525
|
+
const toolOutput = detail?.output ?? "";
|
|
526
|
+
const displayName = toolName ? toolDisplayName(toolName) : `Call ${toolIdx + 1}`;
|
|
527
|
+
const toolInputStr = toolName ? formatToolInput(toolName, toolArgs) : "";
|
|
528
|
+
const toolMeta = {};
|
|
529
|
+
if (toolName) toolMeta.tool_name = toolName;
|
|
530
|
+
if (detail?.error) toolMeta.error = detail.error;
|
|
531
|
+
const toolStart = detail?.start_time ?? beginTime;
|
|
532
|
+
const toolEnd = detail?.end_time ?? endTime;
|
|
533
|
+
const toolLat = latencySeconds(toolStart, toolEnd);
|
|
534
|
+
spans.push({
|
|
535
|
+
trace_unique_id: traceUniqueId,
|
|
536
|
+
span_unique_id: `gcli_${safeId}_${turnTs}_tool_${toolIdx + 1}`,
|
|
537
|
+
span_parent_id: rootSpanId,
|
|
538
|
+
span_name: `Tool: ${displayName}`,
|
|
539
|
+
span_workflow_name: workflowName,
|
|
540
|
+
span_path: toolName ? `tool_${toolName}` : "tool_call",
|
|
541
|
+
provider_id: "",
|
|
542
|
+
metadata: toolMeta,
|
|
543
|
+
input: toolInputStr,
|
|
544
|
+
output: truncate(toolOutput, MAX_CHARS),
|
|
545
|
+
timestamp: toolEnd,
|
|
546
|
+
start_time: toolStart,
|
|
547
|
+
...toolLat !== void 0 ? { latency: toolLat } : {}
|
|
548
|
+
});
|
|
549
|
+
toolIdx++;
|
|
550
|
+
const nextDetail = toolDetails[toolIdx];
|
|
551
|
+
if (nextDetail && roundStarts[r + 1] && nextDetail.start_time && nextDetail.start_time > roundStarts[r + 1]) break;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
520
554
|
}
|
|
521
|
-
|
|
522
|
-
const detail = toolDetails[
|
|
555
|
+
while (toolIdx < toolDetails.length) {
|
|
556
|
+
const detail = toolDetails[toolIdx];
|
|
523
557
|
const toolName = detail?.name ?? "";
|
|
524
558
|
const toolArgs = detail?.args ?? detail?.input ?? {};
|
|
525
559
|
const toolOutput = detail?.output ?? "";
|
|
526
|
-
const displayName = toolName ? toolDisplayName(toolName) : `Call ${
|
|
560
|
+
const displayName = toolName ? toolDisplayName(toolName) : `Call ${toolIdx + 1}`;
|
|
527
561
|
const toolInputStr = toolName ? formatToolInput(toolName, toolArgs) : "";
|
|
528
562
|
const toolMeta = {};
|
|
529
563
|
if (toolName) toolMeta.tool_name = toolName;
|
|
@@ -533,7 +567,7 @@ function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurn
|
|
|
533
567
|
const toolLat = latencySeconds(toolStart, toolEnd);
|
|
534
568
|
spans.push({
|
|
535
569
|
trace_unique_id: traceUniqueId,
|
|
536
|
-
span_unique_id: `gcli_${safeId}_${turnTs}_tool_${
|
|
570
|
+
span_unique_id: `gcli_${safeId}_${turnTs}_tool_${toolIdx + 1}`,
|
|
537
571
|
span_parent_id: rootSpanId,
|
|
538
572
|
span_name: `Tool: ${displayName}`,
|
|
539
573
|
span_workflow_name: workflowName,
|
|
@@ -546,6 +580,23 @@ function buildSpans(hookData, outputText, tokens, config, startTimeIso, toolTurn
|
|
|
546
580
|
start_time: toolStart,
|
|
547
581
|
...toolLat !== void 0 ? { latency: toolLat } : {}
|
|
548
582
|
});
|
|
583
|
+
toolIdx++;
|
|
584
|
+
}
|
|
585
|
+
if (thoughtsTokens > 0) {
|
|
586
|
+
spans.push({
|
|
587
|
+
trace_unique_id: traceUniqueId,
|
|
588
|
+
span_unique_id: `gcli_${safeId}_${turnTs}_reasoning`,
|
|
589
|
+
span_parent_id: rootSpanId,
|
|
590
|
+
span_name: "Reasoning",
|
|
591
|
+
span_workflow_name: workflowName,
|
|
592
|
+
span_path: "reasoning",
|
|
593
|
+
provider_id: "",
|
|
594
|
+
metadata: { reasoning_tokens: thoughtsTokens },
|
|
595
|
+
input: "",
|
|
596
|
+
output: `[Reasoning: ${thoughtsTokens} tokens]`,
|
|
597
|
+
timestamp: endTime,
|
|
598
|
+
start_time: beginTime
|
|
599
|
+
});
|
|
549
600
|
}
|
|
550
601
|
return addDefaultsToAll(spans);
|
|
551
602
|
}
|
|
@@ -665,7 +716,6 @@ function processBeforeTool(hookData) {
|
|
|
665
716
|
pending.push({ name: toolName, input: toolInput, start_time: nowISO() });
|
|
666
717
|
state.pending_tools = pending;
|
|
667
718
|
state.send_version = (state.send_version ?? 0) + 1;
|
|
668
|
-
state.tool_turns = (state.tool_turns ?? 0) + 1;
|
|
669
719
|
saveStreamState(sessionId, state);
|
|
670
720
|
}
|
|
671
721
|
function processAfterTool(hookData) {
|
|
@@ -748,7 +798,8 @@ function processChunk(hookData) {
|
|
|
748
798
|
state.tool_turns = (state.tool_turns ?? 0) + 1;
|
|
749
799
|
state.send_version = (state.send_version ?? 0) + 1;
|
|
750
800
|
toolCallDetected = true;
|
|
751
|
-
|
|
801
|
+
state.current_round = (state.current_round ?? 0) + 1;
|
|
802
|
+
debug(`Tool call detected via msg_count (${savedMsgCount} \u2192 ${currentMsgCount}), tool_turns=${state.tool_turns}, round=${state.current_round}`);
|
|
752
803
|
}
|
|
753
804
|
}
|
|
754
805
|
state.msg_count = currentMsgCount;
|
|
@@ -757,10 +808,15 @@ function processChunk(hookData) {
|
|
|
757
808
|
state.accumulated_text += chunkText;
|
|
758
809
|
state.last_tokens = completionTokens || state.last_tokens;
|
|
759
810
|
if (thoughtsTokens > 0) state.thoughts_tokens = thoughtsTokens;
|
|
760
|
-
|
|
761
|
-
|
|
811
|
+
const round = state.current_round ?? 0;
|
|
812
|
+
if (!state.text_rounds) state.text_rounds = [];
|
|
813
|
+
if (!state.round_start_times) state.round_start_times = [];
|
|
814
|
+
while (state.text_rounds.length <= round) state.text_rounds.push("");
|
|
815
|
+
while (state.round_start_times.length <= round) state.round_start_times.push("");
|
|
816
|
+
state.text_rounds[round] += chunkText;
|
|
817
|
+
if (!state.round_start_times[round]) state.round_start_times[round] = nowISO();
|
|
762
818
|
saveStreamState(sessionId, state);
|
|
763
|
-
debug(`Accumulated chunk: +${chunkText.length} chars, total=${state.accumulated_text.length}`);
|
|
819
|
+
debug(`Accumulated chunk: +${chunkText.length} chars, total=${state.accumulated_text.length}, round=${round}`);
|
|
764
820
|
}
|
|
765
821
|
const isToolTurn = hasToolCall || ["TOOL_CALLS", "FUNCTION_CALL", "TOOL_USE"].includes(finishReason);
|
|
766
822
|
if (isToolTurn) {
|
|
@@ -800,7 +856,9 @@ function processChunk(hookData) {
|
|
|
800
856
|
state.first_chunk_time || void 0,
|
|
801
857
|
state.tool_turns ?? 0,
|
|
802
858
|
state.tool_details ?? [],
|
|
803
|
-
state.thoughts_tokens ?? 0
|
|
859
|
+
state.thoughts_tokens ?? 0,
|
|
860
|
+
state.text_rounds ?? [],
|
|
861
|
+
state.round_start_times ?? []
|
|
804
862
|
);
|
|
805
863
|
if (isFinished && chunkText) {
|
|
806
864
|
debug(`Immediate send (text+STOP, tool_turns=${state.tool_turns ?? 0}), ${state.accumulated_text.length} chars`);
|
|
@@ -814,35 +872,30 @@ function processChunk(hookData) {
|
|
|
814
872
|
debug(`Delayed send (version=${state.send_version}, delay=${SEND_DELAY}s), ${state.accumulated_text.length} chars`);
|
|
815
873
|
launchDelayedSend(sessionId, state.send_version, spans, creds.apiKey, creds.baseUrl);
|
|
816
874
|
}
|
|
817
|
-
function
|
|
875
|
+
function processChunkInWorker(dataFile) {
|
|
818
876
|
try {
|
|
877
|
+
const raw = fs2.readFileSync(dataFile, "utf-8");
|
|
878
|
+
fs2.unlinkSync(dataFile);
|
|
819
879
|
if (!raw.trim()) return;
|
|
820
880
|
const hookData = JSON.parse(raw);
|
|
821
|
-
const event = String(hookData.hook_event_name ?? "");
|
|
822
881
|
const unlock = acquireLock(LOCK_PATH);
|
|
823
882
|
try {
|
|
824
|
-
|
|
825
|
-
processBeforeTool(hookData);
|
|
826
|
-
} else if (event === "AfterTool") {
|
|
827
|
-
processAfterTool(hookData);
|
|
828
|
-
} else {
|
|
829
|
-
processChunk(hookData);
|
|
830
|
-
}
|
|
883
|
+
processChunk(hookData);
|
|
831
884
|
} finally {
|
|
832
885
|
unlock?.();
|
|
833
886
|
}
|
|
834
887
|
} catch (e) {
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
888
|
+
log("ERROR", `Worker error: ${e}`);
|
|
889
|
+
try {
|
|
890
|
+
fs2.unlinkSync(dataFile);
|
|
891
|
+
} catch {
|
|
839
892
|
}
|
|
840
893
|
}
|
|
841
894
|
}
|
|
842
895
|
function main() {
|
|
843
896
|
if (process.env._RESPAN_GEM_WORKER === "1") {
|
|
844
|
-
const
|
|
845
|
-
|
|
897
|
+
const dataFile = process.env._RESPAN_GEM_FILE ?? "";
|
|
898
|
+
if (dataFile) processChunkInWorker(dataFile);
|
|
846
899
|
return;
|
|
847
900
|
}
|
|
848
901
|
let raw = "";
|
|
@@ -855,15 +908,34 @@ function main() {
|
|
|
855
908
|
process.exit(0);
|
|
856
909
|
}
|
|
857
910
|
try {
|
|
858
|
-
const
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
911
|
+
const hookData = JSON.parse(raw);
|
|
912
|
+
const event = String(hookData.hook_event_name ?? "");
|
|
913
|
+
if (event === "BeforeTool" || event === "AfterTool") {
|
|
914
|
+
const unlock = acquireLock(LOCK_PATH);
|
|
915
|
+
try {
|
|
916
|
+
if (event === "BeforeTool") processBeforeTool(hookData);
|
|
917
|
+
else processAfterTool(hookData);
|
|
918
|
+
} finally {
|
|
919
|
+
unlock?.();
|
|
920
|
+
}
|
|
921
|
+
} else {
|
|
922
|
+
const dataFile = path2.join(STATE_DIR, `respan_chunk_${process.pid}.json`);
|
|
923
|
+
fs2.mkdirSync(STATE_DIR, { recursive: true });
|
|
924
|
+
fs2.writeFileSync(dataFile, raw);
|
|
925
|
+
try {
|
|
926
|
+
const scriptPath = __filename || process.argv[1];
|
|
927
|
+
const child = (0, import_node_child_process.execFile)("node", [scriptPath], {
|
|
928
|
+
env: { ...process.env, _RESPAN_GEM_WORKER: "1", _RESPAN_GEM_FILE: dataFile },
|
|
929
|
+
stdio: "ignore",
|
|
930
|
+
detached: true
|
|
931
|
+
});
|
|
932
|
+
child.unref();
|
|
933
|
+
} catch (e) {
|
|
934
|
+
processChunkInWorker(dataFile);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
865
937
|
} catch (e) {
|
|
866
|
-
|
|
938
|
+
log("ERROR", `Hook error: ${e}`);
|
|
867
939
|
}
|
|
868
940
|
process.exit(0);
|
|
869
941
|
}
|