nolo-cli 0.1.48 → 0.1.49
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/index.js +120 -40
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -3436,6 +3436,35 @@ function accumulateToolCallDelta(accumulated, deltas) {
|
|
|
3436
3436
|
function finalizeAccumulatedToolCalls(accumulated) {
|
|
3437
3437
|
return Object.keys(accumulated).map((key2) => accumulated[Number(key2)]).filter((call) => call?.function?.name);
|
|
3438
3438
|
}
|
|
3439
|
+
function processOpenAiCompatibleSseEvent(event, state) {
|
|
3440
|
+
for (const line of event.split("\n")) {
|
|
3441
|
+
const trimmed = line.trim();
|
|
3442
|
+
if (!trimmed.startsWith("data:")) continue;
|
|
3443
|
+
const payload = trimmed.slice(5).trim();
|
|
3444
|
+
if (!payload || payload === "[DONE]") continue;
|
|
3445
|
+
let parsed;
|
|
3446
|
+
try {
|
|
3447
|
+
parsed = JSON.parse(payload);
|
|
3448
|
+
} catch {
|
|
3449
|
+
continue;
|
|
3450
|
+
}
|
|
3451
|
+
if (parsed?.usage && typeof parsed.usage === "object") {
|
|
3452
|
+
state.usage = parsed.usage;
|
|
3453
|
+
}
|
|
3454
|
+
const delta = parsed?.choices?.[0]?.delta;
|
|
3455
|
+
if (!delta || typeof delta !== "object") continue;
|
|
3456
|
+
const reasoningChunk = typeof delta.reasoning_content === "string" ? delta.reasoning_content : typeof delta.reasoning === "string" ? delta.reasoning : "";
|
|
3457
|
+
if (reasoningChunk) state.reasoning += reasoningChunk;
|
|
3458
|
+
if (Array.isArray(delta.tool_calls) && delta.tool_calls.length > 0) {
|
|
3459
|
+
accumulateToolCallDelta(state.accumulatedToolCalls, delta.tool_calls);
|
|
3460
|
+
}
|
|
3461
|
+
const textChunk = typeof delta.content === "string" ? delta.content : "";
|
|
3462
|
+
if (textChunk) {
|
|
3463
|
+
state.content += textChunk;
|
|
3464
|
+
state.onTextDelta?.(textChunk);
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
}
|
|
3439
3468
|
async function readOpenAiCompatibleSseCompletion(args2) {
|
|
3440
3469
|
const reader = args2.response.body?.getReader();
|
|
3441
3470
|
if (!reader) {
|
|
@@ -3443,10 +3472,13 @@ async function readOpenAiCompatibleSseCompletion(args2) {
|
|
|
3443
3472
|
}
|
|
3444
3473
|
const decoder = new TextDecoder();
|
|
3445
3474
|
let buffer = "";
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3475
|
+
const state = {
|
|
3476
|
+
content: "",
|
|
3477
|
+
reasoning: "",
|
|
3478
|
+
usage: void 0,
|
|
3479
|
+
accumulatedToolCalls: {},
|
|
3480
|
+
onTextDelta: args2.onTextDelta
|
|
3481
|
+
};
|
|
3450
3482
|
while (true) {
|
|
3451
3483
|
const { done, value } = await reader.read();
|
|
3452
3484
|
if (done) break;
|
|
@@ -3456,41 +3488,19 @@ async function readOpenAiCompatibleSseCompletion(args2) {
|
|
|
3456
3488
|
if (boundary === -1) break;
|
|
3457
3489
|
const event = buffer.slice(0, boundary);
|
|
3458
3490
|
buffer = buffer.slice(boundary + 2);
|
|
3459
|
-
|
|
3460
|
-
const trimmed = line.trim();
|
|
3461
|
-
if (!trimmed.startsWith("data:")) continue;
|
|
3462
|
-
const payload = trimmed.slice(5).trim();
|
|
3463
|
-
if (!payload || payload === "[DONE]") continue;
|
|
3464
|
-
let parsed;
|
|
3465
|
-
try {
|
|
3466
|
-
parsed = JSON.parse(payload);
|
|
3467
|
-
} catch {
|
|
3468
|
-
continue;
|
|
3469
|
-
}
|
|
3470
|
-
if (parsed?.usage && typeof parsed.usage === "object") {
|
|
3471
|
-
usage2 = parsed.usage;
|
|
3472
|
-
}
|
|
3473
|
-
const delta = parsed?.choices?.[0]?.delta;
|
|
3474
|
-
if (!delta || typeof delta !== "object") continue;
|
|
3475
|
-
const reasoningChunk = typeof delta.reasoning_content === "string" ? delta.reasoning_content : typeof delta.reasoning === "string" ? delta.reasoning : "";
|
|
3476
|
-
if (reasoningChunk) reasoning += reasoningChunk;
|
|
3477
|
-
if (Array.isArray(delta.tool_calls) && delta.tool_calls.length > 0) {
|
|
3478
|
-
accumulateToolCallDelta(accumulatedToolCalls, delta.tool_calls);
|
|
3479
|
-
}
|
|
3480
|
-
const textChunk = typeof delta.content === "string" ? delta.content : "";
|
|
3481
|
-
if (textChunk) {
|
|
3482
|
-
content += textChunk;
|
|
3483
|
-
args2.onTextDelta?.(textChunk);
|
|
3484
|
-
}
|
|
3485
|
-
}
|
|
3491
|
+
processOpenAiCompatibleSseEvent(event, state);
|
|
3486
3492
|
}
|
|
3487
3493
|
}
|
|
3488
|
-
|
|
3494
|
+
buffer += decoder.decode();
|
|
3495
|
+
if (buffer.trim()) {
|
|
3496
|
+
processOpenAiCompatibleSseEvent(buffer, state);
|
|
3497
|
+
}
|
|
3498
|
+
const tool_calls = finalizeAccumulatedToolCalls(state.accumulatedToolCalls);
|
|
3489
3499
|
return {
|
|
3490
|
-
content,
|
|
3491
|
-
...reasoning ? { reasoning_content: reasoning } : {},
|
|
3500
|
+
content: state.content,
|
|
3501
|
+
...state.reasoning ? { reasoning_content: state.reasoning } : {},
|
|
3492
3502
|
...tool_calls.length > 0 ? { tool_calls } : {},
|
|
3493
|
-
...
|
|
3503
|
+
...state.usage ? { usage: state.usage } : {}
|
|
3494
3504
|
};
|
|
3495
3505
|
}
|
|
3496
3506
|
async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
@@ -64754,7 +64764,9 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64754
64764
|
const data2 = parsePlatformChatCompletionData(raw2);
|
|
64755
64765
|
throw new Error(`platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`);
|
|
64756
64766
|
}
|
|
64757
|
-
|
|
64767
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
64768
|
+
const shouldStream = Boolean(stream && options?.onTextDelta) && contentType.includes("text/event-stream");
|
|
64769
|
+
if (shouldStream && options?.onTextDelta) {
|
|
64758
64770
|
const streamed = await readOpenAiCompatibleSseCompletion({
|
|
64759
64771
|
response: res,
|
|
64760
64772
|
onTextDelta: options.onTextDelta
|
|
@@ -68114,6 +68126,64 @@ function formatAssistantDisplay(text, mode = "rich") {
|
|
|
68114
68126
|
}
|
|
68115
68127
|
return polished.split("\n").map((line) => styleRichMarkdownLine(line)).join("\n");
|
|
68116
68128
|
}
|
|
68129
|
+
function emitFormattedAssistantBlock(write2, text, renderMode, trailingNewline = false) {
|
|
68130
|
+
if (!text) return;
|
|
68131
|
+
write2(formatAssistantDisplay(text, renderMode));
|
|
68132
|
+
if (trailingNewline) write2("\n");
|
|
68133
|
+
}
|
|
68134
|
+
function createRenderAwareStreamWriter(args2) {
|
|
68135
|
+
let buffer = "";
|
|
68136
|
+
const flushCompleteBlocks = () => {
|
|
68137
|
+
if (args2.renderMode === "plain") {
|
|
68138
|
+
if (!buffer) return;
|
|
68139
|
+
args2.write(buffer);
|
|
68140
|
+
buffer = "";
|
|
68141
|
+
return;
|
|
68142
|
+
}
|
|
68143
|
+
while (buffer.includes("\n")) {
|
|
68144
|
+
const lines = buffer.split("\n");
|
|
68145
|
+
if (lines.length < 2) break;
|
|
68146
|
+
if (isTableRow(lines[0] ?? "") && isTableSeparator(lines[1] ?? "")) {
|
|
68147
|
+
let end = 2;
|
|
68148
|
+
while (end < lines.length && isTableRow(lines[end] ?? "") && !isTableSeparator(lines[end] ?? "")) {
|
|
68149
|
+
end += 1;
|
|
68150
|
+
}
|
|
68151
|
+
const tableComplete = end < lines.length || buffer.endsWith("\n");
|
|
68152
|
+
if (!tableComplete) break;
|
|
68153
|
+
emitFormattedAssistantBlock(
|
|
68154
|
+
args2.write,
|
|
68155
|
+
lines.slice(0, end).join("\n"),
|
|
68156
|
+
args2.renderMode,
|
|
68157
|
+
true
|
|
68158
|
+
);
|
|
68159
|
+
buffer = lines.slice(end).join("\n");
|
|
68160
|
+
continue;
|
|
68161
|
+
}
|
|
68162
|
+
emitFormattedAssistantBlock(args2.write, lines[0] ?? "", args2.renderMode, true);
|
|
68163
|
+
buffer = lines.slice(1).join("\n");
|
|
68164
|
+
}
|
|
68165
|
+
};
|
|
68166
|
+
return {
|
|
68167
|
+
push(chunk) {
|
|
68168
|
+
if (!chunk) return;
|
|
68169
|
+
if (args2.renderMode === "plain") {
|
|
68170
|
+
args2.write(chunk);
|
|
68171
|
+
return;
|
|
68172
|
+
}
|
|
68173
|
+
buffer += chunk;
|
|
68174
|
+
flushCompleteBlocks();
|
|
68175
|
+
},
|
|
68176
|
+
flush() {
|
|
68177
|
+
if (!buffer) return;
|
|
68178
|
+
if (args2.renderMode === "plain") {
|
|
68179
|
+
args2.write(buffer);
|
|
68180
|
+
} else {
|
|
68181
|
+
emitFormattedAssistantBlock(args2.write, buffer, args2.renderMode);
|
|
68182
|
+
}
|
|
68183
|
+
buffer = "";
|
|
68184
|
+
}
|
|
68185
|
+
};
|
|
68186
|
+
}
|
|
68117
68187
|
|
|
68118
68188
|
// packages/cli/client/thinkingOutput.ts
|
|
68119
68189
|
var THINK_OPEN = /<think>/i;
|
|
@@ -68920,12 +68990,16 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68920
68990
|
const traceLocalTools = shouldEmitToolEvents(toolDisplayMode);
|
|
68921
68991
|
const formatToolEvent = createToolEventFormatter(toolDisplayMode);
|
|
68922
68992
|
const eventMode = resolveAgentEventMode(options);
|
|
68923
|
-
let wroteToolTrace = false;
|
|
68924
68993
|
let streamedAssistantText = false;
|
|
68925
68994
|
let printedAssistantLabel = false;
|
|
68926
68995
|
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
68996
|
+
const renderMode = resolveRenderDisplayMode(options.env);
|
|
68997
|
+
const renderWriter = createRenderAwareStreamWriter({
|
|
68998
|
+
write: (chunk) => options.output.write(chunk),
|
|
68999
|
+
renderMode
|
|
69000
|
+
});
|
|
68927
69001
|
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
68928
|
-
(chunk) =>
|
|
69002
|
+
(chunk) => renderWriter.push(chunk),
|
|
68929
69003
|
thinkingMode
|
|
68930
69004
|
);
|
|
68931
69005
|
const subjectRefs = buildSubjectRefs(options);
|
|
@@ -68959,7 +69033,6 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68959
69033
|
spinner.stop();
|
|
68960
69034
|
const chunk = eventMode === "jsonl" ? formatToolJsonEvent(event) : formatToolEvent(event);
|
|
68961
69035
|
if (chunk) {
|
|
68962
|
-
wroteToolTrace = true;
|
|
68963
69036
|
options.output.write(chunk);
|
|
68964
69037
|
}
|
|
68965
69038
|
}
|
|
@@ -68980,6 +69053,7 @@ ${options.agentName} > `);
|
|
|
68980
69053
|
spinner.stop();
|
|
68981
69054
|
if (streamedAssistantText) {
|
|
68982
69055
|
thinkingFilter.flush();
|
|
69056
|
+
renderWriter.flush();
|
|
68983
69057
|
options.output.write("\n");
|
|
68984
69058
|
} else {
|
|
68985
69059
|
const content = formatAssistantResponseForCli(result.content.trim(), options);
|
|
@@ -69017,8 +69091,13 @@ async function readStreamingAgentRun(options, res) {
|
|
|
69017
69091
|
}
|
|
69018
69092
|
const decoder = new TextDecoder();
|
|
69019
69093
|
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
69094
|
+
const renderMode = resolveRenderDisplayMode(options.env);
|
|
69095
|
+
const renderWriter = createRenderAwareStreamWriter({
|
|
69096
|
+
write: (chunk) => options.output.write(chunk),
|
|
69097
|
+
renderMode
|
|
69098
|
+
});
|
|
69020
69099
|
const writer = createStreamingTextWriter({
|
|
69021
|
-
write: (chunk) =>
|
|
69100
|
+
write: (chunk) => renderWriter.push(chunk)
|
|
69022
69101
|
});
|
|
69023
69102
|
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
69024
69103
|
(chunk) => writer.push(chunk),
|
|
@@ -69091,6 +69170,7 @@ ${options.agentName} > `);
|
|
|
69091
69170
|
} finally {
|
|
69092
69171
|
writer.flushAll();
|
|
69093
69172
|
thinkingFilter.flush();
|
|
69173
|
+
renderWriter.flush();
|
|
69094
69174
|
}
|
|
69095
69175
|
if (!content) {
|
|
69096
69176
|
options.output.write(`
|