nolo-cli 0.1.47 → 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 +1567 -180
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1473,7 +1473,9 @@ var init_agentAliases = __esm({
|
|
|
1473
1473
|
grok: LOCAL_GROK_AGENT_KEY,
|
|
1474
1474
|
"grok-agent": LOCAL_GROK_AGENT_KEY,
|
|
1475
1475
|
"grok cli": LOCAL_GROK_AGENT_KEY,
|
|
1476
|
-
"grok-cli": LOCAL_GROK_AGENT_KEY
|
|
1476
|
+
"grok-cli": LOCAL_GROK_AGENT_KEY,
|
|
1477
|
+
"minimax-m3": "agent-0e95801d90-minimax-m3",
|
|
1478
|
+
minimax: "agent-0e95801d90-minimax-m3"
|
|
1477
1479
|
};
|
|
1478
1480
|
}
|
|
1479
1481
|
});
|
|
@@ -1602,6 +1604,19 @@ function buildMessages(args2) {
|
|
|
1602
1604
|
{ role: "user", content: args2.input }
|
|
1603
1605
|
];
|
|
1604
1606
|
}
|
|
1607
|
+
function mergeTurnUsage(current, next) {
|
|
1608
|
+
if (!next) return current;
|
|
1609
|
+
const read2 = (usage2) => ({
|
|
1610
|
+
input: Number(usage2.input_tokens ?? usage2.prompt_tokens ?? 0),
|
|
1611
|
+
output: Number(usage2.output_tokens ?? usage2.completion_tokens ?? 0)
|
|
1612
|
+
});
|
|
1613
|
+
const right = read2(next);
|
|
1614
|
+
const left = current ? read2(current) : { input: 0, output: 0 };
|
|
1615
|
+
return {
|
|
1616
|
+
input_tokens: right.input || left.input,
|
|
1617
|
+
output_tokens: left.output + right.output
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1605
1620
|
function extractUserInputText(content) {
|
|
1606
1621
|
if (typeof content === "string") return content;
|
|
1607
1622
|
if (!Array.isArray(content)) return "";
|
|
@@ -1627,11 +1642,14 @@ async function runLocalAgentTurn(input2) {
|
|
|
1627
1642
|
const userInputText = extractUserInputText(input2.input);
|
|
1628
1643
|
let toolCallCount = 0;
|
|
1629
1644
|
let result;
|
|
1645
|
+
let turnUsage;
|
|
1630
1646
|
let round = 0;
|
|
1631
1647
|
while (true) {
|
|
1632
1648
|
result = await provider.complete(messages, {
|
|
1633
|
-
...typeof input2.timeoutMs === "number" ? { timeoutMs: input2.timeoutMs } : {}
|
|
1649
|
+
...typeof input2.timeoutMs === "number" ? { timeoutMs: input2.timeoutMs } : {},
|
|
1650
|
+
...input2.onTextDelta ? { onTextDelta: input2.onTextDelta } : {}
|
|
1634
1651
|
});
|
|
1652
|
+
turnUsage = mergeTurnUsage(turnUsage, result.usage);
|
|
1635
1653
|
const toolCalls = result.tool_calls ?? [];
|
|
1636
1654
|
if (toolCalls.length === 0) break;
|
|
1637
1655
|
toolCallCount += toolCalls.length;
|
|
@@ -1724,6 +1742,7 @@ async function runLocalAgentTurn(input2) {
|
|
|
1724
1742
|
});
|
|
1725
1743
|
return {
|
|
1726
1744
|
...result,
|
|
1745
|
+
...turnUsage ? { usage: turnUsage } : {},
|
|
1727
1746
|
...toolCallCount > 0 ? { toolCallCount } : {},
|
|
1728
1747
|
...agentConfig.toolSurface ? { runtimeToolSurface: agentConfig.toolSurface } : {},
|
|
1729
1748
|
dialogId: saved.dialogId,
|
|
@@ -3359,9 +3378,10 @@ function buildOpenAiCompatibleChatCompletionRequest(args2) {
|
|
|
3359
3378
|
const body = {
|
|
3360
3379
|
model: args2.providerConfig.model,
|
|
3361
3380
|
messages: toOpenAiCompatibleMessages(args2.messages),
|
|
3362
|
-
stream: false,
|
|
3381
|
+
stream: args2.stream ?? false,
|
|
3363
3382
|
...args2.providerConfig.requestOptions,
|
|
3364
|
-
...args2.tools && args2.tools.length > 0 ? { tools: args2.tools } : {}
|
|
3383
|
+
...args2.tools && args2.tools.length > 0 ? { tools: args2.tools } : {},
|
|
3384
|
+
...args2.stream ? { stream_options: { include_usage: true } } : {}
|
|
3365
3385
|
};
|
|
3366
3386
|
return {
|
|
3367
3387
|
url: args2.providerConfig.endpoint,
|
|
@@ -3391,6 +3411,148 @@ function parseOpenAiCompatibleChatCompletionResponse(args2) {
|
|
|
3391
3411
|
trace: args2.trace
|
|
3392
3412
|
};
|
|
3393
3413
|
}
|
|
3414
|
+
function accumulateToolCallDelta(accumulated, deltas) {
|
|
3415
|
+
for (const delta of deltas) {
|
|
3416
|
+
const index = typeof delta.index === "number" ? delta.index : 0;
|
|
3417
|
+
const current = accumulated[index] ?? {
|
|
3418
|
+
id: "",
|
|
3419
|
+
type: "function",
|
|
3420
|
+
function: { name: "", arguments: "" }
|
|
3421
|
+
};
|
|
3422
|
+
if (typeof delta.id === "string" && delta.id) current.id = delta.id;
|
|
3423
|
+
const fn = delta.function;
|
|
3424
|
+
if (fn && typeof fn === "object") {
|
|
3425
|
+
const functionDelta = fn;
|
|
3426
|
+
if (typeof functionDelta.name === "string" && functionDelta.name) {
|
|
3427
|
+
current.function.name += functionDelta.name;
|
|
3428
|
+
}
|
|
3429
|
+
if (typeof functionDelta.arguments === "string" && functionDelta.arguments) {
|
|
3430
|
+
current.function.arguments += functionDelta.arguments;
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
accumulated[index] = current;
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
function finalizeAccumulatedToolCalls(accumulated) {
|
|
3437
|
+
return Object.keys(accumulated).map((key2) => accumulated[Number(key2)]).filter((call) => call?.function?.name);
|
|
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
|
+
}
|
|
3468
|
+
async function readOpenAiCompatibleSseCompletion(args2) {
|
|
3469
|
+
const reader = args2.response.body?.getReader();
|
|
3470
|
+
if (!reader) {
|
|
3471
|
+
throw new Error("OpenAI-compatible stream response did not include a readable body.");
|
|
3472
|
+
}
|
|
3473
|
+
const decoder = new TextDecoder();
|
|
3474
|
+
let buffer = "";
|
|
3475
|
+
const state = {
|
|
3476
|
+
content: "",
|
|
3477
|
+
reasoning: "",
|
|
3478
|
+
usage: void 0,
|
|
3479
|
+
accumulatedToolCalls: {},
|
|
3480
|
+
onTextDelta: args2.onTextDelta
|
|
3481
|
+
};
|
|
3482
|
+
while (true) {
|
|
3483
|
+
const { done, value } = await reader.read();
|
|
3484
|
+
if (done) break;
|
|
3485
|
+
buffer += decoder.decode(value, { stream: true });
|
|
3486
|
+
while (true) {
|
|
3487
|
+
const boundary = buffer.indexOf("\n\n");
|
|
3488
|
+
if (boundary === -1) break;
|
|
3489
|
+
const event = buffer.slice(0, boundary);
|
|
3490
|
+
buffer = buffer.slice(boundary + 2);
|
|
3491
|
+
processOpenAiCompatibleSseEvent(event, state);
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
buffer += decoder.decode();
|
|
3495
|
+
if (buffer.trim()) {
|
|
3496
|
+
processOpenAiCompatibleSseEvent(buffer, state);
|
|
3497
|
+
}
|
|
3498
|
+
const tool_calls = finalizeAccumulatedToolCalls(state.accumulatedToolCalls);
|
|
3499
|
+
return {
|
|
3500
|
+
content: state.content,
|
|
3501
|
+
...state.reasoning ? { reasoning_content: state.reasoning } : {},
|
|
3502
|
+
...tool_calls.length > 0 ? { tool_calls } : {},
|
|
3503
|
+
...state.usage ? { usage: state.usage } : {}
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
3507
|
+
const request = buildOpenAiCompatibleChatCompletionRequest({
|
|
3508
|
+
providerConfig: args2.providerConfig,
|
|
3509
|
+
messages: args2.messages,
|
|
3510
|
+
tools: args2.tools,
|
|
3511
|
+
stream: args2.stream
|
|
3512
|
+
});
|
|
3513
|
+
const res = await args2.fetchImpl(request.url, {
|
|
3514
|
+
...request.init,
|
|
3515
|
+
...args2.signal ? { signal: args2.signal } : {}
|
|
3516
|
+
});
|
|
3517
|
+
if (!res.ok) {
|
|
3518
|
+
const raw2 = await res.text().catch(() => "");
|
|
3519
|
+
let data2 = raw2;
|
|
3520
|
+
try {
|
|
3521
|
+
data2 = JSON.parse(raw2);
|
|
3522
|
+
} catch {
|
|
3523
|
+
}
|
|
3524
|
+
throw new Error(`local provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`);
|
|
3525
|
+
}
|
|
3526
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
3527
|
+
const shouldStream = Boolean(args2.stream && args2.onTextDelta) && contentType.includes("text/event-stream");
|
|
3528
|
+
if (shouldStream && args2.onTextDelta) {
|
|
3529
|
+
const streamed = await readOpenAiCompatibleSseCompletion({
|
|
3530
|
+
response: res,
|
|
3531
|
+
onTextDelta: args2.onTextDelta
|
|
3532
|
+
});
|
|
3533
|
+
return {
|
|
3534
|
+
content: streamed.content,
|
|
3535
|
+
model: args2.providerConfig.model,
|
|
3536
|
+
provider: args2.providerConfig.provider,
|
|
3537
|
+
...streamed.tool_calls ? { tool_calls: streamed.tool_calls } : {},
|
|
3538
|
+
...streamed.reasoning_content ? { reasoning_content: streamed.reasoning_content } : {},
|
|
3539
|
+
...streamed.usage ? { usage: streamed.usage } : {},
|
|
3540
|
+
trace: args2.messages
|
|
3541
|
+
};
|
|
3542
|
+
}
|
|
3543
|
+
const raw = await res.text().catch(() => "");
|
|
3544
|
+
let data = {};
|
|
3545
|
+
try {
|
|
3546
|
+
data = raw ? JSON.parse(raw) : {};
|
|
3547
|
+
} catch {
|
|
3548
|
+
data = {};
|
|
3549
|
+
}
|
|
3550
|
+
return parseOpenAiCompatibleChatCompletionResponse({
|
|
3551
|
+
providerConfig: args2.providerConfig,
|
|
3552
|
+
data,
|
|
3553
|
+
trace: args2.messages
|
|
3554
|
+
});
|
|
3555
|
+
}
|
|
3394
3556
|
var init_openAiCompatibleProvider = __esm({
|
|
3395
3557
|
"packages/agent-runtime/openAiCompatibleProvider.ts"() {
|
|
3396
3558
|
"use strict";
|
|
@@ -3688,7 +3850,8 @@ function buildPlatformChatCompletionRequest(args2) {
|
|
|
3688
3850
|
const body = {
|
|
3689
3851
|
model: args2.providerConfig.model,
|
|
3690
3852
|
...usesResponsesApi ? { input: convertMessagesToResponsesInput(args2.messages) } : { messages: toOpenAiCompatibleMessages2(args2.messages) },
|
|
3691
|
-
stream: false,
|
|
3853
|
+
stream: args2.stream ?? false,
|
|
3854
|
+
...args2.stream ? { stream_options: { include_usage: true } } : {},
|
|
3692
3855
|
...requestOptions,
|
|
3693
3856
|
...args2.tools && args2.tools.length > 0 ? {
|
|
3694
3857
|
tools: usesResponsesApi ? toResponsesTools(args2.tools) : args2.tools,
|
|
@@ -10118,6 +10281,8 @@ var init_ai_locale = __esm({
|
|
|
10118
10281
|
creating: "Creating...",
|
|
10119
10282
|
edit: "Edit",
|
|
10120
10283
|
delete: "Delete",
|
|
10284
|
+
favorite: "Favorite",
|
|
10285
|
+
unfavorite: "Unfavorite",
|
|
10121
10286
|
confirmDelete: "Confirm Delete",
|
|
10122
10287
|
resetToDefaults: "Reset to Defaults",
|
|
10123
10288
|
loading: "Loading...",
|
|
@@ -10429,6 +10594,8 @@ var init_ai_locale = __esm({
|
|
|
10429
10594
|
creating: "\u521B\u5EFA\u4E2D...",
|
|
10430
10595
|
edit: "\u7F16\u8F91",
|
|
10431
10596
|
delete: "\u5220\u9664",
|
|
10597
|
+
favorite: "\u6536\u85CF",
|
|
10598
|
+
unfavorite: "\u53D6\u6D88\u6536\u85CF",
|
|
10432
10599
|
confirmDelete: "\u786E\u8BA4\u5220\u9664",
|
|
10433
10600
|
resetToDefaults: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u503C",
|
|
10434
10601
|
loading: "\u52A0\u8F7D\u4E2D...",
|
|
@@ -10741,6 +10908,8 @@ var init_ai_locale = __esm({
|
|
|
10741
10908
|
creating: "\u5EFA\u7ACB\u4E2D...",
|
|
10742
10909
|
edit: "\u7DE8\u8F2F",
|
|
10743
10910
|
delete: "\u522A\u9664",
|
|
10911
|
+
favorite: "\u6536\u85CF",
|
|
10912
|
+
unfavorite: "\u53D6\u6D88\u6536\u85CF",
|
|
10744
10913
|
confirmDelete: "\u78BA\u8A8D\u522A\u9664",
|
|
10745
10914
|
resetToDefaults: "\u91CD\u8A2D\u70BA\u9810\u8A2D\u503C",
|
|
10746
10915
|
loading: "\u8F09\u5165\u4E2D...",
|
|
@@ -10976,6 +11145,8 @@ var init_ai_locale = __esm({
|
|
|
10976
11145
|
creating: "\u4F5C\u6210\u4E2D...",
|
|
10977
11146
|
edit: "\u7DE8\u96C6",
|
|
10978
11147
|
delete: "\u524A\u9664",
|
|
11148
|
+
favorite: "\u304A\u6C17\u306B\u5165\u308A",
|
|
11149
|
+
unfavorite: "\u304A\u6C17\u306B\u5165\u308A\u89E3\u9664",
|
|
10979
11150
|
confirmDelete: "\u524A\u9664\u306E\u78BA\u8A8D",
|
|
10980
11151
|
resetToDefaults: "\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u30EA\u30BB\u30C3\u30C8",
|
|
10981
11152
|
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D...",
|
|
@@ -13051,6 +13222,31 @@ var init_interface_locale = __esm({
|
|
|
13051
13222
|
stop: "Stop",
|
|
13052
13223
|
refresh: "Refresh"
|
|
13053
13224
|
},
|
|
13225
|
+
productivity: {
|
|
13226
|
+
title: "Productivity",
|
|
13227
|
+
default_space: {
|
|
13228
|
+
title: "Default startup space",
|
|
13229
|
+
description: "Choose the workspace you land in after signing in to get into flow faster.",
|
|
13230
|
+
all: "All (no fixed default space)"
|
|
13231
|
+
},
|
|
13232
|
+
shortcuts: {
|
|
13233
|
+
title: "Keyboard shortcuts",
|
|
13234
|
+
description: "View and customize shortcuts for common actions to keep your workflow smooth.",
|
|
13235
|
+
sendMessage: "Send message",
|
|
13236
|
+
newChat: "New chat",
|
|
13237
|
+
deleteDialog: "Delete current conversation",
|
|
13238
|
+
clickToRecord: "Click to change shortcut",
|
|
13239
|
+
updated: "Shortcut updated",
|
|
13240
|
+
pressKeys: "Press shortcut keys...",
|
|
13241
|
+
none: "Disabled",
|
|
13242
|
+
cleared: "Shortcut disabled",
|
|
13243
|
+
clearError: "Failed to disable shortcut",
|
|
13244
|
+
clear: "Disable shortcut",
|
|
13245
|
+
resetSuccess: "Shortcut reset",
|
|
13246
|
+
resetError: "Failed to reset shortcut",
|
|
13247
|
+
reset: "Reset to default"
|
|
13248
|
+
}
|
|
13249
|
+
},
|
|
13054
13250
|
appearance: {
|
|
13055
13251
|
title: "Appearance",
|
|
13056
13252
|
theme: {
|
|
@@ -13744,6 +13940,31 @@ var init_interface_locale = __esm({
|
|
|
13744
13940
|
productivity: "\u6548\u7387",
|
|
13745
13941
|
secrets: "\u5BC6\u94A5"
|
|
13746
13942
|
},
|
|
13943
|
+
productivity: {
|
|
13944
|
+
title: "\u6548\u7387\u8BBE\u7F6E",
|
|
13945
|
+
default_space: {
|
|
13946
|
+
title: "\u9ED8\u8BA4\u542F\u52A8\u7A7A\u95F4",
|
|
13947
|
+
description: "\u9009\u62E9\u4F60\u767B\u5F55\u540E\u9ED8\u8BA4\u8FDB\u5165\u7684\u5DE5\u4F5C\u7A7A\u95F4\u3002\u8FD9\u80FD\u5E2E\u52A9\u4F60\u5FEB\u901F\u8FDB\u5165\u5DE5\u4F5C\u72B6\u6001\u3002",
|
|
13948
|
+
all: "\u5168\u90E8\uFF08\u4E0D\u56FA\u5B9A\u9ED8\u8BA4\u7A7A\u95F4\uFF09"
|
|
13949
|
+
},
|
|
13950
|
+
shortcuts: {
|
|
13951
|
+
title: "\u952E\u76D8\u5FEB\u6377\u952E",
|
|
13952
|
+
description: "\u67E5\u770B\u5E76\u7BA1\u7406\u5E38\u7528\u64CD\u4F5C\u7684\u5FEB\u6377\u952E\u914D\u7F6E\uFF0C\u8BA9\u4F60\u7684\u5DE5\u4F5C\u6D41\u66F4\u52A0\u987A\u7545\u3002",
|
|
13953
|
+
sendMessage: "\u53D1\u9001\u6D88\u606F",
|
|
13954
|
+
newChat: "\u65B0\u5EFA\u5BF9\u8BDD",
|
|
13955
|
+
deleteDialog: "\u5220\u9664\u5F53\u524D\u4F1A\u8BDD",
|
|
13956
|
+
clickToRecord: "\u70B9\u51FB\u4FEE\u6539\u5FEB\u6377\u952E",
|
|
13957
|
+
updated: "\u5FEB\u6377\u952E\u5DF2\u66F4\u65B0",
|
|
13958
|
+
pressKeys: "\u6309\u4E0B\u5FEB\u6377\u952E...",
|
|
13959
|
+
none: "\u5DF2\u7981\u7528",
|
|
13960
|
+
cleared: "\u5FEB\u6377\u952E\u5DF2\u7981\u7528",
|
|
13961
|
+
clearError: "\u7981\u7528\u5931\u8D25",
|
|
13962
|
+
clear: "\u7981\u7528\u5FEB\u6377\u952E",
|
|
13963
|
+
resetSuccess: "\u5FEB\u6377\u952E\u5DF2\u91CD\u7F6E",
|
|
13964
|
+
resetError: "\u91CD\u7F6E\u5931\u8D25",
|
|
13965
|
+
reset: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4"
|
|
13966
|
+
}
|
|
13967
|
+
},
|
|
13747
13968
|
appearance: {
|
|
13748
13969
|
title: "\u5916\u89C2",
|
|
13749
13970
|
theme: {
|
|
@@ -14438,6 +14659,31 @@ var init_interface_locale = __esm({
|
|
|
14438
14659
|
productivity: "\u6548\u7387",
|
|
14439
14660
|
secrets: "\u5BC6\u9470"
|
|
14440
14661
|
},
|
|
14662
|
+
productivity: {
|
|
14663
|
+
title: "\u6548\u7387\u8A2D\u5B9A",
|
|
14664
|
+
default_space: {
|
|
14665
|
+
title: "\u9810\u8A2D\u555F\u52D5\u7A7A\u9593",
|
|
14666
|
+
description: "\u9078\u64C7\u4F60\u767B\u5165\u5F8C\u9810\u8A2D\u9032\u5165\u7684\u5DE5\u4F5C\u7A7A\u9593\uFF0C\u5E6B\u52A9\u4F60\u66F4\u5FEB\u9032\u5165\u5DE5\u4F5C\u72C0\u614B\u3002",
|
|
14667
|
+
all: "\u5168\u90E8\uFF08\u4E0D\u56FA\u5B9A\u9810\u8A2D\u7A7A\u9593\uFF09"
|
|
14668
|
+
},
|
|
14669
|
+
shortcuts: {
|
|
14670
|
+
title: "\u9375\u76E4\u5FEB\u6377\u9375",
|
|
14671
|
+
description: "\u67E5\u770B\u4E26\u7BA1\u7406\u5E38\u7528\u64CD\u4F5C\u7684\u5FEB\u6377\u9375\u8A2D\u5B9A\uFF0C\u8B93\u4F60\u7684\u5DE5\u4F5C\u6D41\u66F4\u52A0\u9806\u66A2\u3002",
|
|
14672
|
+
sendMessage: "\u50B3\u9001\u8A0A\u606F",
|
|
14673
|
+
newChat: "\u65B0\u5EFA\u5C0D\u8A71",
|
|
14674
|
+
deleteDialog: "\u522A\u9664\u76EE\u524D\u6703\u8A71",
|
|
14675
|
+
clickToRecord: "\u9EDE\u64CA\u4FEE\u6539\u5FEB\u6377\u9375",
|
|
14676
|
+
updated: "\u5FEB\u6377\u9375\u5DF2\u66F4\u65B0",
|
|
14677
|
+
pressKeys: "\u6309\u4E0B\u5FEB\u6377\u9375...",
|
|
14678
|
+
none: "\u5DF2\u505C\u7528",
|
|
14679
|
+
cleared: "\u5FEB\u6377\u9375\u5DF2\u505C\u7528",
|
|
14680
|
+
clearError: "\u505C\u7528\u5931\u6557",
|
|
14681
|
+
clear: "\u505C\u7528\u5FEB\u6377\u9375",
|
|
14682
|
+
resetSuccess: "\u5FEB\u6377\u9375\u5DF2\u91CD\u8A2D",
|
|
14683
|
+
resetError: "\u91CD\u8A2D\u5931\u6557",
|
|
14684
|
+
reset: "\u91CD\u8A2D\u70BA\u9810\u8A2D"
|
|
14685
|
+
}
|
|
14686
|
+
},
|
|
14441
14687
|
appearance: {
|
|
14442
14688
|
title: "\u5916\u89C0",
|
|
14443
14689
|
theme: {
|
|
@@ -15130,6 +15376,31 @@ var init_interface_locale = __esm({
|
|
|
15130
15376
|
productivity: "\u52B9\u7387",
|
|
15131
15377
|
secrets: "\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8"
|
|
15132
15378
|
},
|
|
15379
|
+
productivity: {
|
|
15380
|
+
title: "\u52B9\u7387\u8A2D\u5B9A",
|
|
15381
|
+
default_space: {
|
|
15382
|
+
title: "\u65E2\u5B9A\u306E\u8D77\u52D5\u30B9\u30DA\u30FC\u30B9",
|
|
15383
|
+
description: "\u30ED\u30B0\u30A4\u30F3\u5F8C\u306B\u6700\u521D\u306B\u958B\u304F\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u9078\u3073\u3001\u3059\u3050\u4F5C\u696D\u306B\u5165\u308C\u308B\u3088\u3046\u306B\u3057\u307E\u3059\u3002",
|
|
15384
|
+
all: "\u3059\u3079\u3066\uFF08\u65E2\u5B9A\u30B9\u30DA\u30FC\u30B9\u3092\u56FA\u5B9A\u3057\u306A\u3044\uFF09"
|
|
15385
|
+
},
|
|
15386
|
+
shortcuts: {
|
|
15387
|
+
title: "\u30AD\u30FC\u30DC\u30FC\u30C9\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8",
|
|
15388
|
+
description: "\u3088\u304F\u4F7F\u3046\u64CD\u4F5C\u306E\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u78BA\u8A8D\u30FB\u5909\u66F4\u3057\u3066\u3001\u4F5C\u696D\u306E\u6D41\u308C\u3092\u30B9\u30E0\u30FC\u30BA\u306B\u3057\u307E\u3059\u3002",
|
|
15389
|
+
sendMessage: "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u4FE1",
|
|
15390
|
+
newChat: "\u65B0\u3057\u3044\u30C1\u30E3\u30C3\u30C8",
|
|
15391
|
+
deleteDialog: "\u73FE\u5728\u306E\u4F1A\u8A71\u3092\u524A\u9664",
|
|
15392
|
+
clickToRecord: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u5909\u66F4",
|
|
15393
|
+
updated: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u66F4\u65B0\u3057\u307E\u3057\u305F",
|
|
15394
|
+
pressKeys: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30AD\u30FC\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044...",
|
|
15395
|
+
none: "\u7121\u52B9",
|
|
15396
|
+
cleared: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u7121\u52B9\u306B\u3057\u307E\u3057\u305F",
|
|
15397
|
+
clearError: "\u7121\u52B9\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
15398
|
+
clear: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u7121\u52B9\u5316",
|
|
15399
|
+
resetSuccess: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F",
|
|
15400
|
+
resetError: "\u30EA\u30BB\u30C3\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
15401
|
+
reset: "\u65E2\u5B9A\u306B\u623B\u3059"
|
|
15402
|
+
}
|
|
15403
|
+
},
|
|
15133
15404
|
appearance: {
|
|
15134
15405
|
title: "\u5916\u89B3",
|
|
15135
15406
|
theme: {
|
|
@@ -20768,6 +21039,7 @@ __export(settingSlice_exports, {
|
|
|
20768
21039
|
selectDefaultAgentId: () => selectDefaultAgentId,
|
|
20769
21040
|
selectDefaultAgentPreference: () => selectDefaultAgentPreference,
|
|
20770
21041
|
selectDefaultSpaceId: () => selectDefaultSpaceId,
|
|
21042
|
+
selectDeleteShortcut: () => selectDeleteShortcut,
|
|
20771
21043
|
selectDensity: () => selectDensity,
|
|
20772
21044
|
selectDesktopChromeConnectorEnabled: () => selectDesktopChromeConnectorEnabled,
|
|
20773
21045
|
selectEditorAutoSave: () => selectEditorAutoSave,
|
|
@@ -20836,7 +21108,7 @@ import {
|
|
|
20836
21108
|
asyncThunkCreator,
|
|
20837
21109
|
createSelector as createSelector2
|
|
20838
21110
|
} from "@reduxjs/toolkit";
|
|
20839
|
-
var SYSTEM_DEFAULT_AGENT_ID, initialState, createSliceWithThunks, hasOwn, normalizeSidebarVisibleTypesSetting, normalizeDefaultAgentIdSetting, normalizeAuthorityHomeServerSetting, normalizeTonePresetSetting, normalizePolicyLevelSetting, resolveDefaultAgentIdSetting, selectResolvedDefaultAgentId, hexToRgbString, alphaColor, getCachedDefaultAgentRegisterRecord, persistDefaultAgentRegister, omitKeys, normalizeSettingChanges, LOCAL_FIRST_APPEARANCE_KEYS, LOCAL_ONLY_SETTINGS_KEYS, isLocalFirstAppearanceChange, stripRegisterBackedFieldsFromSettingsWrite, sanitizeStoredSettingsRecord, hydrateStoredSettings, buildSettingsPersistencePlan, settingSlice, getSettings, setSettings, clearDefaultSpaceId, addHostToCurrentServer, changeTheme, changeDensity, changeFontPreset, changeDarkMode, toggleShowThinking, setThemeFollowsSystem, setSidebarWidth, toggleEnableReadCurrentSpace, setEditorDefaultMode, setEditorLightCodeTheme, setEditorDarkCodeTheme, setEditorCodeTheme, toggleEditorWordCount, toggleEditorShortcut, setEditorFontSize, toggleEditorAutoSave, setEditorAutoSaveInterval, setGlobalPrompt, setUserTonePreset, setKnowledgeCaptureLevel, setSpaceContextLevel, setAiRecentContentLimit, setContextRetention, setMaxExecutionTime, setDefaultAgentId, setPreferredAnimationSet, setThemeMode, selectSettings, isLocalServerUrl2, resolveDesktopSafeServer, selectCurrentServer, selectSyncServers, selectRemoteServer, selectRemoteSyncServers, selectRemoteServers, selectDefaultSpaceId, selectPreferredAnimationSet, selectShowThinking, selectMaxCost, selectMaxExecutionTime, selectIsDark, selectThemeMode, selectHeaderHeight, selectThemeName, selectThemeFollowsSystem, selectSidebarWidth, selectDensity, selectFontPreset, selectEnableReadCurrentSpace, selectSidebarVisibleTypes, selectGlobalPrompt, selectUserTonePreset, selectKnowledgeCaptureLevel, selectSpaceContextLevel, selectAutoApproveSelfUpdateFields, selectAiRecentContentLimit, selectContextRetention, selectDefaultAgentPreference, selectDefaultAgentId, selectOcrModel, selectShowScrollToTopButton, selectShowScrollToBottomButton, selectCreateMenuOpenCount, selectDesktopChromeConnectorEnabled, selectEditorDefaultMode, selectEditorLightCodeTheme, selectEditorDarkCodeTheme, selectEditorCodeTheme, selectEditorWordCountEnabled, selectEditorShortcuts, selectEditorFontSize, selectEditorAutoSave, selectEditorAutoSaveInterval, selectTheme, selectEditorConfig, settingSlice_default;
|
|
21111
|
+
var SYSTEM_DEFAULT_AGENT_ID, initialState, createSliceWithThunks, hasOwn, normalizeSidebarVisibleTypesSetting, normalizeDefaultAgentIdSetting, normalizeAuthorityHomeServerSetting, normalizeTonePresetSetting, normalizePolicyLevelSetting, resolveDefaultAgentIdSetting, selectResolvedDefaultAgentId, hexToRgbString, alphaColor, getCachedDefaultAgentRegisterRecord, persistDefaultAgentRegister, omitKeys, normalizeSettingChanges, LOCAL_FIRST_APPEARANCE_KEYS, LOCAL_ONLY_SETTINGS_KEYS, isLocalFirstAppearanceChange, stripRegisterBackedFieldsFromSettingsWrite, sanitizeStoredSettingsRecord, hydrateStoredSettings, buildSettingsPersistencePlan, settingSlice, getSettings, setSettings, clearDefaultSpaceId, addHostToCurrentServer, changeTheme, changeDensity, changeFontPreset, changeDarkMode, toggleShowThinking, setThemeFollowsSystem, setSidebarWidth, toggleEnableReadCurrentSpace, setEditorDefaultMode, setEditorLightCodeTheme, setEditorDarkCodeTheme, setEditorCodeTheme, toggleEditorWordCount, toggleEditorShortcut, setEditorFontSize, toggleEditorAutoSave, setEditorAutoSaveInterval, setGlobalPrompt, setUserTonePreset, setKnowledgeCaptureLevel, setSpaceContextLevel, setAiRecentContentLimit, setContextRetention, setMaxExecutionTime, setDefaultAgentId, setPreferredAnimationSet, setThemeMode, selectSettings, isLocalServerUrl2, resolveDesktopSafeServer, selectCurrentServer, selectSyncServers, selectRemoteServer, selectRemoteSyncServers, selectRemoteServers, selectDefaultSpaceId, selectPreferredAnimationSet, selectShowThinking, selectMaxCost, selectMaxExecutionTime, selectIsDark, selectThemeMode, selectHeaderHeight, selectThemeName, selectThemeFollowsSystem, selectSidebarWidth, selectDensity, selectFontPreset, selectEnableReadCurrentSpace, selectSidebarVisibleTypes, selectGlobalPrompt, selectUserTonePreset, selectKnowledgeCaptureLevel, selectSpaceContextLevel, selectAutoApproveSelfUpdateFields, selectAiRecentContentLimit, selectContextRetention, selectDefaultAgentPreference, selectDefaultAgentId, selectOcrModel, selectShowScrollToTopButton, selectShowScrollToBottomButton, selectCreateMenuOpenCount, selectDesktopChromeConnectorEnabled, selectEditorDefaultMode, selectEditorLightCodeTheme, selectEditorDarkCodeTheme, selectEditorCodeTheme, selectEditorWordCountEnabled, selectEditorShortcuts, selectDeleteShortcut, selectEditorFontSize, selectEditorAutoSave, selectEditorAutoSaveInterval, selectTheme, selectEditorConfig, settingSlice_default;
|
|
20840
21112
|
var init_settingSlice = __esm({
|
|
20841
21113
|
"packages/app/settings/settingSlice.tsx"() {
|
|
20842
21114
|
"use strict";
|
|
@@ -20909,7 +21181,8 @@ var init_settingSlice = __esm({
|
|
|
20909
21181
|
showScrollToTopButton: false,
|
|
20910
21182
|
showScrollToBottomButton: false,
|
|
20911
21183
|
createMenuOpenCount: 0,
|
|
20912
|
-
desktopChromeConnectorEnabled: false
|
|
21184
|
+
desktopChromeConnectorEnabled: false,
|
|
21185
|
+
deleteShortcut: typeof window !== "undefined" && typeof window.navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(window.navigator.platform) ? "meta+backspace" : "ctrl+backspace"
|
|
20913
21186
|
};
|
|
20914
21187
|
createSliceWithThunks = buildCreateSlice({
|
|
20915
21188
|
creators: { asyncThunk: asyncThunkCreator }
|
|
@@ -21537,6 +21810,7 @@ var init_settingSlice = __esm({
|
|
|
21537
21810
|
);
|
|
21538
21811
|
selectEditorWordCountEnabled = (state) => state.settings.editorWordCountEnabled;
|
|
21539
21812
|
selectEditorShortcuts = (state) => state.settings.editorShortcuts;
|
|
21813
|
+
selectDeleteShortcut = (state) => state.settings.deleteShortcut;
|
|
21540
21814
|
selectEditorFontSize = (state) => state.settings.editorFontSize;
|
|
21541
21815
|
selectEditorAutoSave = (state) => state.settings.editorAutoSave;
|
|
21542
21816
|
selectEditorAutoSaveInterval = (state) => state.settings.editorAutoSaveInterval;
|
|
@@ -63690,14 +63964,6 @@ function summarizeEndpoint(value) {
|
|
|
63690
63964
|
return "invalid-url";
|
|
63691
63965
|
}
|
|
63692
63966
|
}
|
|
63693
|
-
function parseJsonObject2(raw) {
|
|
63694
|
-
try {
|
|
63695
|
-
const parsed = JSON.parse(raw);
|
|
63696
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
63697
|
-
} catch {
|
|
63698
|
-
return {};
|
|
63699
|
-
}
|
|
63700
|
-
}
|
|
63701
63967
|
function isCliProviderAgent(agentConfig) {
|
|
63702
63968
|
return Boolean(
|
|
63703
63969
|
agentConfig.apiSource === "cli" || agentConfig.provider === "cli" || agentConfig.cliProvider
|
|
@@ -64463,12 +64729,15 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64463
64729
|
toolNames: requestedToolNames,
|
|
64464
64730
|
env: deps.env
|
|
64465
64731
|
});
|
|
64732
|
+
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64733
|
+
const usesResponsesApi = providerConfig2.endpoint.includes("/responses");
|
|
64734
|
+
const stream = Boolean(options?.onTextDelta) && !usesResponsesApi;
|
|
64466
64735
|
const request = buildPlatformChatCompletionRequest({
|
|
64467
64736
|
providerConfig: providerConfig2,
|
|
64468
64737
|
messages,
|
|
64469
|
-
tools
|
|
64738
|
+
tools,
|
|
64739
|
+
stream
|
|
64470
64740
|
});
|
|
64471
|
-
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64472
64741
|
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
64473
64742
|
agentKey: agentConfig.key,
|
|
64474
64743
|
transport: "platform-proxy",
|
|
@@ -64479,32 +64748,64 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64479
64748
|
toolCount: tools.length,
|
|
64480
64749
|
requestedToolNames,
|
|
64481
64750
|
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
64482
|
-
timeoutMs: options?.timeoutMs ?? null
|
|
64751
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
64752
|
+
stream
|
|
64483
64753
|
});
|
|
64484
|
-
|
|
64485
|
-
|
|
64486
|
-
|
|
64487
|
-
|
|
64488
|
-
|
|
64489
|
-
|
|
64490
|
-
|
|
64491
|
-
|
|
64492
|
-
|
|
64493
|
-
|
|
64494
|
-
|
|
64495
|
-
|
|
64496
|
-
|
|
64497
|
-
|
|
64498
|
-
|
|
64499
|
-
|
|
64500
|
-
|
|
64501
|
-
|
|
64754
|
+
try {
|
|
64755
|
+
const res = await fetchWithTransientRetry(fetchImpl, request.url, {
|
|
64756
|
+
...request.init,
|
|
64757
|
+
...timeoutSignal ? { signal: timeoutSignal.signal } : {}
|
|
64758
|
+
}, {
|
|
64759
|
+
sleep: deps.sleep,
|
|
64760
|
+
loopbackRequest
|
|
64761
|
+
});
|
|
64762
|
+
if (!res.ok) {
|
|
64763
|
+
const raw2 = await res.text().catch(() => "");
|
|
64764
|
+
const data2 = parsePlatformChatCompletionData(raw2);
|
|
64765
|
+
throw new Error(`platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`);
|
|
64766
|
+
}
|
|
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) {
|
|
64770
|
+
const streamed = await readOpenAiCompatibleSseCompletion({
|
|
64771
|
+
response: res,
|
|
64772
|
+
onTextDelta: options.onTextDelta
|
|
64773
|
+
});
|
|
64774
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64775
|
+
agentKey: agentConfig.key,
|
|
64776
|
+
transport: "platform-proxy",
|
|
64777
|
+
ok: true,
|
|
64778
|
+
stream: true,
|
|
64779
|
+
contentChars: streamed.content.length,
|
|
64780
|
+
toolCallCount: streamed.tool_calls?.length ?? 0
|
|
64781
|
+
});
|
|
64782
|
+
return {
|
|
64783
|
+
content: streamed.content,
|
|
64784
|
+
model: providerConfig2.model,
|
|
64785
|
+
provider: providerConfig2.provider,
|
|
64786
|
+
...streamed.tool_calls ? { tool_calls: streamed.tool_calls } : {},
|
|
64787
|
+
...streamed.reasoning_content ? { reasoning_content: streamed.reasoning_content } : {},
|
|
64788
|
+
...streamed.usage ? { usage: streamed.usage } : {},
|
|
64789
|
+
trace: messages
|
|
64790
|
+
};
|
|
64791
|
+
}
|
|
64792
|
+
const raw = await res.text().catch(() => "");
|
|
64793
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64794
|
+
agentKey: agentConfig.key,
|
|
64795
|
+
transport: "platform-proxy",
|
|
64796
|
+
status: res.status,
|
|
64797
|
+
ok: res.ok,
|
|
64798
|
+
responseBytes: raw.length
|
|
64799
|
+
});
|
|
64800
|
+
const data = parsePlatformChatCompletionData(raw);
|
|
64801
|
+
return parsePlatformChatCompletionResponse({
|
|
64802
|
+
providerConfig: providerConfig2,
|
|
64803
|
+
data,
|
|
64804
|
+
trace: messages
|
|
64805
|
+
});
|
|
64806
|
+
} finally {
|
|
64807
|
+
timeoutSignal?.clear();
|
|
64502
64808
|
}
|
|
64503
|
-
return parsePlatformChatCompletionResponse({
|
|
64504
|
-
providerConfig: providerConfig2,
|
|
64505
|
-
data,
|
|
64506
|
-
trace: messages
|
|
64507
|
-
});
|
|
64508
64809
|
}
|
|
64509
64810
|
};
|
|
64510
64811
|
}
|
|
@@ -64536,47 +64837,45 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64536
64837
|
toolNames: requestedToolNames,
|
|
64537
64838
|
env: deps.env
|
|
64538
64839
|
});
|
|
64539
|
-
const request = buildOpenAiCompatibleChatCompletionRequest({
|
|
64540
|
-
providerConfig,
|
|
64541
|
-
messages,
|
|
64542
|
-
tools
|
|
64543
|
-
});
|
|
64544
64840
|
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64841
|
+
const stream = Boolean(options?.onTextDelta);
|
|
64545
64842
|
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
64546
64843
|
agentKey: agentConfig.key,
|
|
64547
64844
|
transport: "direct-openai-compatible",
|
|
64548
|
-
requestUrl: summarizeEndpoint(
|
|
64845
|
+
requestUrl: summarizeEndpoint(providerConfig.endpoint) ?? null,
|
|
64549
64846
|
model: providerConfig.model,
|
|
64550
64847
|
messageCount: messages.length,
|
|
64551
64848
|
toolCount: tools.length,
|
|
64552
64849
|
requestedToolNames,
|
|
64553
64850
|
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
64554
|
-
timeoutMs: options?.timeoutMs ?? null
|
|
64851
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
64852
|
+
stream
|
|
64555
64853
|
});
|
|
64556
|
-
|
|
64557
|
-
|
|
64558
|
-
|
|
64559
|
-
|
|
64560
|
-
|
|
64561
|
-
|
|
64562
|
-
|
|
64563
|
-
|
|
64564
|
-
|
|
64565
|
-
|
|
64566
|
-
|
|
64567
|
-
|
|
64568
|
-
|
|
64569
|
-
|
|
64570
|
-
|
|
64571
|
-
|
|
64572
|
-
|
|
64573
|
-
|
|
64854
|
+
try {
|
|
64855
|
+
const result = await executeOpenAiCompatibleChatCompletion({
|
|
64856
|
+
providerConfig,
|
|
64857
|
+
messages,
|
|
64858
|
+
tools,
|
|
64859
|
+
fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
|
|
64860
|
+
sleep: deps.sleep,
|
|
64861
|
+
loopbackRequest
|
|
64862
|
+
}),
|
|
64863
|
+
stream,
|
|
64864
|
+
onTextDelta: options?.onTextDelta,
|
|
64865
|
+
signal: timeoutSignal?.signal
|
|
64866
|
+
});
|
|
64867
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64868
|
+
agentKey: agentConfig.key,
|
|
64869
|
+
transport: "direct-openai-compatible",
|
|
64870
|
+
ok: true,
|
|
64871
|
+
stream,
|
|
64872
|
+
contentChars: result.content.length,
|
|
64873
|
+
toolCallCount: result.tool_calls?.length ?? 0
|
|
64874
|
+
});
|
|
64875
|
+
return result;
|
|
64876
|
+
} finally {
|
|
64877
|
+
timeoutSignal?.clear();
|
|
64574
64878
|
}
|
|
64575
|
-
return parseOpenAiCompatibleChatCompletionResponse({
|
|
64576
|
-
providerConfig,
|
|
64577
|
-
data,
|
|
64578
|
-
trace: messages
|
|
64579
|
-
});
|
|
64580
64879
|
}
|
|
64581
64880
|
};
|
|
64582
64881
|
},
|
|
@@ -67743,6 +68042,470 @@ function createStreamingTextWriter({
|
|
|
67743
68042
|
};
|
|
67744
68043
|
}
|
|
67745
68044
|
|
|
68045
|
+
// packages/cli/client/assistantOutput.ts
|
|
68046
|
+
var ANSI = {
|
|
68047
|
+
reset: "\x1B[0m",
|
|
68048
|
+
bold: "\x1B[1m",
|
|
68049
|
+
dim: "\x1B[2m",
|
|
68050
|
+
cyan: "\x1B[36m"
|
|
68051
|
+
};
|
|
68052
|
+
function normalizeRenderDisplayMode(raw, fallback = "rich") {
|
|
68053
|
+
const normalized = raw?.trim().toLowerCase();
|
|
68054
|
+
if (normalized === "plain" || normalized === "raw" || normalized === "off" || normalized === "0") {
|
|
68055
|
+
return "plain";
|
|
68056
|
+
}
|
|
68057
|
+
if (normalized === "rich" || normalized === "on" || normalized === "1" || normalized === "styled") {
|
|
68058
|
+
return "rich";
|
|
68059
|
+
}
|
|
68060
|
+
return fallback;
|
|
68061
|
+
}
|
|
68062
|
+
function resolveRenderDisplayMode(env = process.env) {
|
|
68063
|
+
return normalizeRenderDisplayMode(env.NOLO_CLI_RENDER ?? env.NOLO_RENDER, "rich");
|
|
68064
|
+
}
|
|
68065
|
+
function splitTableCells(line) {
|
|
68066
|
+
const trimmed = line.trim();
|
|
68067
|
+
if (!trimmed.includes("|")) return [];
|
|
68068
|
+
const core = trimmed.replace(/^\|/, "").replace(/\|$/, "");
|
|
68069
|
+
return core.split("|").map((cell) => cell.trim()).filter(Boolean);
|
|
68070
|
+
}
|
|
68071
|
+
function isTableSeparator(line) {
|
|
68072
|
+
const cells = splitTableCells(line);
|
|
68073
|
+
return cells.length > 0 && cells.every((cell) => /^:?-{3,}:?$/.test(cell));
|
|
68074
|
+
}
|
|
68075
|
+
function isTableRow(line) {
|
|
68076
|
+
const cells = splitTableCells(line);
|
|
68077
|
+
return cells.length >= 2 && cells.some((cell) => cell.length > 0);
|
|
68078
|
+
}
|
|
68079
|
+
function convertMarkdownTablesForTerminal(text) {
|
|
68080
|
+
const lines = text.split("\n");
|
|
68081
|
+
const out = [];
|
|
68082
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
68083
|
+
const line = lines[index] ?? "";
|
|
68084
|
+
const next = lines[index + 1] ?? "";
|
|
68085
|
+
if (isTableRow(line) && isTableSeparator(next)) {
|
|
68086
|
+
const headers = splitTableCells(line);
|
|
68087
|
+
index += 1;
|
|
68088
|
+
while (index + 1 < lines.length && isTableRow(lines[index + 1] ?? "") && !isTableSeparator(lines[index + 1] ?? "")) {
|
|
68089
|
+
index += 1;
|
|
68090
|
+
const row = splitTableCells(lines[index] ?? "");
|
|
68091
|
+
const label = row[0] ?? "";
|
|
68092
|
+
const detail = row.slice(1).join(" \u2014 ").trim();
|
|
68093
|
+
out.push(detail ? ` \u2022 ${label} \u2014 ${detail}` : ` \u2022 ${label}`);
|
|
68094
|
+
}
|
|
68095
|
+
if (out.length > 0 && out[out.length - 1] !== "") out.push("");
|
|
68096
|
+
continue;
|
|
68097
|
+
}
|
|
68098
|
+
out.push(line);
|
|
68099
|
+
}
|
|
68100
|
+
return out.join("\n");
|
|
68101
|
+
}
|
|
68102
|
+
function polishAssistantStructure(text) {
|
|
68103
|
+
return convertMarkdownTablesForTerminal(text).replace(/\r\n/g, "\n").replace(/([^\n])\n(#{1,3} )/g, "$1\n\n$2").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
68104
|
+
}
|
|
68105
|
+
function styleInlineMarkdown(line, mode) {
|
|
68106
|
+
if (mode === "plain") return line;
|
|
68107
|
+
return line.replace(/\*\*(.+?)\*\*/g, `${ANSI.bold}$1${ANSI.reset}`);
|
|
68108
|
+
}
|
|
68109
|
+
function styleRichMarkdownLine(line) {
|
|
68110
|
+
const heading = line.match(/^(#{1,3})\s+(.+)$/);
|
|
68111
|
+
if (heading) {
|
|
68112
|
+
const level = heading[1].length;
|
|
68113
|
+
const title = heading[2];
|
|
68114
|
+
if (level <= 2) return `${ANSI.bold}${title}${ANSI.reset}`;
|
|
68115
|
+
return `${ANSI.cyan}${title}${ANSI.reset}`;
|
|
68116
|
+
}
|
|
68117
|
+
if (/^---+$/.test(line.trim())) {
|
|
68118
|
+
return `${ANSI.dim}${line}${ANSI.reset}`;
|
|
68119
|
+
}
|
|
68120
|
+
return styleInlineMarkdown(line, "rich");
|
|
68121
|
+
}
|
|
68122
|
+
function formatAssistantDisplay(text, mode = "rich") {
|
|
68123
|
+
const polished = polishAssistantStructure(text);
|
|
68124
|
+
if (mode === "plain") {
|
|
68125
|
+
return polished.split("\n").map((line) => styleInlineMarkdown(line, "plain")).join("\n");
|
|
68126
|
+
}
|
|
68127
|
+
return polished.split("\n").map((line) => styleRichMarkdownLine(line)).join("\n");
|
|
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
|
+
}
|
|
68187
|
+
|
|
68188
|
+
// packages/cli/client/thinkingOutput.ts
|
|
68189
|
+
var THINK_OPEN = /<think>/i;
|
|
68190
|
+
var THINK_CLOSE = /<\/think>/i;
|
|
68191
|
+
var COLLAPSED_MARKER = /^\s*▸ 思考已折叠\s*$/;
|
|
68192
|
+
function normalizeThinkingDisplayMode(raw, fallback = "hide") {
|
|
68193
|
+
const normalized = raw?.trim().toLowerCase();
|
|
68194
|
+
if (normalized === "hide" || normalized === "off" || normalized === "false" || normalized === "0") {
|
|
68195
|
+
return "hide";
|
|
68196
|
+
}
|
|
68197
|
+
if (normalized === "marker" || normalized === "collapsed" || normalized === "fold") {
|
|
68198
|
+
return "marker";
|
|
68199
|
+
}
|
|
68200
|
+
if (normalized === "show" || normalized === "on" || normalized === "true" || normalized === "1") {
|
|
68201
|
+
return "show";
|
|
68202
|
+
}
|
|
68203
|
+
return fallback;
|
|
68204
|
+
}
|
|
68205
|
+
function resolveThinkingDisplayMode(env = process.env) {
|
|
68206
|
+
return normalizeThinkingDisplayMode(env.NOLO_CLI_THINKING ?? env.NOLO_THINKING, "hide");
|
|
68207
|
+
}
|
|
68208
|
+
function collapseThinkingBlocks(text, mode = "hide") {
|
|
68209
|
+
if (mode === "show") return text;
|
|
68210
|
+
const replacement = mode === "marker" ? "\u25B8 \u601D\u8003\u5DF2\u6298\u53E0\n" : "";
|
|
68211
|
+
return text.replace(/<think>[\s\S]*?<\/think>\s*/gi, replacement).replace(/\n{3,}/g, "\n\n").trim();
|
|
68212
|
+
}
|
|
68213
|
+
function stripCollapsedThinkingMarkers(text) {
|
|
68214
|
+
return text.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n").replace(/\n{2,}/g, "\n").trim();
|
|
68215
|
+
}
|
|
68216
|
+
function formatAssistantTextForCli(text, mode = "hide") {
|
|
68217
|
+
const collapsed = collapseThinkingBlocks(text, mode);
|
|
68218
|
+
return mode === "hide" ? stripCollapsedThinkingMarkers(collapsed) : collapsed;
|
|
68219
|
+
}
|
|
68220
|
+
function createThinkingAwareStreamFilter(write2, mode = "hide") {
|
|
68221
|
+
if (mode === "show") {
|
|
68222
|
+
return {
|
|
68223
|
+
push(chunk) {
|
|
68224
|
+
write2(chunk);
|
|
68225
|
+
},
|
|
68226
|
+
flush() {
|
|
68227
|
+
}
|
|
68228
|
+
};
|
|
68229
|
+
}
|
|
68230
|
+
let pending = "";
|
|
68231
|
+
let insideThink = false;
|
|
68232
|
+
let markerEmitted = false;
|
|
68233
|
+
const emit = (chunk) => {
|
|
68234
|
+
if (chunk) write2(chunk);
|
|
68235
|
+
};
|
|
68236
|
+
const emitMarker = () => {
|
|
68237
|
+
if (mode !== "marker" || markerEmitted) return;
|
|
68238
|
+
emit("\n\u25B8 \u601D\u8003\u5DF2\u6298\u53E0\n");
|
|
68239
|
+
markerEmitted = true;
|
|
68240
|
+
};
|
|
68241
|
+
const consume = (input2) => {
|
|
68242
|
+
pending += input2;
|
|
68243
|
+
while (pending.length > 0) {
|
|
68244
|
+
if (insideThink) {
|
|
68245
|
+
const closeMatch = pending.match(THINK_CLOSE);
|
|
68246
|
+
if (!closeMatch || closeMatch.index == null) {
|
|
68247
|
+
emitMarker();
|
|
68248
|
+
pending = "";
|
|
68249
|
+
return;
|
|
68250
|
+
}
|
|
68251
|
+
emitMarker();
|
|
68252
|
+
pending = pending.slice(closeMatch.index + closeMatch[0].length);
|
|
68253
|
+
insideThink = false;
|
|
68254
|
+
markerEmitted = false;
|
|
68255
|
+
continue;
|
|
68256
|
+
}
|
|
68257
|
+
const openMatch = pending.match(THINK_OPEN);
|
|
68258
|
+
if (!openMatch || openMatch.index == null) {
|
|
68259
|
+
const nextMarker = pending.indexOf("<");
|
|
68260
|
+
if (nextMarker === -1) {
|
|
68261
|
+
const cleaned = mode === "hide" ? pending.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : pending;
|
|
68262
|
+
emit(cleaned);
|
|
68263
|
+
pending = "";
|
|
68264
|
+
return;
|
|
68265
|
+
}
|
|
68266
|
+
if (nextMarker > 0) {
|
|
68267
|
+
const head = pending.slice(0, nextMarker);
|
|
68268
|
+
const cleaned = mode === "hide" ? head.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : head;
|
|
68269
|
+
emit(cleaned);
|
|
68270
|
+
pending = pending.slice(nextMarker);
|
|
68271
|
+
continue;
|
|
68272
|
+
}
|
|
68273
|
+
if (pending.length < 7) return;
|
|
68274
|
+
emit(pending[0]);
|
|
68275
|
+
pending = pending.slice(1);
|
|
68276
|
+
continue;
|
|
68277
|
+
}
|
|
68278
|
+
if (openMatch.index > 0) {
|
|
68279
|
+
const head = pending.slice(0, openMatch.index);
|
|
68280
|
+
const cleaned = mode === "hide" ? head.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : head;
|
|
68281
|
+
emit(cleaned);
|
|
68282
|
+
pending = pending.slice(openMatch.index);
|
|
68283
|
+
continue;
|
|
68284
|
+
}
|
|
68285
|
+
pending = pending.slice(openMatch[0].length);
|
|
68286
|
+
insideThink = true;
|
|
68287
|
+
markerEmitted = false;
|
|
68288
|
+
}
|
|
68289
|
+
};
|
|
68290
|
+
return {
|
|
68291
|
+
push(chunk) {
|
|
68292
|
+
consume(chunk);
|
|
68293
|
+
},
|
|
68294
|
+
flush() {
|
|
68295
|
+
if (insideThink) emitMarker();
|
|
68296
|
+
if (pending) {
|
|
68297
|
+
const cleaned = mode === "hide" ? pending.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : pending;
|
|
68298
|
+
emit(cleaned);
|
|
68299
|
+
}
|
|
68300
|
+
pending = "";
|
|
68301
|
+
insideThink = false;
|
|
68302
|
+
markerEmitted = false;
|
|
68303
|
+
}
|
|
68304
|
+
};
|
|
68305
|
+
}
|
|
68306
|
+
|
|
68307
|
+
// packages/cli/client/tokenUsage.ts
|
|
68308
|
+
init_providers();
|
|
68309
|
+
var PROVIDER_LOOKUP_ORDER = [
|
|
68310
|
+
"openrouter",
|
|
68311
|
+
"fireworks",
|
|
68312
|
+
"openai",
|
|
68313
|
+
"mimo",
|
|
68314
|
+
"gmi",
|
|
68315
|
+
"google",
|
|
68316
|
+
"deepseek",
|
|
68317
|
+
"mistral",
|
|
68318
|
+
"vultr",
|
|
68319
|
+
"deepinfra",
|
|
68320
|
+
"cloudflare"
|
|
68321
|
+
];
|
|
68322
|
+
function parseUsageRecord(usage2) {
|
|
68323
|
+
if (!usage2 || typeof usage2 !== "object") return void 0;
|
|
68324
|
+
const input2 = Number(usage2.input_tokens ?? usage2.prompt_tokens ?? 0);
|
|
68325
|
+
const output2 = Number(usage2.output_tokens ?? usage2.completion_tokens ?? 0);
|
|
68326
|
+
if (!Number.isFinite(input2) || !Number.isFinite(output2)) return void 0;
|
|
68327
|
+
if (!input2 && !output2) return void 0;
|
|
68328
|
+
return { input: input2, output: output2 };
|
|
68329
|
+
}
|
|
68330
|
+
function fuzzyContextWindow(model) {
|
|
68331
|
+
const lower = model.toLowerCase();
|
|
68332
|
+
if (lower.includes("minimax-m3") || lower.includes("minimax_m3")) return 1e6;
|
|
68333
|
+
if (lower.includes("minimax-m2")) return 262144;
|
|
68334
|
+
if (lower.includes("gpt-5") || lower.includes("gpt-4.1")) return 1047576;
|
|
68335
|
+
if (lower.includes("claude")) return 2e5;
|
|
68336
|
+
return void 0;
|
|
68337
|
+
}
|
|
68338
|
+
function resolveContextWindow(model) {
|
|
68339
|
+
const raw = model?.trim();
|
|
68340
|
+
if (!raw) return void 0;
|
|
68341
|
+
for (const provider of PROVIDER_LOOKUP_ORDER) {
|
|
68342
|
+
const config = findModelConfig(provider, raw);
|
|
68343
|
+
if (config?.contextWindow) return config.contextWindow;
|
|
68344
|
+
}
|
|
68345
|
+
return fuzzyContextWindow(raw);
|
|
68346
|
+
}
|
|
68347
|
+
function buildTurnTokenUsage(usage2, model) {
|
|
68348
|
+
const parsed = parseUsageRecord(usage2);
|
|
68349
|
+
if (!parsed) return void 0;
|
|
68350
|
+
const contextWindow = resolveContextWindow(model);
|
|
68351
|
+
const remaining = contextWindow && parsed.input > 0 ? Math.max(0, contextWindow - parsed.input) : void 0;
|
|
68352
|
+
return {
|
|
68353
|
+
...parsed,
|
|
68354
|
+
...contextWindow ? { contextWindow } : {},
|
|
68355
|
+
...remaining != null ? { remaining } : {}
|
|
68356
|
+
};
|
|
68357
|
+
}
|
|
68358
|
+
function formatTokenCount(value) {
|
|
68359
|
+
if (!Number.isFinite(value) || value < 0) return "\u2014";
|
|
68360
|
+
if (value < 1e3) return String(Math.round(value));
|
|
68361
|
+
if (value < 1e6) {
|
|
68362
|
+
const compact3 = value / 1e3;
|
|
68363
|
+
if (Number.isInteger(compact3)) return `${compact3}k`;
|
|
68364
|
+
return `${compact3.toFixed(1).replace(/\.0$/, "")}k`;
|
|
68365
|
+
}
|
|
68366
|
+
const compact2 = value / 1e6;
|
|
68367
|
+
return compact2 >= 100 ? `${Math.round(compact2)}M` : `${compact2.toFixed(1).replace(/\.0$/, "")}M`;
|
|
68368
|
+
}
|
|
68369
|
+
function renderTokenStatus(tokens) {
|
|
68370
|
+
if (!tokens) return "in \u2014 out \u2014 left \u2014";
|
|
68371
|
+
const left = tokens.remaining != null ? formatTokenCount(tokens.remaining) : tokens.contextWindow ? "\u2014" : "\u2014";
|
|
68372
|
+
return `in ${formatTokenCount(tokens.input)} out ${formatTokenCount(tokens.output)} left ${left}`;
|
|
68373
|
+
}
|
|
68374
|
+
|
|
68375
|
+
// packages/cli/client/terminalStyles.ts
|
|
68376
|
+
var ANSI2 = {
|
|
68377
|
+
dim: "\x1B[2m",
|
|
68378
|
+
bold: "\x1B[1m",
|
|
68379
|
+
cyan: "\x1B[36m",
|
|
68380
|
+
green: "\x1B[32m",
|
|
68381
|
+
red: "\x1B[31m"
|
|
68382
|
+
};
|
|
68383
|
+
var RESET = "\x1B[0m";
|
|
68384
|
+
function resolveCliColorEnabled(env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
|
|
68385
|
+
const setting = (env.NOLO_CLI_COLOR ?? "").trim().toLowerCase();
|
|
68386
|
+
if (setting === "0" || setting === "false" || setting === "off") return false;
|
|
68387
|
+
if (env.NO_COLOR) return false;
|
|
68388
|
+
if (setting === "1" || setting === "true" || setting === "on") return true;
|
|
68389
|
+
return isTTY;
|
|
68390
|
+
}
|
|
68391
|
+
function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
|
|
68392
|
+
if (!enabled || !text) return text;
|
|
68393
|
+
return `${ANSI2[style]}${text}${RESET}`;
|
|
68394
|
+
}
|
|
68395
|
+
function dimCliText(text, enabled = resolveCliColorEnabled()) {
|
|
68396
|
+
return styleCliText(text, "dim", enabled);
|
|
68397
|
+
}
|
|
68398
|
+
|
|
68399
|
+
// packages/cli/client/toolOutput.ts
|
|
68400
|
+
function normalizeToolDisplayMode(raw, fallback = "compact") {
|
|
68401
|
+
const normalized = raw?.trim().toLowerCase();
|
|
68402
|
+
if (normalized === "hide" || normalized === "off" || normalized === "false" || normalized === "0") {
|
|
68403
|
+
return "hide";
|
|
68404
|
+
}
|
|
68405
|
+
if (normalized === "verbose" || normalized === "debug" || normalized === "trace" || normalized === "full") {
|
|
68406
|
+
return "verbose";
|
|
68407
|
+
}
|
|
68408
|
+
if (normalized === "compact" || normalized === "minimal" || normalized === "short") {
|
|
68409
|
+
return "compact";
|
|
68410
|
+
}
|
|
68411
|
+
return fallback;
|
|
68412
|
+
}
|
|
68413
|
+
function resolveToolDisplayMode(env = process.env) {
|
|
68414
|
+
const legacyTrace = env.NOLO_TRACE_TOOLS?.trim().toLowerCase();
|
|
68415
|
+
if (legacyTrace === "0" || legacyTrace === "false" || legacyTrace === "off") {
|
|
68416
|
+
return "hide";
|
|
68417
|
+
}
|
|
68418
|
+
if (legacyTrace === "verbose" || legacyTrace === "full") {
|
|
68419
|
+
return "verbose";
|
|
68420
|
+
}
|
|
68421
|
+
return normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact");
|
|
68422
|
+
}
|
|
68423
|
+
function shouldEmitToolEvents(mode) {
|
|
68424
|
+
return mode !== "hide";
|
|
68425
|
+
}
|
|
68426
|
+
function clip4(value, max = 72) {
|
|
68427
|
+
const compact2 = value.replace(/\s+/g, " ").trim();
|
|
68428
|
+
return compact2.length > max ? `${compact2.slice(0, max - 1)}\u2026` : compact2;
|
|
68429
|
+
}
|
|
68430
|
+
function compactResultHint(summary, toolName) {
|
|
68431
|
+
if (!summary) return "";
|
|
68432
|
+
const linesMatch = summary.match(/(\d+)\s+lines?/);
|
|
68433
|
+
if (linesMatch) {
|
|
68434
|
+
if (toolName === "readFile" || toolName === "listFiles" || toolName === "globFiles") {
|
|
68435
|
+
return `${linesMatch[1]} lines`;
|
|
68436
|
+
}
|
|
68437
|
+
if (toolName === "execShell" || toolName === "runCommand") {
|
|
68438
|
+
return `${linesMatch[1]} lines`;
|
|
68439
|
+
}
|
|
68440
|
+
}
|
|
68441
|
+
const exitMatch = summary.match(/exit=(\d+)/);
|
|
68442
|
+
if (exitMatch && exitMatch[1] !== "0") return `exit ${exitMatch[1]}`;
|
|
68443
|
+
return "";
|
|
68444
|
+
}
|
|
68445
|
+
function formatToolTraceLine(text, colorEnabled, accent = "none") {
|
|
68446
|
+
if (!colorEnabled) return `${text}
|
|
68447
|
+
`;
|
|
68448
|
+
if (accent === "error") {
|
|
68449
|
+
return `${styleCliText(text, "red", true)}
|
|
68450
|
+
`;
|
|
68451
|
+
}
|
|
68452
|
+
return `${dimCliText(text, true)}
|
|
68453
|
+
`;
|
|
68454
|
+
}
|
|
68455
|
+
function formatVerboseToolEvent(event, colorEnabled) {
|
|
68456
|
+
const round = event.round + 1;
|
|
68457
|
+
const detail = event.argumentsPreview ? ` ${event.argumentsPreview}` : "";
|
|
68458
|
+
if (event.type === "tool-call") {
|
|
68459
|
+
return formatToolTraceLine(`[nolo:tool] #${round} -> ${event.toolName}${detail}`, colorEnabled);
|
|
68460
|
+
}
|
|
68461
|
+
if (event.type === "tool-error") {
|
|
68462
|
+
const elapsed2 = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68463
|
+
return formatToolTraceLine(
|
|
68464
|
+
`[nolo:tool] #${round} !! ${event.toolName}${elapsed2}: ${event.message ?? "failed"}`,
|
|
68465
|
+
colorEnabled,
|
|
68466
|
+
"error"
|
|
68467
|
+
);
|
|
68468
|
+
}
|
|
68469
|
+
const elapsed = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68470
|
+
const summary = event.summary ? ` ${event.summary}` : "";
|
|
68471
|
+
return formatToolTraceLine(
|
|
68472
|
+
`[nolo:tool] #${round} <- ${event.toolName}${elapsed}${summary}`,
|
|
68473
|
+
colorEnabled
|
|
68474
|
+
);
|
|
68475
|
+
}
|
|
68476
|
+
function formatCompactToolLine(event, pending, colorEnabled) {
|
|
68477
|
+
const toolName = event.toolName || pending?.toolName || "tool";
|
|
68478
|
+
const args2 = clip4(event.argumentsPreview || pending?.argumentsPreview || "");
|
|
68479
|
+
const label = args2 ? `${toolName} ${args2}` : toolName;
|
|
68480
|
+
const ms = typeof event.elapsedMs === "number" ? `${event.elapsedMs}ms` : "";
|
|
68481
|
+
if (event.type === "tool-error") {
|
|
68482
|
+
const message = clip4(event.message ?? "failed", 96);
|
|
68483
|
+
const timing2 = ms ? ` \xB7 ${ms}` : "";
|
|
68484
|
+
return formatToolTraceLine(` \u25B8 ${label} \u2717 ${message}${timing2}`, colorEnabled, "error");
|
|
68485
|
+
}
|
|
68486
|
+
const hint = compactResultHint(event.summary, toolName);
|
|
68487
|
+
const timing = ms ? ` ${ms}` : "";
|
|
68488
|
+
const suffix = hint ? ` \xB7 ${hint}` : "";
|
|
68489
|
+
return formatToolTraceLine(` \u25B8 ${label} \u2713${timing}${suffix}`, colorEnabled);
|
|
68490
|
+
}
|
|
68491
|
+
function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled()) {
|
|
68492
|
+
const pending = /* @__PURE__ */ new Map();
|
|
68493
|
+
return (event) => {
|
|
68494
|
+
if (mode === "hide") return "";
|
|
68495
|
+
if (mode === "verbose") return formatVerboseToolEvent(event, colorEnabled);
|
|
68496
|
+
if (event.type === "tool-call") {
|
|
68497
|
+
pending.set(event.toolCallId, {
|
|
68498
|
+
toolName: event.toolName,
|
|
68499
|
+
argumentsPreview: event.argumentsPreview
|
|
68500
|
+
});
|
|
68501
|
+
return "";
|
|
68502
|
+
}
|
|
68503
|
+
const call = pending.get(event.toolCallId);
|
|
68504
|
+
pending.delete(event.toolCallId);
|
|
68505
|
+
return formatCompactToolLine(event, call, colorEnabled);
|
|
68506
|
+
};
|
|
68507
|
+
}
|
|
68508
|
+
|
|
67746
68509
|
// packages/cli/client/agentRun.ts
|
|
67747
68510
|
var Spinner = class {
|
|
67748
68511
|
constructor(output2, text) {
|
|
@@ -67988,10 +68751,13 @@ function buildSubjectRefs(options) {
|
|
|
67988
68751
|
}
|
|
67989
68752
|
return refs.length ? refs : void 0;
|
|
67990
68753
|
}
|
|
67991
|
-
function
|
|
67992
|
-
const
|
|
67993
|
-
|
|
67994
|
-
return
|
|
68754
|
+
function formatAssistantResponseForCli(text, options) {
|
|
68755
|
+
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
68756
|
+
const renderMode = resolveRenderDisplayMode(options.env);
|
|
68757
|
+
return formatAssistantDisplay(
|
|
68758
|
+
formatAssistantTextForCli(text, thinkingMode),
|
|
68759
|
+
renderMode
|
|
68760
|
+
);
|
|
67995
68761
|
}
|
|
67996
68762
|
function resolveAgentEventMode(options) {
|
|
67997
68763
|
if (options.eventsMode === "jsonl") return "jsonl";
|
|
@@ -68002,23 +68768,6 @@ function isMissingLocalAgentConfigError(error, agentRef) {
|
|
|
68002
68768
|
error && typeof error === "object" && "code" in error && error.code === LOCAL_AGENT_CONFIG_MISSING_CODE && error.agentRef === agentRef
|
|
68003
68769
|
);
|
|
68004
68770
|
}
|
|
68005
|
-
function formatToolTraceEvent(event) {
|
|
68006
|
-
const round = event.round + 1;
|
|
68007
|
-
const detail = event.argumentsPreview ? ` ${event.argumentsPreview}` : "";
|
|
68008
|
-
if (event.type === "tool-call") {
|
|
68009
|
-
return `[nolo:tool] #${round} -> ${event.toolName}${detail}
|
|
68010
|
-
`;
|
|
68011
|
-
}
|
|
68012
|
-
if (event.type === "tool-error") {
|
|
68013
|
-
const elapsed2 = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68014
|
-
return `[nolo:tool] #${round} !! ${event.toolName}${elapsed2}: ${event.message ?? "failed"}
|
|
68015
|
-
`;
|
|
68016
|
-
}
|
|
68017
|
-
const elapsed = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68018
|
-
const summary = event.summary ? ` ${event.summary}` : "";
|
|
68019
|
-
return `[nolo:tool] #${round} <- ${event.toolName}${elapsed}${summary}
|
|
68020
|
-
`;
|
|
68021
|
-
}
|
|
68022
68771
|
function formatToolJsonEvent(event) {
|
|
68023
68772
|
return `${JSON.stringify({
|
|
68024
68773
|
schemaVersion: 1,
|
|
@@ -68150,8 +68899,8 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
68150
68899
|
const contentType = res.headers.get("content-type") || "";
|
|
68151
68900
|
if (contentType.includes("text/event-stream") && res.body) {
|
|
68152
68901
|
spinner.stop();
|
|
68153
|
-
const
|
|
68154
|
-
return
|
|
68902
|
+
const result = await readStreamingAgentRun(options, res);
|
|
68903
|
+
return result;
|
|
68155
68904
|
}
|
|
68156
68905
|
spinner.stop();
|
|
68157
68906
|
let data = {};
|
|
@@ -68194,7 +68943,10 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
68194
68943
|
}
|
|
68195
68944
|
return dialogIdText ? { exitCode: 1, dialogId: dialogIdText } : { exitCode: 1 };
|
|
68196
68945
|
}
|
|
68197
|
-
const content =
|
|
68946
|
+
const content = formatAssistantResponseForCli(
|
|
68947
|
+
String(data?.content ?? data?.message ?? ""),
|
|
68948
|
+
options
|
|
68949
|
+
);
|
|
68198
68950
|
if (content) {
|
|
68199
68951
|
options.output.write(`
|
|
68200
68952
|
${options.agentName} > ${content}
|
|
@@ -68207,11 +68959,14 @@ ${options.agentName} > (no text response)
|
|
|
68207
68959
|
const usage2 = formatUsage(data?.usage, data?.dialogId);
|
|
68208
68960
|
if (usage2 && shouldShowUsage(options.env)) options.output.write(`${usage2}
|
|
68209
68961
|
`);
|
|
68210
|
-
|
|
68962
|
+
return {
|
|
68211
68963
|
exitCode: 0,
|
|
68212
|
-
...typeof data?.dialogId === "string" && data.dialogId ? { dialogId: data.dialogId } : {}
|
|
68964
|
+
...typeof data?.dialogId === "string" && data.dialogId ? { dialogId: data.dialogId } : {},
|
|
68965
|
+
turnTokens: buildTurnTokenUsage(
|
|
68966
|
+
data?.usage,
|
|
68967
|
+
typeof data?.model === "string" ? data.model : options.agentKey
|
|
68968
|
+
)
|
|
68213
68969
|
};
|
|
68214
|
-
return result;
|
|
68215
68970
|
}
|
|
68216
68971
|
async function runInjectedLocalAgentTurn(options) {
|
|
68217
68972
|
return runLocalAgentTurnForCli(options, { reportFailure: true });
|
|
@@ -68231,8 +68986,22 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68231
68986
|
const spinner = new Spinner(options.output, `${options.agentName} -> working locally`);
|
|
68232
68987
|
spinner.start();
|
|
68233
68988
|
try {
|
|
68234
|
-
const
|
|
68989
|
+
const toolDisplayMode = resolveToolDisplayMode(options.env);
|
|
68990
|
+
const traceLocalTools = shouldEmitToolEvents(toolDisplayMode);
|
|
68991
|
+
const formatToolEvent = createToolEventFormatter(toolDisplayMode);
|
|
68235
68992
|
const eventMode = resolveAgentEventMode(options);
|
|
68993
|
+
let streamedAssistantText = false;
|
|
68994
|
+
let printedAssistantLabel = false;
|
|
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
|
+
});
|
|
69001
|
+
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
69002
|
+
(chunk) => renderWriter.push(chunk),
|
|
69003
|
+
thinkingMode
|
|
69004
|
+
);
|
|
68236
69005
|
const subjectRefs = buildSubjectRefs(options);
|
|
68237
69006
|
const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter((key2) => key2.trim());
|
|
68238
69007
|
const allowedToolNames = options.allowedToolNames?.filter((name) => name.trim());
|
|
@@ -68261,27 +69030,48 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68261
69030
|
...typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
|
|
68262
69031
|
...traceLocalTools ? {
|
|
68263
69032
|
onToolEvent: (event) => {
|
|
68264
|
-
|
|
68265
|
-
|
|
68266
|
-
|
|
68267
|
-
|
|
68268
|
-
|
|
69033
|
+
spinner.stop();
|
|
69034
|
+
const chunk = eventMode === "jsonl" ? formatToolJsonEvent(event) : formatToolEvent(event);
|
|
69035
|
+
if (chunk) {
|
|
69036
|
+
options.output.write(chunk);
|
|
69037
|
+
}
|
|
69038
|
+
}
|
|
69039
|
+
} : {},
|
|
69040
|
+
...!options.noStream ? {
|
|
69041
|
+
onTextDelta: (chunk) => {
|
|
69042
|
+
spinner.stop();
|
|
69043
|
+
if (!printedAssistantLabel) {
|
|
69044
|
+
options.output.write(`
|
|
69045
|
+
${options.agentName} > `);
|
|
69046
|
+
printedAssistantLabel = true;
|
|
68269
69047
|
}
|
|
69048
|
+
streamedAssistantText = true;
|
|
69049
|
+
thinkingFilter.push(chunk);
|
|
68270
69050
|
}
|
|
68271
69051
|
} : {}
|
|
68272
69052
|
});
|
|
68273
69053
|
spinner.stop();
|
|
68274
|
-
|
|
68275
|
-
|
|
68276
|
-
|
|
69054
|
+
if (streamedAssistantText) {
|
|
69055
|
+
thinkingFilter.flush();
|
|
69056
|
+
renderWriter.flush();
|
|
69057
|
+
options.output.write("\n");
|
|
69058
|
+
} else {
|
|
69059
|
+
const content = formatAssistantResponseForCli(result.content.trim(), options);
|
|
69060
|
+
if (content) {
|
|
69061
|
+
options.output.write(`
|
|
68277
69062
|
${options.agentName} > ${content}
|
|
68278
69063
|
`);
|
|
68279
|
-
|
|
68280
|
-
|
|
69064
|
+
} else {
|
|
69065
|
+
options.output.write(`
|
|
68281
69066
|
${options.agentName} > (no text response)
|
|
68282
69067
|
`);
|
|
69068
|
+
}
|
|
68283
69069
|
}
|
|
68284
|
-
return {
|
|
69070
|
+
return {
|
|
69071
|
+
exitCode: 0,
|
|
69072
|
+
dialogId: result.dialogId,
|
|
69073
|
+
turnTokens: buildTurnTokenUsage(result.usage, result.model)
|
|
69074
|
+
};
|
|
68285
69075
|
} catch (error) {
|
|
68286
69076
|
spinner.stop();
|
|
68287
69077
|
if (settings.reportFailure) {
|
|
@@ -68300,9 +69090,19 @@ async function readStreamingAgentRun(options, res) {
|
|
|
68300
69090
|
return { exitCode: 1 };
|
|
68301
69091
|
}
|
|
68302
69092
|
const decoder = new TextDecoder();
|
|
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
|
+
});
|
|
68303
69099
|
const writer = createStreamingTextWriter({
|
|
68304
|
-
write: (chunk) =>
|
|
69100
|
+
write: (chunk) => renderWriter.push(chunk)
|
|
68305
69101
|
});
|
|
69102
|
+
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
69103
|
+
(chunk) => writer.push(chunk),
|
|
69104
|
+
thinkingMode
|
|
69105
|
+
);
|
|
68306
69106
|
let buffer = "";
|
|
68307
69107
|
let content = "";
|
|
68308
69108
|
let dialogId;
|
|
@@ -68332,7 +69132,7 @@ ${options.agentName} > `);
|
|
|
68332
69132
|
if (!chunk) return;
|
|
68333
69133
|
printLabel();
|
|
68334
69134
|
content += chunk;
|
|
68335
|
-
|
|
69135
|
+
thinkingFilter.push(chunk);
|
|
68336
69136
|
};
|
|
68337
69137
|
try {
|
|
68338
69138
|
while (true) {
|
|
@@ -68369,6 +69169,8 @@ ${options.agentName} > `);
|
|
|
68369
69169
|
return { exitCode: 1 };
|
|
68370
69170
|
} finally {
|
|
68371
69171
|
writer.flushAll();
|
|
69172
|
+
thinkingFilter.flush();
|
|
69173
|
+
renderWriter.flush();
|
|
68372
69174
|
}
|
|
68373
69175
|
if (!content) {
|
|
68374
69176
|
options.output.write(`
|
|
@@ -68382,7 +69184,8 @@ ${options.agentName} > (no text response)
|
|
|
68382
69184
|
`);
|
|
68383
69185
|
return {
|
|
68384
69186
|
exitCode: 0,
|
|
68385
|
-
...dialogId ? { dialogId } : {}
|
|
69187
|
+
...dialogId ? { dialogId } : {},
|
|
69188
|
+
turnTokens: buildTurnTokenUsage(usage2, options.agentKey)
|
|
68386
69189
|
};
|
|
68387
69190
|
}
|
|
68388
69191
|
async function runAgentTurn(options) {
|
|
@@ -68395,10 +69198,17 @@ async function runAgentTurn(options) {
|
|
|
68395
69198
|
const skipLocal = await shouldSkipAutoLocalForServerPlatformTools(options);
|
|
68396
69199
|
if (!skipLocal) {
|
|
68397
69200
|
const localResult = await runLocalAgentTurnForCli(options, { reportFailure: false });
|
|
69201
|
+
if (localResult.exitCode !== 0 && localResult.localError) {
|
|
69202
|
+
options.output.write(
|
|
69203
|
+
`[nolo] auto runtime: local run unavailable (${localResult.localError instanceof Error ? localResult.localError.message : String(localResult.localError)}); falling back to server.
|
|
69204
|
+
`
|
|
69205
|
+
);
|
|
69206
|
+
}
|
|
68398
69207
|
if (localResult.exitCode === 0) {
|
|
68399
69208
|
return {
|
|
68400
69209
|
exitCode: localResult.exitCode,
|
|
68401
|
-
...localResult.dialogId ? { dialogId: localResult.dialogId } : {}
|
|
69210
|
+
...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
|
|
69211
|
+
...localResult.turnTokens ? { turnTokens: localResult.turnTokens } : {}
|
|
68402
69212
|
};
|
|
68403
69213
|
}
|
|
68404
69214
|
if (isMissingLocalAgentConfigError(localResult.localError, options.agentKey)) {
|
|
@@ -68415,7 +69225,8 @@ async function runAgentTurn(options) {
|
|
|
68415
69225
|
if (retriedLocalResult.exitCode === 0) {
|
|
68416
69226
|
return {
|
|
68417
69227
|
exitCode: retriedLocalResult.exitCode,
|
|
68418
|
-
...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {}
|
|
69228
|
+
...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {},
|
|
69229
|
+
...retriedLocalResult.turnTokens ? { turnTokens: retriedLocalResult.turnTokens } : {}
|
|
68419
69230
|
};
|
|
68420
69231
|
}
|
|
68421
69232
|
}
|
|
@@ -69617,7 +70428,7 @@ function countByName(values) {
|
|
|
69617
70428
|
function uniq(values) {
|
|
69618
70429
|
return [...new Set(values.filter(Boolean))];
|
|
69619
70430
|
}
|
|
69620
|
-
function
|
|
70431
|
+
function parseJsonObject2(raw) {
|
|
69621
70432
|
if (typeof raw !== "string" || !raw.trim()) return null;
|
|
69622
70433
|
try {
|
|
69623
70434
|
const parsed = JSON.parse(raw);
|
|
@@ -69633,7 +70444,7 @@ function deriveWrittenFiles(toolMessages) {
|
|
|
69633
70444
|
const toolName = toToolName(message?.toolName ?? message?.name);
|
|
69634
70445
|
if (!writeToolNames.has(toolName)) continue;
|
|
69635
70446
|
const payload = message?.toolPayload ?? {};
|
|
69636
|
-
const content =
|
|
70447
|
+
const content = parseJsonObject2(message?.content);
|
|
69637
70448
|
for (const candidate of [payload?.input?.filePath, payload?.response?.filePath, content?.filePath]) {
|
|
69638
70449
|
const normalized = typeof candidate === "string" ? candidate.trim() : "";
|
|
69639
70450
|
if (normalized) files.push(normalized);
|
|
@@ -69646,7 +70457,7 @@ function deriveToolErrors(toolMessages) {
|
|
|
69646
70457
|
for (const message of toolMessages) {
|
|
69647
70458
|
const toolName = toToolName(message?.toolName ?? message?.name);
|
|
69648
70459
|
const payload = message?.toolPayload ?? {};
|
|
69649
|
-
const content =
|
|
70460
|
+
const content = parseJsonObject2(message?.content);
|
|
69650
70461
|
if (payload?.status === "failed" || content?.ok === false || content?.applied === false || content?.success === false) {
|
|
69651
70462
|
errors.push(toolName || "unknown-tool");
|
|
69652
70463
|
}
|
|
@@ -71578,6 +72389,18 @@ function getCurrentProfile(config) {
|
|
|
71578
72389
|
if (!config) return null;
|
|
71579
72390
|
return config.profiles[config.currentProfile] ?? null;
|
|
71580
72391
|
}
|
|
72392
|
+
function saveProfileAgentSelection(selection, path7 = getDefaultProfileConfigPath()) {
|
|
72393
|
+
const config = loadProfileConfig(path7);
|
|
72394
|
+
if (!config) return null;
|
|
72395
|
+
const profile = config.profiles[config.currentProfile];
|
|
72396
|
+
if (!profile) return null;
|
|
72397
|
+
profile.agentKey = selection.agentKey.trim();
|
|
72398
|
+
profile.agentName = selection.agentName.trim();
|
|
72399
|
+
mkdirSync5(dirname6(path7), { recursive: true });
|
|
72400
|
+
writeFileSync4(path7, `${JSON.stringify(config, null, 2)}
|
|
72401
|
+
`, "utf8");
|
|
72402
|
+
return config;
|
|
72403
|
+
}
|
|
71581
72404
|
|
|
71582
72405
|
// packages/cli/authCommands.ts
|
|
71583
72406
|
init_cliEnvHelpers();
|
|
@@ -73315,23 +74138,410 @@ async function compactDialog(options) {
|
|
|
73315
74138
|
// packages/cli/tui/readlineWorkspace.ts
|
|
73316
74139
|
init_processSpawn();
|
|
73317
74140
|
|
|
73318
|
-
// packages/cli/tui/
|
|
73319
|
-
|
|
74141
|
+
// packages/cli/tui/agentPicker.ts
|
|
74142
|
+
init_agentAliases();
|
|
74143
|
+
|
|
74144
|
+
// packages/cli/tui/agentCatalog.ts
|
|
74145
|
+
init_cliEnvHelpers();
|
|
73320
74146
|
var DEFAULT_TUI_AGENT_KEY = "agent-pub-01NOLOAPPBLD000000019KCKT0";
|
|
73321
|
-
var
|
|
73322
|
-
var KNOWN_AGENTS = [
|
|
74147
|
+
var PLATFORM_AGENTS = [
|
|
73323
74148
|
{
|
|
73324
74149
|
name: "nolo",
|
|
73325
|
-
key:
|
|
74150
|
+
key: DEFAULT_TUI_AGENT_KEY,
|
|
74151
|
+
model: "-",
|
|
74152
|
+
kind: "platform",
|
|
73326
74153
|
description: "one assistant that routes work across your agents and data"
|
|
73327
74154
|
},
|
|
73328
74155
|
{
|
|
73329
74156
|
name: "app-builder",
|
|
73330
74157
|
key: "agent-pub-01APPBUILDER00000001YAII3I",
|
|
74158
|
+
model: "-",
|
|
74159
|
+
kind: "platform",
|
|
73331
74160
|
description: "builds web apps, tools, charts, and product prototypes"
|
|
73332
74161
|
}
|
|
73333
74162
|
];
|
|
73334
|
-
|
|
74163
|
+
function toUpdatedAt(value) {
|
|
74164
|
+
if (value == null) return 0;
|
|
74165
|
+
const parsed = new Date(value).getTime();
|
|
74166
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
74167
|
+
}
|
|
74168
|
+
function listedAgentToCatalogEntry(agent) {
|
|
74169
|
+
return {
|
|
74170
|
+
name: agent.name,
|
|
74171
|
+
key: agent.privateKey,
|
|
74172
|
+
model: agent.model,
|
|
74173
|
+
kind: "private",
|
|
74174
|
+
updatedAt: toUpdatedAt(agent.updatedAt)
|
|
74175
|
+
};
|
|
74176
|
+
}
|
|
74177
|
+
function mergeCatalogEntries(currentKey, platformAgents, privateAgents) {
|
|
74178
|
+
const seen = /* @__PURE__ */ new Set();
|
|
74179
|
+
const merged = [];
|
|
74180
|
+
const push = (entry) => {
|
|
74181
|
+
if (seen.has(entry.key)) return;
|
|
74182
|
+
seen.add(entry.key);
|
|
74183
|
+
merged.push(entry);
|
|
74184
|
+
};
|
|
74185
|
+
const current = [...platformAgents, ...privateAgents].find((entry) => entry.key === currentKey) ?? null;
|
|
74186
|
+
if (current) push(current);
|
|
74187
|
+
for (const entry of platformAgents) {
|
|
74188
|
+
if (entry.key !== currentKey) push(entry);
|
|
74189
|
+
}
|
|
74190
|
+
const sortedPrivate = [...privateAgents].sort((a, b) => {
|
|
74191
|
+
const tb = b.updatedAt ?? 0;
|
|
74192
|
+
const ta = a.updatedAt ?? 0;
|
|
74193
|
+
if (tb !== ta) return tb - ta;
|
|
74194
|
+
return a.name.localeCompare(b.name);
|
|
74195
|
+
});
|
|
74196
|
+
for (const entry of sortedPrivate) {
|
|
74197
|
+
if (entry.key !== currentKey) push(entry);
|
|
74198
|
+
}
|
|
74199
|
+
return merged;
|
|
74200
|
+
}
|
|
74201
|
+
async function loadAgentCatalog(args2) {
|
|
74202
|
+
const env = args2.env ?? process.env;
|
|
74203
|
+
const fetchImpl = args2.fetchImpl ?? fetch;
|
|
74204
|
+
const fallbackFetchImpl = args2.fallbackFetchImpl;
|
|
74205
|
+
const authToken = resolveAuthToken([], env);
|
|
74206
|
+
const userId = authToken ? parseUserIdFromAuthToken(authToken) : null;
|
|
74207
|
+
if (!authToken || !userId) {
|
|
74208
|
+
return mergeCatalogEntries(args2.currentKey, PLATFORM_AGENTS, []);
|
|
74209
|
+
}
|
|
74210
|
+
const serverUrl = resolveServerUrl(env);
|
|
74211
|
+
const serverUrls = resolveServerCandidates([], env, serverUrl);
|
|
74212
|
+
let privateAgents = [];
|
|
74213
|
+
try {
|
|
74214
|
+
const remoteResult = await listRemoteAgentsAcrossServers({
|
|
74215
|
+
authToken,
|
|
74216
|
+
fallbackFetchImpl,
|
|
74217
|
+
fetchImpl,
|
|
74218
|
+
includeLegacy: false,
|
|
74219
|
+
serverUrls,
|
|
74220
|
+
userId
|
|
74221
|
+
});
|
|
74222
|
+
privateAgents = remoteResult.agents.map(listedAgentToCatalogEntry);
|
|
74223
|
+
} catch {
|
|
74224
|
+
try {
|
|
74225
|
+
const db = await getReadableCliDb();
|
|
74226
|
+
const cached = await listLocalCachedAgents({ db, userId });
|
|
74227
|
+
privateAgents = cached.map(listedAgentToCatalogEntry);
|
|
74228
|
+
} catch {
|
|
74229
|
+
privateAgents = (await listRemoteAgents({
|
|
74230
|
+
authToken,
|
|
74231
|
+
fallbackFetchImpl,
|
|
74232
|
+
fetchImpl,
|
|
74233
|
+
includeLegacy: false,
|
|
74234
|
+
serverUrl,
|
|
74235
|
+
userId,
|
|
74236
|
+
queryUserRecords,
|
|
74237
|
+
readDbRecord
|
|
74238
|
+
})).map(listedAgentToCatalogEntry);
|
|
74239
|
+
}
|
|
74240
|
+
}
|
|
74241
|
+
return mergeCatalogEntries(args2.currentKey, PLATFORM_AGENTS, privateAgents);
|
|
74242
|
+
}
|
|
74243
|
+
function renderAgentCatalogList(entries, currentKey) {
|
|
74244
|
+
const lines = ["Agents:"];
|
|
74245
|
+
entries.forEach((entry, index) => {
|
|
74246
|
+
const current = entry.key === currentKey ? " (current)" : "";
|
|
74247
|
+
const kind = entry.kind === "platform" ? "platform" : "private";
|
|
74248
|
+
const detail = entry.description ? ` \u2014 ${entry.description}` : "";
|
|
74249
|
+
lines.push(
|
|
74250
|
+
` ${String(index + 1).padStart(2)} ${entry.name.padEnd(18)} ${entry.model.padEnd(14)} ${kind}${detail}${current}`
|
|
74251
|
+
);
|
|
74252
|
+
});
|
|
74253
|
+
lines.push("");
|
|
74254
|
+
lines.push("Tip: run /agent in an interactive terminal to pick with \u2191\u2193.");
|
|
74255
|
+
return lines.join("\n");
|
|
74256
|
+
}
|
|
74257
|
+
function findAgentCatalogEntry(entries, rawTarget) {
|
|
74258
|
+
const target = rawTarget.trim();
|
|
74259
|
+
if (!target) return null;
|
|
74260
|
+
if (/^\d+$/.test(target)) {
|
|
74261
|
+
const entry = entries[Number(target) - 1];
|
|
74262
|
+
return entry ? { name: entry.name, key: entry.key } : null;
|
|
74263
|
+
}
|
|
74264
|
+
const lower = target.toLowerCase();
|
|
74265
|
+
const byName = entries.find(
|
|
74266
|
+
(entry) => entry.name.toLowerCase() === lower || entry.key.toLowerCase() === lower || entry.key.toLowerCase().endsWith(`-${lower}`)
|
|
74267
|
+
);
|
|
74268
|
+
if (byName) return { name: byName.name, key: byName.key };
|
|
74269
|
+
if (target.startsWith("agent-") || target.startsWith("agent-pub-") || target.startsWith("cybot-")) {
|
|
74270
|
+
return { name: target, key: target };
|
|
74271
|
+
}
|
|
74272
|
+
return null;
|
|
74273
|
+
}
|
|
74274
|
+
|
|
74275
|
+
// packages/cli/tui/selectDialog.ts
|
|
74276
|
+
var CSI_ARROW_UP = "\x1B[A";
|
|
74277
|
+
var CSI_ARROW_DOWN = "\x1B[B";
|
|
74278
|
+
var CSI_ARROW_UP_APP = "\x1BOA";
|
|
74279
|
+
var CSI_ARROW_DOWN_APP = "\x1BOB";
|
|
74280
|
+
var DEFAULT_MAX_VISIBLE = 8;
|
|
74281
|
+
function computeVisibleWindow(args2) {
|
|
74282
|
+
const maxVisible = Math.max(1, args2.maxVisible ?? DEFAULT_MAX_VISIBLE);
|
|
74283
|
+
if (args2.total <= maxVisible) {
|
|
74284
|
+
return { start: 0, end: args2.total, maxVisible };
|
|
74285
|
+
}
|
|
74286
|
+
let start = Math.max(0, args2.selectedIndex - Math.floor(maxVisible / 2));
|
|
74287
|
+
if (start + maxVisible > args2.total) {
|
|
74288
|
+
start = args2.total - maxVisible;
|
|
74289
|
+
}
|
|
74290
|
+
return { start, end: start + maxVisible, maxVisible };
|
|
74291
|
+
}
|
|
74292
|
+
function renderSelectDialog(args2) {
|
|
74293
|
+
const total = args2.items.length;
|
|
74294
|
+
const window2 = computeVisibleWindow({
|
|
74295
|
+
selectedIndex: args2.selectedIndex,
|
|
74296
|
+
total,
|
|
74297
|
+
maxVisible: args2.maxVisible
|
|
74298
|
+
});
|
|
74299
|
+
const lines = [
|
|
74300
|
+
args2.title ?? `Select agent (\u2191\u2193 Enter Esc) ${args2.selectedIndex + 1}/${total}`
|
|
74301
|
+
];
|
|
74302
|
+
if (window2.start > 0) {
|
|
74303
|
+
lines.push(` ... ${window2.start} more above`);
|
|
74304
|
+
}
|
|
74305
|
+
for (let index = window2.start; index < window2.end; index += 1) {
|
|
74306
|
+
const item = args2.items[index];
|
|
74307
|
+
const marker = index === args2.selectedIndex ? ">" : " ";
|
|
74308
|
+
const detail = item.detail ? ` ${item.detail}` : "";
|
|
74309
|
+
lines.push(`${marker} ${item.label}${detail}`);
|
|
74310
|
+
}
|
|
74311
|
+
if (window2.end < total) {
|
|
74312
|
+
lines.push(` ... ${total - window2.end} more below`);
|
|
74313
|
+
}
|
|
74314
|
+
return lines.join("\n");
|
|
74315
|
+
}
|
|
74316
|
+
function countRenderedLines(text) {
|
|
74317
|
+
return text.split("\n").length;
|
|
74318
|
+
}
|
|
74319
|
+
function clearRenderedLines(output2, lineCount) {
|
|
74320
|
+
if (!output2.isTTY || lineCount <= 0) return;
|
|
74321
|
+
for (let index = 0; index < lineCount; index += 1) {
|
|
74322
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
74323
|
+
}
|
|
74324
|
+
}
|
|
74325
|
+
function isArrowUp(sequence) {
|
|
74326
|
+
return sequence === CSI_ARROW_UP || sequence === CSI_ARROW_UP_APP;
|
|
74327
|
+
}
|
|
74328
|
+
function isArrowDown(sequence) {
|
|
74329
|
+
return sequence === CSI_ARROW_DOWN || sequence === CSI_ARROW_DOWN_APP;
|
|
74330
|
+
}
|
|
74331
|
+
function isSubmit(sequence) {
|
|
74332
|
+
return sequence === "\r" || sequence === "\n";
|
|
74333
|
+
}
|
|
74334
|
+
function isCancel(sequence) {
|
|
74335
|
+
return sequence === "" || sequence === "\x1B";
|
|
74336
|
+
}
|
|
74337
|
+
function createRawKeyReader(input2) {
|
|
74338
|
+
let buffer = "";
|
|
74339
|
+
const tryParseSequence = () => {
|
|
74340
|
+
if (!buffer) return null;
|
|
74341
|
+
if (isSubmit(buffer) || isCancel(buffer)) {
|
|
74342
|
+
const sequence2 = buffer;
|
|
74343
|
+
buffer = "";
|
|
74344
|
+
return sequence2;
|
|
74345
|
+
}
|
|
74346
|
+
if (buffer.startsWith("\x1B")) {
|
|
74347
|
+
for (const candidate of [
|
|
74348
|
+
CSI_ARROW_UP,
|
|
74349
|
+
CSI_ARROW_DOWN,
|
|
74350
|
+
CSI_ARROW_UP_APP,
|
|
74351
|
+
CSI_ARROW_DOWN_APP
|
|
74352
|
+
]) {
|
|
74353
|
+
if (buffer.startsWith(candidate)) {
|
|
74354
|
+
buffer = buffer.slice(candidate.length);
|
|
74355
|
+
return candidate;
|
|
74356
|
+
}
|
|
74357
|
+
}
|
|
74358
|
+
if (buffer.length >= 8) {
|
|
74359
|
+
buffer = "";
|
|
74360
|
+
return null;
|
|
74361
|
+
}
|
|
74362
|
+
return void 0;
|
|
74363
|
+
}
|
|
74364
|
+
const sequence = buffer;
|
|
74365
|
+
buffer = "";
|
|
74366
|
+
return sequence;
|
|
74367
|
+
};
|
|
74368
|
+
return () => new Promise((resolve6) => {
|
|
74369
|
+
const finalize = (sequence) => {
|
|
74370
|
+
cleanup();
|
|
74371
|
+
resolve6(sequence ?? null);
|
|
74372
|
+
};
|
|
74373
|
+
const onReadable = () => {
|
|
74374
|
+
while (true) {
|
|
74375
|
+
const chunk = input2.read();
|
|
74376
|
+
if (chunk == null) break;
|
|
74377
|
+
buffer += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
74378
|
+
const parsed = tryParseSequence();
|
|
74379
|
+
if (parsed === void 0) return;
|
|
74380
|
+
finalize(parsed);
|
|
74381
|
+
return;
|
|
74382
|
+
}
|
|
74383
|
+
};
|
|
74384
|
+
const cleanup = () => {
|
|
74385
|
+
input2.off("readable", onReadable);
|
|
74386
|
+
};
|
|
74387
|
+
onReadable();
|
|
74388
|
+
if (buffer) {
|
|
74389
|
+
const parsed = tryParseSequence();
|
|
74390
|
+
if (parsed !== void 0) {
|
|
74391
|
+
finalize(parsed);
|
|
74392
|
+
return;
|
|
74393
|
+
}
|
|
74394
|
+
}
|
|
74395
|
+
input2.on("readable", onReadable);
|
|
74396
|
+
});
|
|
74397
|
+
}
|
|
74398
|
+
function drainInputBuffer(input2) {
|
|
74399
|
+
if (typeof input2.read !== "function") return;
|
|
74400
|
+
while (input2.read() !== null) {
|
|
74401
|
+
}
|
|
74402
|
+
}
|
|
74403
|
+
async function runSelectDialog(args2) {
|
|
74404
|
+
const items = args2.items;
|
|
74405
|
+
if (items.length === 0) {
|
|
74406
|
+
return { kind: "cancelled" };
|
|
74407
|
+
}
|
|
74408
|
+
let selectedIndex = Math.min(
|
|
74409
|
+
Math.max(args2.initialIndex ?? 0, 0),
|
|
74410
|
+
items.length - 1
|
|
74411
|
+
);
|
|
74412
|
+
const output2 = args2.output ?? process.stdout;
|
|
74413
|
+
const input2 = args2.input ?? process.stdin;
|
|
74414
|
+
const readKey = args2.readKey ?? createRawKeyReader(input2);
|
|
74415
|
+
const wasRaw = Boolean(input2.isTTY && input2.isRaw);
|
|
74416
|
+
const wasPaused = typeof input2.isPaused === "function" ? input2.isPaused() : false;
|
|
74417
|
+
let renderedLineCount = 0;
|
|
74418
|
+
const paint = () => {
|
|
74419
|
+
const frame = renderSelectDialog({
|
|
74420
|
+
items,
|
|
74421
|
+
selectedIndex,
|
|
74422
|
+
title: args2.title,
|
|
74423
|
+
maxVisible: args2.maxVisible
|
|
74424
|
+
});
|
|
74425
|
+
if (output2.isTTY && typeof output2.write === "function") {
|
|
74426
|
+
clearRenderedLines(output2, renderedLineCount);
|
|
74427
|
+
output2.write(`${frame}
|
|
74428
|
+
`);
|
|
74429
|
+
renderedLineCount = countRenderedLines(frame);
|
|
74430
|
+
return;
|
|
74431
|
+
}
|
|
74432
|
+
if (typeof output2.write === "function") {
|
|
74433
|
+
output2.write(`${frame}
|
|
74434
|
+
`);
|
|
74435
|
+
}
|
|
74436
|
+
renderedLineCount = countRenderedLines(frame);
|
|
74437
|
+
};
|
|
74438
|
+
if (input2.isTTY) {
|
|
74439
|
+
if (!wasRaw) input2.setRawMode(true);
|
|
74440
|
+
if (!wasPaused) input2.pause();
|
|
74441
|
+
}
|
|
74442
|
+
paint();
|
|
74443
|
+
try {
|
|
74444
|
+
while (true) {
|
|
74445
|
+
const sequence = await readKey();
|
|
74446
|
+
if (sequence == null) {
|
|
74447
|
+
return { kind: "cancelled" };
|
|
74448
|
+
}
|
|
74449
|
+
if (isCancel(sequence)) {
|
|
74450
|
+
return { kind: "cancelled" };
|
|
74451
|
+
}
|
|
74452
|
+
if (isSubmit(sequence)) {
|
|
74453
|
+
return { kind: "selected", index: selectedIndex, item: items[selectedIndex] };
|
|
74454
|
+
}
|
|
74455
|
+
if (isArrowUp(sequence)) {
|
|
74456
|
+
selectedIndex = selectedIndex <= 0 ? items.length - 1 : selectedIndex - 1;
|
|
74457
|
+
paint();
|
|
74458
|
+
continue;
|
|
74459
|
+
}
|
|
74460
|
+
if (isArrowDown(sequence)) {
|
|
74461
|
+
selectedIndex = selectedIndex >= items.length - 1 ? 0 : selectedIndex + 1;
|
|
74462
|
+
paint();
|
|
74463
|
+
continue;
|
|
74464
|
+
}
|
|
74465
|
+
}
|
|
74466
|
+
} finally {
|
|
74467
|
+
if (input2.isTTY) {
|
|
74468
|
+
drainInputBuffer(input2);
|
|
74469
|
+
if (!wasRaw) input2.setRawMode(false);
|
|
74470
|
+
if (!wasPaused) input2.resume();
|
|
74471
|
+
clearRenderedLines(output2, renderedLineCount);
|
|
74472
|
+
renderedLineCount = 0;
|
|
74473
|
+
}
|
|
74474
|
+
}
|
|
74475
|
+
}
|
|
74476
|
+
|
|
74477
|
+
// packages/cli/tui/agentPicker.ts
|
|
74478
|
+
function toAgentPickerItems(entries) {
|
|
74479
|
+
return entries.map((entry) => ({
|
|
74480
|
+
label: entry.name,
|
|
74481
|
+
detail: `${entry.model} ${entry.kind}`,
|
|
74482
|
+
entry
|
|
74483
|
+
}));
|
|
74484
|
+
}
|
|
74485
|
+
function formatAgentSwitchMessage(args2) {
|
|
74486
|
+
const dialog = args2.dialogId ? `Dialog kept: ${args2.dialogId}` : "Dialog kept: new";
|
|
74487
|
+
return `Switched to ${args2.name}. ${dialog}`;
|
|
74488
|
+
}
|
|
74489
|
+
async function runAgentPicker(args2) {
|
|
74490
|
+
const output2 = args2.output ?? process.stdout;
|
|
74491
|
+
const input2 = args2.input ?? process.stdin;
|
|
74492
|
+
const interactive = args2.interactive ?? Boolean(input2.isTTY && output2.isTTY);
|
|
74493
|
+
const entries = await loadAgentCatalog({
|
|
74494
|
+
env: args2.env,
|
|
74495
|
+
currentKey: args2.currentKey,
|
|
74496
|
+
fetchImpl: args2.fetchImpl,
|
|
74497
|
+
fallbackFetchImpl: args2.fallbackFetchImpl
|
|
74498
|
+
});
|
|
74499
|
+
if (!interactive) {
|
|
74500
|
+
return {
|
|
74501
|
+
kind: "list",
|
|
74502
|
+
output: renderAgentCatalogList(entries, args2.currentKey),
|
|
74503
|
+
entries
|
|
74504
|
+
};
|
|
74505
|
+
}
|
|
74506
|
+
const items = toAgentPickerItems(entries);
|
|
74507
|
+
const initialIndex = Math.max(
|
|
74508
|
+
entries.findIndex((entry) => entry.key === args2.currentKey),
|
|
74509
|
+
0
|
|
74510
|
+
);
|
|
74511
|
+
const result = await runSelectDialog({
|
|
74512
|
+
items,
|
|
74513
|
+
initialIndex,
|
|
74514
|
+
title: void 0,
|
|
74515
|
+
input: input2,
|
|
74516
|
+
output: output2,
|
|
74517
|
+
readKey: args2.readKey
|
|
74518
|
+
});
|
|
74519
|
+
if (result.kind === "cancelled") {
|
|
74520
|
+
return { kind: "cancelled", entries };
|
|
74521
|
+
}
|
|
74522
|
+
const selected = result.item.entry;
|
|
74523
|
+
return {
|
|
74524
|
+
kind: "selected",
|
|
74525
|
+
name: selected.name,
|
|
74526
|
+
key: selected.key,
|
|
74527
|
+
entries
|
|
74528
|
+
};
|
|
74529
|
+
}
|
|
74530
|
+
function resolveAgentSwitchTarget(rawTarget, catalogEntries = []) {
|
|
74531
|
+
const resolvedKey = resolveCliAgentKeyInput(rawTarget);
|
|
74532
|
+
if (resolvedKey !== rawTarget.trim()) {
|
|
74533
|
+
const aliasEntry = catalogEntries.find((entry) => entry.key === resolvedKey);
|
|
74534
|
+
return {
|
|
74535
|
+
name: aliasEntry?.name ?? rawTarget.trim().toLowerCase(),
|
|
74536
|
+
key: resolvedKey
|
|
74537
|
+
};
|
|
74538
|
+
}
|
|
74539
|
+
return findAgentCatalogEntry(catalogEntries, rawTarget);
|
|
74540
|
+
}
|
|
74541
|
+
|
|
74542
|
+
// packages/cli/tui/session.ts
|
|
74543
|
+
init_defaultServer();
|
|
74544
|
+
var DEFAULT_TUI_SERVER_URL = DEFAULT_NOLO_SERVER_URL;
|
|
73335
74545
|
function shortenDialogId(dialogId) {
|
|
73336
74546
|
return dialogId.length > 12 ? `${dialogId.slice(0, 6)}...${dialogId.slice(-4)}` : dialogId;
|
|
73337
74547
|
}
|
|
@@ -73353,25 +74563,29 @@ function createInitialTuiState(env = process.env) {
|
|
|
73353
74563
|
),
|
|
73354
74564
|
cliVersion: env.NOLO_CLI_VERSION?.trim() || void 0,
|
|
73355
74565
|
attachedDocs: [],
|
|
73356
|
-
runtimeMode: env.NOLO_RUNTIME_MODE === "local" || env.NOLO_RUNTIME_MODE === "server" ? env.NOLO_RUNTIME_MODE : "auto"
|
|
74566
|
+
runtimeMode: env.NOLO_RUNTIME_MODE === "local" || env.NOLO_RUNTIME_MODE === "server" ? env.NOLO_RUNTIME_MODE : "auto",
|
|
74567
|
+
thinkingDisplay: normalizeThinkingDisplayMode(
|
|
74568
|
+
env.NOLO_CLI_THINKING ?? env.NOLO_THINKING,
|
|
74569
|
+
"hide"
|
|
74570
|
+
),
|
|
74571
|
+
toolDisplay: normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact"),
|
|
74572
|
+
renderDisplay: normalizeRenderDisplayMode(env.NOLO_CLI_RENDER ?? env.NOLO_RENDER, "rich")
|
|
73357
74573
|
};
|
|
73358
74574
|
}
|
|
73359
74575
|
function renderStatusLine(state) {
|
|
73360
|
-
const
|
|
73361
|
-
|
|
73362
|
-
|
|
73363
|
-
|
|
73364
|
-
|
|
73365
|
-
|
|
73366
|
-
|
|
73367
|
-
].join(" | ");
|
|
74576
|
+
const colorEnabled = resolveCliColorEnabled();
|
|
74577
|
+
const agent = styleCliText(state.agentName, "cyan", colorEnabled);
|
|
74578
|
+
const tokens = dimCliText(renderTokenStatus(state.turnTokens), colorEnabled);
|
|
74579
|
+
const profile = dimCliText(`profile ${state.profileName}`, colorEnabled);
|
|
74580
|
+
return [`agent ${agent}`, tokens, profile].join(
|
|
74581
|
+
dimCliText(" | ", colorEnabled)
|
|
74582
|
+
);
|
|
73368
74583
|
}
|
|
73369
74584
|
function renderWelcome(state) {
|
|
73370
|
-
const docs = state.attachedDocs.length > 0 ? `${state.attachedDocs.length} attached` : "none";
|
|
73371
74585
|
return [
|
|
73372
74586
|
"",
|
|
73373
74587
|
`Nolo workspace${state.cliVersion ? ` nolo ${state.cliVersion}` : ""}`,
|
|
73374
|
-
`agent ${state.agentName} |
|
|
74588
|
+
`agent ${state.agentName} | ${renderTokenStatus(state.turnTokens)} | profile ${state.profileName}`,
|
|
73375
74589
|
`server ${state.serverUrl}`,
|
|
73376
74590
|
"",
|
|
73377
74591
|
"Tell nolo what you want. Use /help for commands. Use /version if this install feels stale.",
|
|
@@ -73389,9 +74603,14 @@ function renderTuiHelp() {
|
|
|
73389
74603
|
" /compact Compact current dialog and fork a new one",
|
|
73390
74604
|
" /context Show workspace context and next actions",
|
|
73391
74605
|
" /runtime <mode> Use auto, local, or server runtime",
|
|
73392
|
-
" /
|
|
73393
|
-
" /
|
|
73394
|
-
" /
|
|
74606
|
+
" /tools <mode> Control tool trace: hide, compact, verbose",
|
|
74607
|
+
" /thinking <mode> Control thinking output: hide, marker, show",
|
|
74608
|
+
" /render <mode> Control assistant output: plain, rich",
|
|
74609
|
+
" /agent Pick an agent interactively (\u2191\u2193, Enter)",
|
|
74610
|
+
" /agent list List agents as text",
|
|
74611
|
+
" /agent <name> Switch directly by name, alias, or key",
|
|
74612
|
+
" /agents List platform agent shortcuts",
|
|
74613
|
+
" /switch <agent> Switch the current agent (alias of /agent <name>)",
|
|
73395
74614
|
" /dialog Show the current dialog",
|
|
73396
74615
|
" /doc List attached docs",
|
|
73397
74616
|
" /doc attach <doc> Attach a doc to this workspace",
|
|
@@ -73410,12 +74629,16 @@ function renderContextPanel(state) {
|
|
|
73410
74629
|
return [
|
|
73411
74630
|
"Workspace context",
|
|
73412
74631
|
"-----------------",
|
|
73413
|
-
`agent
|
|
73414
|
-
`
|
|
73415
|
-
`
|
|
73416
|
-
`
|
|
73417
|
-
`
|
|
73418
|
-
`
|
|
74632
|
+
`agent ${state.agentName}`,
|
|
74633
|
+
`tokens ${renderTokenStatus(state.turnTokens)}`,
|
|
74634
|
+
`dialog ${resolveDialogLabel(state)}`,
|
|
74635
|
+
`docs ${docs}`,
|
|
74636
|
+
`profile ${state.profileName}`,
|
|
74637
|
+
`runtime ${state.runtimeMode}`,
|
|
74638
|
+
`tools ${state.toolDisplay}`,
|
|
74639
|
+
`thinking ${state.thinkingDisplay}`,
|
|
74640
|
+
`render ${state.renderDisplay}`,
|
|
74641
|
+
`server ${state.serverUrl}`,
|
|
73419
74642
|
"",
|
|
73420
74643
|
"Next:",
|
|
73421
74644
|
" /agents see specialist shortcuts",
|
|
@@ -73426,25 +74649,22 @@ function renderContextPanel(state) {
|
|
|
73426
74649
|
function renderKnownAgents() {
|
|
73427
74650
|
return [
|
|
73428
74651
|
"Agents:",
|
|
73429
|
-
...
|
|
73430
|
-
(agent, index) => ` ${index + 1} ${agent.name.padEnd(11)} ${agent.description}`
|
|
74652
|
+
...PLATFORM_AGENTS.map(
|
|
74653
|
+
(agent, index) => ` ${index + 1} ${agent.name.padEnd(11)} ${agent.description ?? ""}`
|
|
73431
74654
|
),
|
|
73432
74655
|
"",
|
|
73433
|
-
"Tip:
|
|
74656
|
+
"Tip: run /agent for the full picker, or /agent list for your private agents too."
|
|
73434
74657
|
].join("\n");
|
|
73435
74658
|
}
|
|
73436
|
-
function
|
|
73437
|
-
|
|
73438
|
-
|
|
73439
|
-
|
|
73440
|
-
|
|
73441
|
-
|
|
73442
|
-
|
|
73443
|
-
|
|
73444
|
-
|
|
73445
|
-
return { name: target, key: target };
|
|
73446
|
-
}
|
|
73447
|
-
return null;
|
|
74659
|
+
function applyAgentSwitch(state, target) {
|
|
74660
|
+
return {
|
|
74661
|
+
nextState: {
|
|
74662
|
+
...state,
|
|
74663
|
+
agentName: target.name,
|
|
74664
|
+
agentKey: target.key
|
|
74665
|
+
},
|
|
74666
|
+
output: `Switched to ${target.name}. ${state.dialogId ? `Dialog kept: ${state.dialogId}` : "Dialog kept: new"}`
|
|
74667
|
+
};
|
|
73448
74668
|
}
|
|
73449
74669
|
var DIALOG_ID_PATTERN = /[0-9A-HJKMNP-TV-Z]{26}/i;
|
|
73450
74670
|
var DIALOG_KEY_PATTERN = /dialog-[^\s"'<>]+-[0-9A-HJKMNP-TV-Z]{26}/i;
|
|
@@ -73622,6 +74842,66 @@ function handleTuiInput(input2, state) {
|
|
|
73622
74842
|
output: `Runtime: ${argText}`
|
|
73623
74843
|
};
|
|
73624
74844
|
}
|
|
74845
|
+
case "/tools": {
|
|
74846
|
+
if (!argText) {
|
|
74847
|
+
return {
|
|
74848
|
+
nextState: state,
|
|
74849
|
+
output: `Tool display: ${state.toolDisplay} (hide | compact | verbose)`
|
|
74850
|
+
};
|
|
74851
|
+
}
|
|
74852
|
+
const normalizedArg = argText.trim().toLowerCase();
|
|
74853
|
+
if (!["hide", "compact", "verbose", "on", "off"].includes(normalizedArg)) {
|
|
74854
|
+
return {
|
|
74855
|
+
nextState: state,
|
|
74856
|
+
output: "Usage: /tools <hide|compact|verbose>"
|
|
74857
|
+
};
|
|
74858
|
+
}
|
|
74859
|
+
const nextMode = normalizeToolDisplayMode(normalizedArg, state.toolDisplay);
|
|
74860
|
+
return {
|
|
74861
|
+
nextState: { ...state, toolDisplay: nextMode },
|
|
74862
|
+
output: `Tool display: ${nextMode}`
|
|
74863
|
+
};
|
|
74864
|
+
}
|
|
74865
|
+
case "/thinking": {
|
|
74866
|
+
if (!argText) {
|
|
74867
|
+
return {
|
|
74868
|
+
nextState: state,
|
|
74869
|
+
output: `Thinking display: ${state.thinkingDisplay} (hide | marker | show)`
|
|
74870
|
+
};
|
|
74871
|
+
}
|
|
74872
|
+
const normalizedArg = argText.trim().toLowerCase();
|
|
74873
|
+
if (!["hide", "marker", "show", "on", "off"].includes(normalizedArg)) {
|
|
74874
|
+
return {
|
|
74875
|
+
nextState: state,
|
|
74876
|
+
output: "Usage: /thinking <hide|marker|show>"
|
|
74877
|
+
};
|
|
74878
|
+
}
|
|
74879
|
+
const nextMode = normalizeThinkingDisplayMode(normalizedArg, state.thinkingDisplay);
|
|
74880
|
+
return {
|
|
74881
|
+
nextState: { ...state, thinkingDisplay: nextMode },
|
|
74882
|
+
output: `Thinking display: ${nextMode}`
|
|
74883
|
+
};
|
|
74884
|
+
}
|
|
74885
|
+
case "/render": {
|
|
74886
|
+
if (!argText) {
|
|
74887
|
+
return {
|
|
74888
|
+
nextState: state,
|
|
74889
|
+
output: `Render display: ${state.renderDisplay} (plain | rich)`
|
|
74890
|
+
};
|
|
74891
|
+
}
|
|
74892
|
+
const normalizedArg = argText.trim().toLowerCase();
|
|
74893
|
+
if (!["plain", "rich", "on", "off"].includes(normalizedArg)) {
|
|
74894
|
+
return {
|
|
74895
|
+
nextState: state,
|
|
74896
|
+
output: "Usage: /render <plain|rich>"
|
|
74897
|
+
};
|
|
74898
|
+
}
|
|
74899
|
+
const nextMode = normalizeRenderDisplayMode(normalizedArg, state.renderDisplay);
|
|
74900
|
+
return {
|
|
74901
|
+
nextState: { ...state, renderDisplay: nextMode },
|
|
74902
|
+
output: `Render display: ${nextMode}`
|
|
74903
|
+
};
|
|
74904
|
+
}
|
|
73625
74905
|
case "/exit":
|
|
73626
74906
|
case "/quit":
|
|
73627
74907
|
return { nextState: state, output: "Bye.", action: { type: "exit" } };
|
|
@@ -73631,7 +74911,8 @@ function handleTuiInput(input2, state) {
|
|
|
73631
74911
|
...state,
|
|
73632
74912
|
dialogId: void 0,
|
|
73633
74913
|
dialogLabel: "new",
|
|
73634
|
-
attachedDocs: []
|
|
74914
|
+
attachedDocs: [],
|
|
74915
|
+
turnTokens: void 0
|
|
73635
74916
|
},
|
|
73636
74917
|
output: "Started a fresh dialog."
|
|
73637
74918
|
};
|
|
@@ -73655,11 +74936,37 @@ ${renderTuiHelp()}`
|
|
|
73655
74936
|
output: "Compacting current dialog...",
|
|
73656
74937
|
action: { type: "compact", dialogId: state.dialogId }
|
|
73657
74938
|
};
|
|
73658
|
-
case "/agent":
|
|
73659
|
-
|
|
73660
|
-
|
|
73661
|
-
|
|
73662
|
-
|
|
74939
|
+
case "/agent": {
|
|
74940
|
+
if (!argText) {
|
|
74941
|
+
return {
|
|
74942
|
+
nextState: state,
|
|
74943
|
+
output: "",
|
|
74944
|
+
action: { type: "pick-agent" }
|
|
74945
|
+
};
|
|
74946
|
+
}
|
|
74947
|
+
if (argText === "list") {
|
|
74948
|
+
return {
|
|
74949
|
+
nextState: state,
|
|
74950
|
+
output: "",
|
|
74951
|
+
action: { type: "list-agents" }
|
|
74952
|
+
};
|
|
74953
|
+
}
|
|
74954
|
+
if (argText === "current" || argText === "show") {
|
|
74955
|
+
return {
|
|
74956
|
+
nextState: state,
|
|
74957
|
+
output: `Current agent: ${state.agentName} (${state.agentKey})`
|
|
74958
|
+
};
|
|
74959
|
+
}
|
|
74960
|
+
const resolvedTarget = resolveAgentSwitchTarget(argText, PLATFORM_AGENTS);
|
|
74961
|
+
if (!resolvedTarget) {
|
|
74962
|
+
return {
|
|
74963
|
+
nextState: state,
|
|
74964
|
+
output: `I don't know agent "${argText}" yet.
|
|
74965
|
+
Use /agent, /agent list, /agent minimax-m3, or a full agent key.`
|
|
74966
|
+
};
|
|
74967
|
+
}
|
|
74968
|
+
return applyAgentSwitch(state, resolvedTarget);
|
|
74969
|
+
}
|
|
73663
74970
|
case "/agents":
|
|
73664
74971
|
return {
|
|
73665
74972
|
nextState: state,
|
|
@@ -73669,25 +74976,18 @@ ${renderTuiHelp()}`
|
|
|
73669
74976
|
if (!argText) {
|
|
73670
74977
|
return {
|
|
73671
74978
|
nextState: state,
|
|
73672
|
-
output: "Usage: /switch <agent-key|alias>"
|
|
74979
|
+
output: "Usage: /switch <agent-key|alias> (or run /agent)"
|
|
73673
74980
|
};
|
|
73674
74981
|
}
|
|
73675
|
-
const resolvedTarget =
|
|
74982
|
+
const resolvedTarget = resolveAgentSwitchTarget(argText, PLATFORM_AGENTS);
|
|
73676
74983
|
if (!resolvedTarget) {
|
|
73677
74984
|
return {
|
|
73678
74985
|
nextState: state,
|
|
73679
74986
|
output: `I don't know agent shortcut "${argText}" yet.
|
|
73680
|
-
Use /switch nolo, /switch
|
|
74987
|
+
Use /agent, /switch nolo, /switch minimax-m3, or a full agent key.`
|
|
73681
74988
|
};
|
|
73682
74989
|
}
|
|
73683
|
-
return
|
|
73684
|
-
nextState: {
|
|
73685
|
-
...state,
|
|
73686
|
-
agentName: resolvedTarget.name,
|
|
73687
|
-
agentKey: resolvedTarget.key
|
|
73688
|
-
},
|
|
73689
|
-
output: `Switched to ${resolvedTarget.name}.`
|
|
73690
|
-
};
|
|
74990
|
+
return applyAgentSwitch(state, resolvedTarget);
|
|
73691
74991
|
}
|
|
73692
74992
|
case "/dialog":
|
|
73693
74993
|
return {
|
|
@@ -73758,8 +75058,14 @@ async function runAgentChat(scriptDir, state, message, env, output2, agentRunner
|
|
|
73758
75058
|
message,
|
|
73759
75059
|
continueDialogId: state.dialogId,
|
|
73760
75060
|
runtimeMode: state.runtimeMode,
|
|
75061
|
+
localRuntimeCwd: process.cwd(),
|
|
73761
75062
|
scriptDir,
|
|
73762
|
-
env
|
|
75063
|
+
env: {
|
|
75064
|
+
...env,
|
|
75065
|
+
NOLO_CLI_THINKING: state.thinkingDisplay,
|
|
75066
|
+
NOLO_CLI_TOOLS: state.toolDisplay,
|
|
75067
|
+
NOLO_CLI_RENDER: state.renderDisplay
|
|
75068
|
+
},
|
|
73763
75069
|
output: output2
|
|
73764
75070
|
});
|
|
73765
75071
|
return result;
|
|
@@ -73785,6 +75091,19 @@ async function runCliCommandInChildProcess(args2, context) {
|
|
|
73785
75091
|
]);
|
|
73786
75092
|
return proc.exited;
|
|
73787
75093
|
}
|
|
75094
|
+
function persistAgentSelection(state, env) {
|
|
75095
|
+
try {
|
|
75096
|
+
saveProfileAgentSelection({
|
|
75097
|
+
agentKey: state.agentKey,
|
|
75098
|
+
agentName: state.agentName
|
|
75099
|
+
});
|
|
75100
|
+
} catch {
|
|
75101
|
+
}
|
|
75102
|
+
if (env) {
|
|
75103
|
+
env.NOLO_AGENT = state.agentKey;
|
|
75104
|
+
env.NOLO_AGENT_NAME = state.agentName;
|
|
75105
|
+
}
|
|
75106
|
+
}
|
|
73788
75107
|
async function startTuiWorkspace(options) {
|
|
73789
75108
|
let state = createInitialTuiState(options.env ?? process.env);
|
|
73790
75109
|
const input2 = options.input ?? defaultInput;
|
|
@@ -73798,12 +75117,19 @@ async function startTuiWorkspace(options) {
|
|
|
73798
75117
|
rl.prompt();
|
|
73799
75118
|
try {
|
|
73800
75119
|
for await (const line of rl) {
|
|
75120
|
+
if (!line.trim()) {
|
|
75121
|
+
continue;
|
|
75122
|
+
}
|
|
73801
75123
|
const result = handleTuiInput(line, state);
|
|
75124
|
+
const previousAgentKey = state.agentKey;
|
|
73802
75125
|
state = result.nextState;
|
|
73803
75126
|
if (result.output) {
|
|
73804
75127
|
output2.write(`${result.output}
|
|
73805
75128
|
`);
|
|
73806
75129
|
}
|
|
75130
|
+
if (state.agentKey !== previousAgentKey && result.output?.startsWith("Switched to ")) {
|
|
75131
|
+
persistAgentSelection(state, options.env ?? process.env);
|
|
75132
|
+
}
|
|
73807
75133
|
if (result.action?.type === "exit") {
|
|
73808
75134
|
break;
|
|
73809
75135
|
}
|
|
@@ -73842,6 +75168,64 @@ async function startTuiWorkspace(options) {
|
|
|
73842
75168
|
output2.write("Update failed. Check the error above, then run /update again or use nolo update.\n");
|
|
73843
75169
|
}
|
|
73844
75170
|
}
|
|
75171
|
+
if (result.action?.type === "pick-agent") {
|
|
75172
|
+
rl.pause();
|
|
75173
|
+
try {
|
|
75174
|
+
const pickResult = await runAgentPicker({
|
|
75175
|
+
currentKey: state.agentKey,
|
|
75176
|
+
env: options.env ?? process.env,
|
|
75177
|
+
input: input2,
|
|
75178
|
+
output: output2
|
|
75179
|
+
});
|
|
75180
|
+
if (pickResult.kind === "list") {
|
|
75181
|
+
output2.write(`${pickResult.output}
|
|
75182
|
+
`);
|
|
75183
|
+
} else if (pickResult.kind === "selected") {
|
|
75184
|
+
state = {
|
|
75185
|
+
...state,
|
|
75186
|
+
agentName: pickResult.name,
|
|
75187
|
+
agentKey: pickResult.key
|
|
75188
|
+
};
|
|
75189
|
+
persistAgentSelection(state, options.env ?? process.env);
|
|
75190
|
+
output2.write(
|
|
75191
|
+
`${formatAgentSwitchMessage({
|
|
75192
|
+
name: pickResult.name,
|
|
75193
|
+
dialogId: state.dialogId
|
|
75194
|
+
})}
|
|
75195
|
+
`
|
|
75196
|
+
);
|
|
75197
|
+
} else {
|
|
75198
|
+
output2.write("Agent switch cancelled.\n");
|
|
75199
|
+
}
|
|
75200
|
+
} catch (error) {
|
|
75201
|
+
output2.write(
|
|
75202
|
+
`[nolo] Agent picker failed: ${error instanceof Error ? error.message : String(error)}
|
|
75203
|
+
`
|
|
75204
|
+
);
|
|
75205
|
+
} finally {
|
|
75206
|
+
rl.resume();
|
|
75207
|
+
}
|
|
75208
|
+
}
|
|
75209
|
+
if (result.action?.type === "list-agents") {
|
|
75210
|
+
try {
|
|
75211
|
+
const pickResult = await runAgentPicker({
|
|
75212
|
+
currentKey: state.agentKey,
|
|
75213
|
+
env: options.env ?? process.env,
|
|
75214
|
+
input: input2,
|
|
75215
|
+
output: output2,
|
|
75216
|
+
interactive: false
|
|
75217
|
+
});
|
|
75218
|
+
if (pickResult.kind === "list") {
|
|
75219
|
+
output2.write(`${pickResult.output}
|
|
75220
|
+
`);
|
|
75221
|
+
}
|
|
75222
|
+
} catch (error) {
|
|
75223
|
+
output2.write(
|
|
75224
|
+
`[nolo] Agent list failed: ${error instanceof Error ? error.message : String(error)}
|
|
75225
|
+
`
|
|
75226
|
+
);
|
|
75227
|
+
}
|
|
75228
|
+
}
|
|
73845
75229
|
if (result.action?.type === "cli-command") {
|
|
73846
75230
|
try {
|
|
73847
75231
|
const exitCode2 = await cliCommandRunner(result.action.args, {
|
|
@@ -73870,11 +75254,14 @@ async function startTuiWorkspace(options) {
|
|
|
73870
75254
|
output2,
|
|
73871
75255
|
options.agentRunner
|
|
73872
75256
|
);
|
|
73873
|
-
if (runResult.dialogId) {
|
|
75257
|
+
if (runResult.dialogId || runResult.turnTokens) {
|
|
73874
75258
|
state = {
|
|
73875
75259
|
...state,
|
|
73876
|
-
|
|
73877
|
-
|
|
75260
|
+
...runResult.dialogId ? {
|
|
75261
|
+
dialogId: runResult.dialogId,
|
|
75262
|
+
dialogLabel: runResult.dialogId
|
|
75263
|
+
} : {},
|
|
75264
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
73878
75265
|
};
|
|
73879
75266
|
}
|
|
73880
75267
|
}
|