nolo-cli 0.1.47 → 0.1.48
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 +1486 -179
- 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,138 @@ 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
|
+
async function readOpenAiCompatibleSseCompletion(args2) {
|
|
3440
|
+
const reader = args2.response.body?.getReader();
|
|
3441
|
+
if (!reader) {
|
|
3442
|
+
throw new Error("OpenAI-compatible stream response did not include a readable body.");
|
|
3443
|
+
}
|
|
3444
|
+
const decoder = new TextDecoder();
|
|
3445
|
+
let buffer = "";
|
|
3446
|
+
let content = "";
|
|
3447
|
+
let reasoning = "";
|
|
3448
|
+
let usage2;
|
|
3449
|
+
const accumulatedToolCalls = {};
|
|
3450
|
+
while (true) {
|
|
3451
|
+
const { done, value } = await reader.read();
|
|
3452
|
+
if (done) break;
|
|
3453
|
+
buffer += decoder.decode(value, { stream: true });
|
|
3454
|
+
while (true) {
|
|
3455
|
+
const boundary = buffer.indexOf("\n\n");
|
|
3456
|
+
if (boundary === -1) break;
|
|
3457
|
+
const event = buffer.slice(0, boundary);
|
|
3458
|
+
buffer = buffer.slice(boundary + 2);
|
|
3459
|
+
for (const line of event.split("\n")) {
|
|
3460
|
+
const trimmed = line.trim();
|
|
3461
|
+
if (!trimmed.startsWith("data:")) continue;
|
|
3462
|
+
const payload = trimmed.slice(5).trim();
|
|
3463
|
+
if (!payload || payload === "[DONE]") continue;
|
|
3464
|
+
let parsed;
|
|
3465
|
+
try {
|
|
3466
|
+
parsed = JSON.parse(payload);
|
|
3467
|
+
} catch {
|
|
3468
|
+
continue;
|
|
3469
|
+
}
|
|
3470
|
+
if (parsed?.usage && typeof parsed.usage === "object") {
|
|
3471
|
+
usage2 = parsed.usage;
|
|
3472
|
+
}
|
|
3473
|
+
const delta = parsed?.choices?.[0]?.delta;
|
|
3474
|
+
if (!delta || typeof delta !== "object") continue;
|
|
3475
|
+
const reasoningChunk = typeof delta.reasoning_content === "string" ? delta.reasoning_content : typeof delta.reasoning === "string" ? delta.reasoning : "";
|
|
3476
|
+
if (reasoningChunk) reasoning += reasoningChunk;
|
|
3477
|
+
if (Array.isArray(delta.tool_calls) && delta.tool_calls.length > 0) {
|
|
3478
|
+
accumulateToolCallDelta(accumulatedToolCalls, delta.tool_calls);
|
|
3479
|
+
}
|
|
3480
|
+
const textChunk = typeof delta.content === "string" ? delta.content : "";
|
|
3481
|
+
if (textChunk) {
|
|
3482
|
+
content += textChunk;
|
|
3483
|
+
args2.onTextDelta?.(textChunk);
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
}
|
|
3487
|
+
}
|
|
3488
|
+
const tool_calls = finalizeAccumulatedToolCalls(accumulatedToolCalls);
|
|
3489
|
+
return {
|
|
3490
|
+
content,
|
|
3491
|
+
...reasoning ? { reasoning_content: reasoning } : {},
|
|
3492
|
+
...tool_calls.length > 0 ? { tool_calls } : {},
|
|
3493
|
+
...usage2 ? { usage: usage2 } : {}
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
async function executeOpenAiCompatibleChatCompletion(args2) {
|
|
3497
|
+
const request = buildOpenAiCompatibleChatCompletionRequest({
|
|
3498
|
+
providerConfig: args2.providerConfig,
|
|
3499
|
+
messages: args2.messages,
|
|
3500
|
+
tools: args2.tools,
|
|
3501
|
+
stream: args2.stream
|
|
3502
|
+
});
|
|
3503
|
+
const res = await args2.fetchImpl(request.url, {
|
|
3504
|
+
...request.init,
|
|
3505
|
+
...args2.signal ? { signal: args2.signal } : {}
|
|
3506
|
+
});
|
|
3507
|
+
if (!res.ok) {
|
|
3508
|
+
const raw2 = await res.text().catch(() => "");
|
|
3509
|
+
let data2 = raw2;
|
|
3510
|
+
try {
|
|
3511
|
+
data2 = JSON.parse(raw2);
|
|
3512
|
+
} catch {
|
|
3513
|
+
}
|
|
3514
|
+
throw new Error(`local provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`);
|
|
3515
|
+
}
|
|
3516
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
3517
|
+
const shouldStream = Boolean(args2.stream && args2.onTextDelta) && contentType.includes("text/event-stream");
|
|
3518
|
+
if (shouldStream && args2.onTextDelta) {
|
|
3519
|
+
const streamed = await readOpenAiCompatibleSseCompletion({
|
|
3520
|
+
response: res,
|
|
3521
|
+
onTextDelta: args2.onTextDelta
|
|
3522
|
+
});
|
|
3523
|
+
return {
|
|
3524
|
+
content: streamed.content,
|
|
3525
|
+
model: args2.providerConfig.model,
|
|
3526
|
+
provider: args2.providerConfig.provider,
|
|
3527
|
+
...streamed.tool_calls ? { tool_calls: streamed.tool_calls } : {},
|
|
3528
|
+
...streamed.reasoning_content ? { reasoning_content: streamed.reasoning_content } : {},
|
|
3529
|
+
...streamed.usage ? { usage: streamed.usage } : {},
|
|
3530
|
+
trace: args2.messages
|
|
3531
|
+
};
|
|
3532
|
+
}
|
|
3533
|
+
const raw = await res.text().catch(() => "");
|
|
3534
|
+
let data = {};
|
|
3535
|
+
try {
|
|
3536
|
+
data = raw ? JSON.parse(raw) : {};
|
|
3537
|
+
} catch {
|
|
3538
|
+
data = {};
|
|
3539
|
+
}
|
|
3540
|
+
return parseOpenAiCompatibleChatCompletionResponse({
|
|
3541
|
+
providerConfig: args2.providerConfig,
|
|
3542
|
+
data,
|
|
3543
|
+
trace: args2.messages
|
|
3544
|
+
});
|
|
3545
|
+
}
|
|
3394
3546
|
var init_openAiCompatibleProvider = __esm({
|
|
3395
3547
|
"packages/agent-runtime/openAiCompatibleProvider.ts"() {
|
|
3396
3548
|
"use strict";
|
|
@@ -3688,7 +3840,8 @@ function buildPlatformChatCompletionRequest(args2) {
|
|
|
3688
3840
|
const body = {
|
|
3689
3841
|
model: args2.providerConfig.model,
|
|
3690
3842
|
...usesResponsesApi ? { input: convertMessagesToResponsesInput(args2.messages) } : { messages: toOpenAiCompatibleMessages2(args2.messages) },
|
|
3691
|
-
stream: false,
|
|
3843
|
+
stream: args2.stream ?? false,
|
|
3844
|
+
...args2.stream ? { stream_options: { include_usage: true } } : {},
|
|
3692
3845
|
...requestOptions,
|
|
3693
3846
|
...args2.tools && args2.tools.length > 0 ? {
|
|
3694
3847
|
tools: usesResponsesApi ? toResponsesTools(args2.tools) : args2.tools,
|
|
@@ -10118,6 +10271,8 @@ var init_ai_locale = __esm({
|
|
|
10118
10271
|
creating: "Creating...",
|
|
10119
10272
|
edit: "Edit",
|
|
10120
10273
|
delete: "Delete",
|
|
10274
|
+
favorite: "Favorite",
|
|
10275
|
+
unfavorite: "Unfavorite",
|
|
10121
10276
|
confirmDelete: "Confirm Delete",
|
|
10122
10277
|
resetToDefaults: "Reset to Defaults",
|
|
10123
10278
|
loading: "Loading...",
|
|
@@ -10429,6 +10584,8 @@ var init_ai_locale = __esm({
|
|
|
10429
10584
|
creating: "\u521B\u5EFA\u4E2D...",
|
|
10430
10585
|
edit: "\u7F16\u8F91",
|
|
10431
10586
|
delete: "\u5220\u9664",
|
|
10587
|
+
favorite: "\u6536\u85CF",
|
|
10588
|
+
unfavorite: "\u53D6\u6D88\u6536\u85CF",
|
|
10432
10589
|
confirmDelete: "\u786E\u8BA4\u5220\u9664",
|
|
10433
10590
|
resetToDefaults: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u503C",
|
|
10434
10591
|
loading: "\u52A0\u8F7D\u4E2D...",
|
|
@@ -10741,6 +10898,8 @@ var init_ai_locale = __esm({
|
|
|
10741
10898
|
creating: "\u5EFA\u7ACB\u4E2D...",
|
|
10742
10899
|
edit: "\u7DE8\u8F2F",
|
|
10743
10900
|
delete: "\u522A\u9664",
|
|
10901
|
+
favorite: "\u6536\u85CF",
|
|
10902
|
+
unfavorite: "\u53D6\u6D88\u6536\u85CF",
|
|
10744
10903
|
confirmDelete: "\u78BA\u8A8D\u522A\u9664",
|
|
10745
10904
|
resetToDefaults: "\u91CD\u8A2D\u70BA\u9810\u8A2D\u503C",
|
|
10746
10905
|
loading: "\u8F09\u5165\u4E2D...",
|
|
@@ -10976,6 +11135,8 @@ var init_ai_locale = __esm({
|
|
|
10976
11135
|
creating: "\u4F5C\u6210\u4E2D...",
|
|
10977
11136
|
edit: "\u7DE8\u96C6",
|
|
10978
11137
|
delete: "\u524A\u9664",
|
|
11138
|
+
favorite: "\u304A\u6C17\u306B\u5165\u308A",
|
|
11139
|
+
unfavorite: "\u304A\u6C17\u306B\u5165\u308A\u89E3\u9664",
|
|
10979
11140
|
confirmDelete: "\u524A\u9664\u306E\u78BA\u8A8D",
|
|
10980
11141
|
resetToDefaults: "\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u30EA\u30BB\u30C3\u30C8",
|
|
10981
11142
|
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D...",
|
|
@@ -13051,6 +13212,31 @@ var init_interface_locale = __esm({
|
|
|
13051
13212
|
stop: "Stop",
|
|
13052
13213
|
refresh: "Refresh"
|
|
13053
13214
|
},
|
|
13215
|
+
productivity: {
|
|
13216
|
+
title: "Productivity",
|
|
13217
|
+
default_space: {
|
|
13218
|
+
title: "Default startup space",
|
|
13219
|
+
description: "Choose the workspace you land in after signing in to get into flow faster.",
|
|
13220
|
+
all: "All (no fixed default space)"
|
|
13221
|
+
},
|
|
13222
|
+
shortcuts: {
|
|
13223
|
+
title: "Keyboard shortcuts",
|
|
13224
|
+
description: "View and customize shortcuts for common actions to keep your workflow smooth.",
|
|
13225
|
+
sendMessage: "Send message",
|
|
13226
|
+
newChat: "New chat",
|
|
13227
|
+
deleteDialog: "Delete current conversation",
|
|
13228
|
+
clickToRecord: "Click to change shortcut",
|
|
13229
|
+
updated: "Shortcut updated",
|
|
13230
|
+
pressKeys: "Press shortcut keys...",
|
|
13231
|
+
none: "Disabled",
|
|
13232
|
+
cleared: "Shortcut disabled",
|
|
13233
|
+
clearError: "Failed to disable shortcut",
|
|
13234
|
+
clear: "Disable shortcut",
|
|
13235
|
+
resetSuccess: "Shortcut reset",
|
|
13236
|
+
resetError: "Failed to reset shortcut",
|
|
13237
|
+
reset: "Reset to default"
|
|
13238
|
+
}
|
|
13239
|
+
},
|
|
13054
13240
|
appearance: {
|
|
13055
13241
|
title: "Appearance",
|
|
13056
13242
|
theme: {
|
|
@@ -13744,6 +13930,31 @@ var init_interface_locale = __esm({
|
|
|
13744
13930
|
productivity: "\u6548\u7387",
|
|
13745
13931
|
secrets: "\u5BC6\u94A5"
|
|
13746
13932
|
},
|
|
13933
|
+
productivity: {
|
|
13934
|
+
title: "\u6548\u7387\u8BBE\u7F6E",
|
|
13935
|
+
default_space: {
|
|
13936
|
+
title: "\u9ED8\u8BA4\u542F\u52A8\u7A7A\u95F4",
|
|
13937
|
+
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",
|
|
13938
|
+
all: "\u5168\u90E8\uFF08\u4E0D\u56FA\u5B9A\u9ED8\u8BA4\u7A7A\u95F4\uFF09"
|
|
13939
|
+
},
|
|
13940
|
+
shortcuts: {
|
|
13941
|
+
title: "\u952E\u76D8\u5FEB\u6377\u952E",
|
|
13942
|
+
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",
|
|
13943
|
+
sendMessage: "\u53D1\u9001\u6D88\u606F",
|
|
13944
|
+
newChat: "\u65B0\u5EFA\u5BF9\u8BDD",
|
|
13945
|
+
deleteDialog: "\u5220\u9664\u5F53\u524D\u4F1A\u8BDD",
|
|
13946
|
+
clickToRecord: "\u70B9\u51FB\u4FEE\u6539\u5FEB\u6377\u952E",
|
|
13947
|
+
updated: "\u5FEB\u6377\u952E\u5DF2\u66F4\u65B0",
|
|
13948
|
+
pressKeys: "\u6309\u4E0B\u5FEB\u6377\u952E...",
|
|
13949
|
+
none: "\u5DF2\u7981\u7528",
|
|
13950
|
+
cleared: "\u5FEB\u6377\u952E\u5DF2\u7981\u7528",
|
|
13951
|
+
clearError: "\u7981\u7528\u5931\u8D25",
|
|
13952
|
+
clear: "\u7981\u7528\u5FEB\u6377\u952E",
|
|
13953
|
+
resetSuccess: "\u5FEB\u6377\u952E\u5DF2\u91CD\u7F6E",
|
|
13954
|
+
resetError: "\u91CD\u7F6E\u5931\u8D25",
|
|
13955
|
+
reset: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4"
|
|
13956
|
+
}
|
|
13957
|
+
},
|
|
13747
13958
|
appearance: {
|
|
13748
13959
|
title: "\u5916\u89C2",
|
|
13749
13960
|
theme: {
|
|
@@ -14438,6 +14649,31 @@ var init_interface_locale = __esm({
|
|
|
14438
14649
|
productivity: "\u6548\u7387",
|
|
14439
14650
|
secrets: "\u5BC6\u9470"
|
|
14440
14651
|
},
|
|
14652
|
+
productivity: {
|
|
14653
|
+
title: "\u6548\u7387\u8A2D\u5B9A",
|
|
14654
|
+
default_space: {
|
|
14655
|
+
title: "\u9810\u8A2D\u555F\u52D5\u7A7A\u9593",
|
|
14656
|
+
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",
|
|
14657
|
+
all: "\u5168\u90E8\uFF08\u4E0D\u56FA\u5B9A\u9810\u8A2D\u7A7A\u9593\uFF09"
|
|
14658
|
+
},
|
|
14659
|
+
shortcuts: {
|
|
14660
|
+
title: "\u9375\u76E4\u5FEB\u6377\u9375",
|
|
14661
|
+
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",
|
|
14662
|
+
sendMessage: "\u50B3\u9001\u8A0A\u606F",
|
|
14663
|
+
newChat: "\u65B0\u5EFA\u5C0D\u8A71",
|
|
14664
|
+
deleteDialog: "\u522A\u9664\u76EE\u524D\u6703\u8A71",
|
|
14665
|
+
clickToRecord: "\u9EDE\u64CA\u4FEE\u6539\u5FEB\u6377\u9375",
|
|
14666
|
+
updated: "\u5FEB\u6377\u9375\u5DF2\u66F4\u65B0",
|
|
14667
|
+
pressKeys: "\u6309\u4E0B\u5FEB\u6377\u9375...",
|
|
14668
|
+
none: "\u5DF2\u505C\u7528",
|
|
14669
|
+
cleared: "\u5FEB\u6377\u9375\u5DF2\u505C\u7528",
|
|
14670
|
+
clearError: "\u505C\u7528\u5931\u6557",
|
|
14671
|
+
clear: "\u505C\u7528\u5FEB\u6377\u9375",
|
|
14672
|
+
resetSuccess: "\u5FEB\u6377\u9375\u5DF2\u91CD\u8A2D",
|
|
14673
|
+
resetError: "\u91CD\u8A2D\u5931\u6557",
|
|
14674
|
+
reset: "\u91CD\u8A2D\u70BA\u9810\u8A2D"
|
|
14675
|
+
}
|
|
14676
|
+
},
|
|
14441
14677
|
appearance: {
|
|
14442
14678
|
title: "\u5916\u89C0",
|
|
14443
14679
|
theme: {
|
|
@@ -15130,6 +15366,31 @@ var init_interface_locale = __esm({
|
|
|
15130
15366
|
productivity: "\u52B9\u7387",
|
|
15131
15367
|
secrets: "\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8"
|
|
15132
15368
|
},
|
|
15369
|
+
productivity: {
|
|
15370
|
+
title: "\u52B9\u7387\u8A2D\u5B9A",
|
|
15371
|
+
default_space: {
|
|
15372
|
+
title: "\u65E2\u5B9A\u306E\u8D77\u52D5\u30B9\u30DA\u30FC\u30B9",
|
|
15373
|
+
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",
|
|
15374
|
+
all: "\u3059\u3079\u3066\uFF08\u65E2\u5B9A\u30B9\u30DA\u30FC\u30B9\u3092\u56FA\u5B9A\u3057\u306A\u3044\uFF09"
|
|
15375
|
+
},
|
|
15376
|
+
shortcuts: {
|
|
15377
|
+
title: "\u30AD\u30FC\u30DC\u30FC\u30C9\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8",
|
|
15378
|
+
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",
|
|
15379
|
+
sendMessage: "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u9001\u4FE1",
|
|
15380
|
+
newChat: "\u65B0\u3057\u3044\u30C1\u30E3\u30C3\u30C8",
|
|
15381
|
+
deleteDialog: "\u73FE\u5728\u306E\u4F1A\u8A71\u3092\u524A\u9664",
|
|
15382
|
+
clickToRecord: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u5909\u66F4",
|
|
15383
|
+
updated: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u66F4\u65B0\u3057\u307E\u3057\u305F",
|
|
15384
|
+
pressKeys: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30AD\u30FC\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044...",
|
|
15385
|
+
none: "\u7121\u52B9",
|
|
15386
|
+
cleared: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u7121\u52B9\u306B\u3057\u307E\u3057\u305F",
|
|
15387
|
+
clearError: "\u7121\u52B9\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
15388
|
+
clear: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u7121\u52B9\u5316",
|
|
15389
|
+
resetSuccess: "\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3057\u305F",
|
|
15390
|
+
resetError: "\u30EA\u30BB\u30C3\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
|
|
15391
|
+
reset: "\u65E2\u5B9A\u306B\u623B\u3059"
|
|
15392
|
+
}
|
|
15393
|
+
},
|
|
15133
15394
|
appearance: {
|
|
15134
15395
|
title: "\u5916\u89B3",
|
|
15135
15396
|
theme: {
|
|
@@ -20768,6 +21029,7 @@ __export(settingSlice_exports, {
|
|
|
20768
21029
|
selectDefaultAgentId: () => selectDefaultAgentId,
|
|
20769
21030
|
selectDefaultAgentPreference: () => selectDefaultAgentPreference,
|
|
20770
21031
|
selectDefaultSpaceId: () => selectDefaultSpaceId,
|
|
21032
|
+
selectDeleteShortcut: () => selectDeleteShortcut,
|
|
20771
21033
|
selectDensity: () => selectDensity,
|
|
20772
21034
|
selectDesktopChromeConnectorEnabled: () => selectDesktopChromeConnectorEnabled,
|
|
20773
21035
|
selectEditorAutoSave: () => selectEditorAutoSave,
|
|
@@ -20836,7 +21098,7 @@ import {
|
|
|
20836
21098
|
asyncThunkCreator,
|
|
20837
21099
|
createSelector as createSelector2
|
|
20838
21100
|
} 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;
|
|
21101
|
+
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
21102
|
var init_settingSlice = __esm({
|
|
20841
21103
|
"packages/app/settings/settingSlice.tsx"() {
|
|
20842
21104
|
"use strict";
|
|
@@ -20909,7 +21171,8 @@ var init_settingSlice = __esm({
|
|
|
20909
21171
|
showScrollToTopButton: false,
|
|
20910
21172
|
showScrollToBottomButton: false,
|
|
20911
21173
|
createMenuOpenCount: 0,
|
|
20912
|
-
desktopChromeConnectorEnabled: false
|
|
21174
|
+
desktopChromeConnectorEnabled: false,
|
|
21175
|
+
deleteShortcut: typeof window !== "undefined" && typeof window.navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(window.navigator.platform) ? "meta+backspace" : "ctrl+backspace"
|
|
20913
21176
|
};
|
|
20914
21177
|
createSliceWithThunks = buildCreateSlice({
|
|
20915
21178
|
creators: { asyncThunk: asyncThunkCreator }
|
|
@@ -21537,6 +21800,7 @@ var init_settingSlice = __esm({
|
|
|
21537
21800
|
);
|
|
21538
21801
|
selectEditorWordCountEnabled = (state) => state.settings.editorWordCountEnabled;
|
|
21539
21802
|
selectEditorShortcuts = (state) => state.settings.editorShortcuts;
|
|
21803
|
+
selectDeleteShortcut = (state) => state.settings.deleteShortcut;
|
|
21540
21804
|
selectEditorFontSize = (state) => state.settings.editorFontSize;
|
|
21541
21805
|
selectEditorAutoSave = (state) => state.settings.editorAutoSave;
|
|
21542
21806
|
selectEditorAutoSaveInterval = (state) => state.settings.editorAutoSaveInterval;
|
|
@@ -63690,14 +63954,6 @@ function summarizeEndpoint(value) {
|
|
|
63690
63954
|
return "invalid-url";
|
|
63691
63955
|
}
|
|
63692
63956
|
}
|
|
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
63957
|
function isCliProviderAgent(agentConfig) {
|
|
63702
63958
|
return Boolean(
|
|
63703
63959
|
agentConfig.apiSource === "cli" || agentConfig.provider === "cli" || agentConfig.cliProvider
|
|
@@ -64463,12 +64719,15 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64463
64719
|
toolNames: requestedToolNames,
|
|
64464
64720
|
env: deps.env
|
|
64465
64721
|
});
|
|
64722
|
+
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64723
|
+
const usesResponsesApi = providerConfig2.endpoint.includes("/responses");
|
|
64724
|
+
const stream = Boolean(options?.onTextDelta) && !usesResponsesApi;
|
|
64466
64725
|
const request = buildPlatformChatCompletionRequest({
|
|
64467
64726
|
providerConfig: providerConfig2,
|
|
64468
64727
|
messages,
|
|
64469
|
-
tools
|
|
64728
|
+
tools,
|
|
64729
|
+
stream
|
|
64470
64730
|
});
|
|
64471
|
-
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64472
64731
|
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
64473
64732
|
agentKey: agentConfig.key,
|
|
64474
64733
|
transport: "platform-proxy",
|
|
@@ -64479,32 +64738,62 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64479
64738
|
toolCount: tools.length,
|
|
64480
64739
|
requestedToolNames,
|
|
64481
64740
|
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
64482
|
-
timeoutMs: options?.timeoutMs ?? null
|
|
64483
|
-
|
|
64484
|
-
const res = await fetchWithTransientRetry(fetchImpl, request.url, {
|
|
64485
|
-
...request.init,
|
|
64486
|
-
...timeoutSignal ? { signal: timeoutSignal.signal } : {}
|
|
64487
|
-
}, {
|
|
64488
|
-
sleep: deps.sleep,
|
|
64489
|
-
loopbackRequest
|
|
64490
|
-
}).finally(() => timeoutSignal?.clear());
|
|
64491
|
-
const raw = await res.text().catch(() => "");
|
|
64492
|
-
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64493
|
-
agentKey: agentConfig.key,
|
|
64494
|
-
transport: "platform-proxy",
|
|
64495
|
-
status: res.status,
|
|
64496
|
-
ok: res.ok,
|
|
64497
|
-
responseBytes: raw.length
|
|
64741
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
64742
|
+
stream
|
|
64498
64743
|
});
|
|
64499
|
-
|
|
64500
|
-
|
|
64501
|
-
|
|
64744
|
+
try {
|
|
64745
|
+
const res = await fetchWithTransientRetry(fetchImpl, request.url, {
|
|
64746
|
+
...request.init,
|
|
64747
|
+
...timeoutSignal ? { signal: timeoutSignal.signal } : {}
|
|
64748
|
+
}, {
|
|
64749
|
+
sleep: deps.sleep,
|
|
64750
|
+
loopbackRequest
|
|
64751
|
+
});
|
|
64752
|
+
if (!res.ok) {
|
|
64753
|
+
const raw2 = await res.text().catch(() => "");
|
|
64754
|
+
const data2 = parsePlatformChatCompletionData(raw2);
|
|
64755
|
+
throw new Error(`platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}`);
|
|
64756
|
+
}
|
|
64757
|
+
if (stream && options?.onTextDelta) {
|
|
64758
|
+
const streamed = await readOpenAiCompatibleSseCompletion({
|
|
64759
|
+
response: res,
|
|
64760
|
+
onTextDelta: options.onTextDelta
|
|
64761
|
+
});
|
|
64762
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64763
|
+
agentKey: agentConfig.key,
|
|
64764
|
+
transport: "platform-proxy",
|
|
64765
|
+
ok: true,
|
|
64766
|
+
stream: true,
|
|
64767
|
+
contentChars: streamed.content.length,
|
|
64768
|
+
toolCallCount: streamed.tool_calls?.length ?? 0
|
|
64769
|
+
});
|
|
64770
|
+
return {
|
|
64771
|
+
content: streamed.content,
|
|
64772
|
+
model: providerConfig2.model,
|
|
64773
|
+
provider: providerConfig2.provider,
|
|
64774
|
+
...streamed.tool_calls ? { tool_calls: streamed.tool_calls } : {},
|
|
64775
|
+
...streamed.reasoning_content ? { reasoning_content: streamed.reasoning_content } : {},
|
|
64776
|
+
...streamed.usage ? { usage: streamed.usage } : {},
|
|
64777
|
+
trace: messages
|
|
64778
|
+
};
|
|
64779
|
+
}
|
|
64780
|
+
const raw = await res.text().catch(() => "");
|
|
64781
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64782
|
+
agentKey: agentConfig.key,
|
|
64783
|
+
transport: "platform-proxy",
|
|
64784
|
+
status: res.status,
|
|
64785
|
+
ok: res.ok,
|
|
64786
|
+
responseBytes: raw.length
|
|
64787
|
+
});
|
|
64788
|
+
const data = parsePlatformChatCompletionData(raw);
|
|
64789
|
+
return parsePlatformChatCompletionResponse({
|
|
64790
|
+
providerConfig: providerConfig2,
|
|
64791
|
+
data,
|
|
64792
|
+
trace: messages
|
|
64793
|
+
});
|
|
64794
|
+
} finally {
|
|
64795
|
+
timeoutSignal?.clear();
|
|
64502
64796
|
}
|
|
64503
|
-
return parsePlatformChatCompletionResponse({
|
|
64504
|
-
providerConfig: providerConfig2,
|
|
64505
|
-
data,
|
|
64506
|
-
trace: messages
|
|
64507
|
-
});
|
|
64508
64797
|
}
|
|
64509
64798
|
};
|
|
64510
64799
|
}
|
|
@@ -64536,47 +64825,45 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64536
64825
|
toolNames: requestedToolNames,
|
|
64537
64826
|
env: deps.env
|
|
64538
64827
|
});
|
|
64539
|
-
const request = buildOpenAiCompatibleChatCompletionRequest({
|
|
64540
|
-
providerConfig,
|
|
64541
|
-
messages,
|
|
64542
|
-
tools
|
|
64543
|
-
});
|
|
64544
64828
|
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64829
|
+
const stream = Boolean(options?.onTextDelta);
|
|
64545
64830
|
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
64546
64831
|
agentKey: agentConfig.key,
|
|
64547
64832
|
transport: "direct-openai-compatible",
|
|
64548
|
-
requestUrl: summarizeEndpoint(
|
|
64833
|
+
requestUrl: summarizeEndpoint(providerConfig.endpoint) ?? null,
|
|
64549
64834
|
model: providerConfig.model,
|
|
64550
64835
|
messageCount: messages.length,
|
|
64551
64836
|
toolCount: tools.length,
|
|
64552
64837
|
requestedToolNames,
|
|
64553
64838
|
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
64554
|
-
timeoutMs: options?.timeoutMs ?? null
|
|
64839
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
64840
|
+
stream
|
|
64555
64841
|
});
|
|
64556
|
-
|
|
64557
|
-
|
|
64558
|
-
|
|
64559
|
-
|
|
64560
|
-
|
|
64561
|
-
|
|
64562
|
-
|
|
64563
|
-
|
|
64564
|
-
|
|
64565
|
-
|
|
64566
|
-
|
|
64567
|
-
|
|
64568
|
-
|
|
64569
|
-
|
|
64570
|
-
|
|
64571
|
-
|
|
64572
|
-
|
|
64573
|
-
|
|
64842
|
+
try {
|
|
64843
|
+
const result = await executeOpenAiCompatibleChatCompletion({
|
|
64844
|
+
providerConfig,
|
|
64845
|
+
messages,
|
|
64846
|
+
tools,
|
|
64847
|
+
fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
|
|
64848
|
+
sleep: deps.sleep,
|
|
64849
|
+
loopbackRequest
|
|
64850
|
+
}),
|
|
64851
|
+
stream,
|
|
64852
|
+
onTextDelta: options?.onTextDelta,
|
|
64853
|
+
signal: timeoutSignal?.signal
|
|
64854
|
+
});
|
|
64855
|
+
logLocalRuntimeDiagnostic("provider.request.result", {
|
|
64856
|
+
agentKey: agentConfig.key,
|
|
64857
|
+
transport: "direct-openai-compatible",
|
|
64858
|
+
ok: true,
|
|
64859
|
+
stream,
|
|
64860
|
+
contentChars: result.content.length,
|
|
64861
|
+
toolCallCount: result.tool_calls?.length ?? 0
|
|
64862
|
+
});
|
|
64863
|
+
return result;
|
|
64864
|
+
} finally {
|
|
64865
|
+
timeoutSignal?.clear();
|
|
64574
64866
|
}
|
|
64575
|
-
return parseOpenAiCompatibleChatCompletionResponse({
|
|
64576
|
-
providerConfig,
|
|
64577
|
-
data,
|
|
64578
|
-
trace: messages
|
|
64579
|
-
});
|
|
64580
64867
|
}
|
|
64581
64868
|
};
|
|
64582
64869
|
},
|
|
@@ -67743,6 +68030,412 @@ function createStreamingTextWriter({
|
|
|
67743
68030
|
};
|
|
67744
68031
|
}
|
|
67745
68032
|
|
|
68033
|
+
// packages/cli/client/assistantOutput.ts
|
|
68034
|
+
var ANSI = {
|
|
68035
|
+
reset: "\x1B[0m",
|
|
68036
|
+
bold: "\x1B[1m",
|
|
68037
|
+
dim: "\x1B[2m",
|
|
68038
|
+
cyan: "\x1B[36m"
|
|
68039
|
+
};
|
|
68040
|
+
function normalizeRenderDisplayMode(raw, fallback = "rich") {
|
|
68041
|
+
const normalized = raw?.trim().toLowerCase();
|
|
68042
|
+
if (normalized === "plain" || normalized === "raw" || normalized === "off" || normalized === "0") {
|
|
68043
|
+
return "plain";
|
|
68044
|
+
}
|
|
68045
|
+
if (normalized === "rich" || normalized === "on" || normalized === "1" || normalized === "styled") {
|
|
68046
|
+
return "rich";
|
|
68047
|
+
}
|
|
68048
|
+
return fallback;
|
|
68049
|
+
}
|
|
68050
|
+
function resolveRenderDisplayMode(env = process.env) {
|
|
68051
|
+
return normalizeRenderDisplayMode(env.NOLO_CLI_RENDER ?? env.NOLO_RENDER, "rich");
|
|
68052
|
+
}
|
|
68053
|
+
function splitTableCells(line) {
|
|
68054
|
+
const trimmed = line.trim();
|
|
68055
|
+
if (!trimmed.includes("|")) return [];
|
|
68056
|
+
const core = trimmed.replace(/^\|/, "").replace(/\|$/, "");
|
|
68057
|
+
return core.split("|").map((cell) => cell.trim()).filter(Boolean);
|
|
68058
|
+
}
|
|
68059
|
+
function isTableSeparator(line) {
|
|
68060
|
+
const cells = splitTableCells(line);
|
|
68061
|
+
return cells.length > 0 && cells.every((cell) => /^:?-{3,}:?$/.test(cell));
|
|
68062
|
+
}
|
|
68063
|
+
function isTableRow(line) {
|
|
68064
|
+
const cells = splitTableCells(line);
|
|
68065
|
+
return cells.length >= 2 && cells.some((cell) => cell.length > 0);
|
|
68066
|
+
}
|
|
68067
|
+
function convertMarkdownTablesForTerminal(text) {
|
|
68068
|
+
const lines = text.split("\n");
|
|
68069
|
+
const out = [];
|
|
68070
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
68071
|
+
const line = lines[index] ?? "";
|
|
68072
|
+
const next = lines[index + 1] ?? "";
|
|
68073
|
+
if (isTableRow(line) && isTableSeparator(next)) {
|
|
68074
|
+
const headers = splitTableCells(line);
|
|
68075
|
+
index += 1;
|
|
68076
|
+
while (index + 1 < lines.length && isTableRow(lines[index + 1] ?? "") && !isTableSeparator(lines[index + 1] ?? "")) {
|
|
68077
|
+
index += 1;
|
|
68078
|
+
const row = splitTableCells(lines[index] ?? "");
|
|
68079
|
+
const label = row[0] ?? "";
|
|
68080
|
+
const detail = row.slice(1).join(" \u2014 ").trim();
|
|
68081
|
+
out.push(detail ? ` \u2022 ${label} \u2014 ${detail}` : ` \u2022 ${label}`);
|
|
68082
|
+
}
|
|
68083
|
+
if (out.length > 0 && out[out.length - 1] !== "") out.push("");
|
|
68084
|
+
continue;
|
|
68085
|
+
}
|
|
68086
|
+
out.push(line);
|
|
68087
|
+
}
|
|
68088
|
+
return out.join("\n");
|
|
68089
|
+
}
|
|
68090
|
+
function polishAssistantStructure(text) {
|
|
68091
|
+
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();
|
|
68092
|
+
}
|
|
68093
|
+
function styleInlineMarkdown(line, mode) {
|
|
68094
|
+
if (mode === "plain") return line;
|
|
68095
|
+
return line.replace(/\*\*(.+?)\*\*/g, `${ANSI.bold}$1${ANSI.reset}`);
|
|
68096
|
+
}
|
|
68097
|
+
function styleRichMarkdownLine(line) {
|
|
68098
|
+
const heading = line.match(/^(#{1,3})\s+(.+)$/);
|
|
68099
|
+
if (heading) {
|
|
68100
|
+
const level = heading[1].length;
|
|
68101
|
+
const title = heading[2];
|
|
68102
|
+
if (level <= 2) return `${ANSI.bold}${title}${ANSI.reset}`;
|
|
68103
|
+
return `${ANSI.cyan}${title}${ANSI.reset}`;
|
|
68104
|
+
}
|
|
68105
|
+
if (/^---+$/.test(line.trim())) {
|
|
68106
|
+
return `${ANSI.dim}${line}${ANSI.reset}`;
|
|
68107
|
+
}
|
|
68108
|
+
return styleInlineMarkdown(line, "rich");
|
|
68109
|
+
}
|
|
68110
|
+
function formatAssistantDisplay(text, mode = "rich") {
|
|
68111
|
+
const polished = polishAssistantStructure(text);
|
|
68112
|
+
if (mode === "plain") {
|
|
68113
|
+
return polished.split("\n").map((line) => styleInlineMarkdown(line, "plain")).join("\n");
|
|
68114
|
+
}
|
|
68115
|
+
return polished.split("\n").map((line) => styleRichMarkdownLine(line)).join("\n");
|
|
68116
|
+
}
|
|
68117
|
+
|
|
68118
|
+
// packages/cli/client/thinkingOutput.ts
|
|
68119
|
+
var THINK_OPEN = /<think>/i;
|
|
68120
|
+
var THINK_CLOSE = /<\/think>/i;
|
|
68121
|
+
var COLLAPSED_MARKER = /^\s*▸ 思考已折叠\s*$/;
|
|
68122
|
+
function normalizeThinkingDisplayMode(raw, fallback = "hide") {
|
|
68123
|
+
const normalized = raw?.trim().toLowerCase();
|
|
68124
|
+
if (normalized === "hide" || normalized === "off" || normalized === "false" || normalized === "0") {
|
|
68125
|
+
return "hide";
|
|
68126
|
+
}
|
|
68127
|
+
if (normalized === "marker" || normalized === "collapsed" || normalized === "fold") {
|
|
68128
|
+
return "marker";
|
|
68129
|
+
}
|
|
68130
|
+
if (normalized === "show" || normalized === "on" || normalized === "true" || normalized === "1") {
|
|
68131
|
+
return "show";
|
|
68132
|
+
}
|
|
68133
|
+
return fallback;
|
|
68134
|
+
}
|
|
68135
|
+
function resolveThinkingDisplayMode(env = process.env) {
|
|
68136
|
+
return normalizeThinkingDisplayMode(env.NOLO_CLI_THINKING ?? env.NOLO_THINKING, "hide");
|
|
68137
|
+
}
|
|
68138
|
+
function collapseThinkingBlocks(text, mode = "hide") {
|
|
68139
|
+
if (mode === "show") return text;
|
|
68140
|
+
const replacement = mode === "marker" ? "\u25B8 \u601D\u8003\u5DF2\u6298\u53E0\n" : "";
|
|
68141
|
+
return text.replace(/<think>[\s\S]*?<\/think>\s*/gi, replacement).replace(/\n{3,}/g, "\n\n").trim();
|
|
68142
|
+
}
|
|
68143
|
+
function stripCollapsedThinkingMarkers(text) {
|
|
68144
|
+
return text.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n").replace(/\n{2,}/g, "\n").trim();
|
|
68145
|
+
}
|
|
68146
|
+
function formatAssistantTextForCli(text, mode = "hide") {
|
|
68147
|
+
const collapsed = collapseThinkingBlocks(text, mode);
|
|
68148
|
+
return mode === "hide" ? stripCollapsedThinkingMarkers(collapsed) : collapsed;
|
|
68149
|
+
}
|
|
68150
|
+
function createThinkingAwareStreamFilter(write2, mode = "hide") {
|
|
68151
|
+
if (mode === "show") {
|
|
68152
|
+
return {
|
|
68153
|
+
push(chunk) {
|
|
68154
|
+
write2(chunk);
|
|
68155
|
+
},
|
|
68156
|
+
flush() {
|
|
68157
|
+
}
|
|
68158
|
+
};
|
|
68159
|
+
}
|
|
68160
|
+
let pending = "";
|
|
68161
|
+
let insideThink = false;
|
|
68162
|
+
let markerEmitted = false;
|
|
68163
|
+
const emit = (chunk) => {
|
|
68164
|
+
if (chunk) write2(chunk);
|
|
68165
|
+
};
|
|
68166
|
+
const emitMarker = () => {
|
|
68167
|
+
if (mode !== "marker" || markerEmitted) return;
|
|
68168
|
+
emit("\n\u25B8 \u601D\u8003\u5DF2\u6298\u53E0\n");
|
|
68169
|
+
markerEmitted = true;
|
|
68170
|
+
};
|
|
68171
|
+
const consume = (input2) => {
|
|
68172
|
+
pending += input2;
|
|
68173
|
+
while (pending.length > 0) {
|
|
68174
|
+
if (insideThink) {
|
|
68175
|
+
const closeMatch = pending.match(THINK_CLOSE);
|
|
68176
|
+
if (!closeMatch || closeMatch.index == null) {
|
|
68177
|
+
emitMarker();
|
|
68178
|
+
pending = "";
|
|
68179
|
+
return;
|
|
68180
|
+
}
|
|
68181
|
+
emitMarker();
|
|
68182
|
+
pending = pending.slice(closeMatch.index + closeMatch[0].length);
|
|
68183
|
+
insideThink = false;
|
|
68184
|
+
markerEmitted = false;
|
|
68185
|
+
continue;
|
|
68186
|
+
}
|
|
68187
|
+
const openMatch = pending.match(THINK_OPEN);
|
|
68188
|
+
if (!openMatch || openMatch.index == null) {
|
|
68189
|
+
const nextMarker = pending.indexOf("<");
|
|
68190
|
+
if (nextMarker === -1) {
|
|
68191
|
+
const cleaned = mode === "hide" ? pending.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : pending;
|
|
68192
|
+
emit(cleaned);
|
|
68193
|
+
pending = "";
|
|
68194
|
+
return;
|
|
68195
|
+
}
|
|
68196
|
+
if (nextMarker > 0) {
|
|
68197
|
+
const head = pending.slice(0, nextMarker);
|
|
68198
|
+
const cleaned = mode === "hide" ? head.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : head;
|
|
68199
|
+
emit(cleaned);
|
|
68200
|
+
pending = pending.slice(nextMarker);
|
|
68201
|
+
continue;
|
|
68202
|
+
}
|
|
68203
|
+
if (pending.length < 7) return;
|
|
68204
|
+
emit(pending[0]);
|
|
68205
|
+
pending = pending.slice(1);
|
|
68206
|
+
continue;
|
|
68207
|
+
}
|
|
68208
|
+
if (openMatch.index > 0) {
|
|
68209
|
+
const head = pending.slice(0, openMatch.index);
|
|
68210
|
+
const cleaned = mode === "hide" ? head.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : head;
|
|
68211
|
+
emit(cleaned);
|
|
68212
|
+
pending = pending.slice(openMatch.index);
|
|
68213
|
+
continue;
|
|
68214
|
+
}
|
|
68215
|
+
pending = pending.slice(openMatch[0].length);
|
|
68216
|
+
insideThink = true;
|
|
68217
|
+
markerEmitted = false;
|
|
68218
|
+
}
|
|
68219
|
+
};
|
|
68220
|
+
return {
|
|
68221
|
+
push(chunk) {
|
|
68222
|
+
consume(chunk);
|
|
68223
|
+
},
|
|
68224
|
+
flush() {
|
|
68225
|
+
if (insideThink) emitMarker();
|
|
68226
|
+
if (pending) {
|
|
68227
|
+
const cleaned = mode === "hide" ? pending.split("\n").filter((line) => !COLLAPSED_MARKER.test(line)).join("\n") : pending;
|
|
68228
|
+
emit(cleaned);
|
|
68229
|
+
}
|
|
68230
|
+
pending = "";
|
|
68231
|
+
insideThink = false;
|
|
68232
|
+
markerEmitted = false;
|
|
68233
|
+
}
|
|
68234
|
+
};
|
|
68235
|
+
}
|
|
68236
|
+
|
|
68237
|
+
// packages/cli/client/tokenUsage.ts
|
|
68238
|
+
init_providers();
|
|
68239
|
+
var PROVIDER_LOOKUP_ORDER = [
|
|
68240
|
+
"openrouter",
|
|
68241
|
+
"fireworks",
|
|
68242
|
+
"openai",
|
|
68243
|
+
"mimo",
|
|
68244
|
+
"gmi",
|
|
68245
|
+
"google",
|
|
68246
|
+
"deepseek",
|
|
68247
|
+
"mistral",
|
|
68248
|
+
"vultr",
|
|
68249
|
+
"deepinfra",
|
|
68250
|
+
"cloudflare"
|
|
68251
|
+
];
|
|
68252
|
+
function parseUsageRecord(usage2) {
|
|
68253
|
+
if (!usage2 || typeof usage2 !== "object") return void 0;
|
|
68254
|
+
const input2 = Number(usage2.input_tokens ?? usage2.prompt_tokens ?? 0);
|
|
68255
|
+
const output2 = Number(usage2.output_tokens ?? usage2.completion_tokens ?? 0);
|
|
68256
|
+
if (!Number.isFinite(input2) || !Number.isFinite(output2)) return void 0;
|
|
68257
|
+
if (!input2 && !output2) return void 0;
|
|
68258
|
+
return { input: input2, output: output2 };
|
|
68259
|
+
}
|
|
68260
|
+
function fuzzyContextWindow(model) {
|
|
68261
|
+
const lower = model.toLowerCase();
|
|
68262
|
+
if (lower.includes("minimax-m3") || lower.includes("minimax_m3")) return 1e6;
|
|
68263
|
+
if (lower.includes("minimax-m2")) return 262144;
|
|
68264
|
+
if (lower.includes("gpt-5") || lower.includes("gpt-4.1")) return 1047576;
|
|
68265
|
+
if (lower.includes("claude")) return 2e5;
|
|
68266
|
+
return void 0;
|
|
68267
|
+
}
|
|
68268
|
+
function resolveContextWindow(model) {
|
|
68269
|
+
const raw = model?.trim();
|
|
68270
|
+
if (!raw) return void 0;
|
|
68271
|
+
for (const provider of PROVIDER_LOOKUP_ORDER) {
|
|
68272
|
+
const config = findModelConfig(provider, raw);
|
|
68273
|
+
if (config?.contextWindow) return config.contextWindow;
|
|
68274
|
+
}
|
|
68275
|
+
return fuzzyContextWindow(raw);
|
|
68276
|
+
}
|
|
68277
|
+
function buildTurnTokenUsage(usage2, model) {
|
|
68278
|
+
const parsed = parseUsageRecord(usage2);
|
|
68279
|
+
if (!parsed) return void 0;
|
|
68280
|
+
const contextWindow = resolveContextWindow(model);
|
|
68281
|
+
const remaining = contextWindow && parsed.input > 0 ? Math.max(0, contextWindow - parsed.input) : void 0;
|
|
68282
|
+
return {
|
|
68283
|
+
...parsed,
|
|
68284
|
+
...contextWindow ? { contextWindow } : {},
|
|
68285
|
+
...remaining != null ? { remaining } : {}
|
|
68286
|
+
};
|
|
68287
|
+
}
|
|
68288
|
+
function formatTokenCount(value) {
|
|
68289
|
+
if (!Number.isFinite(value) || value < 0) return "\u2014";
|
|
68290
|
+
if (value < 1e3) return String(Math.round(value));
|
|
68291
|
+
if (value < 1e6) {
|
|
68292
|
+
const compact3 = value / 1e3;
|
|
68293
|
+
if (Number.isInteger(compact3)) return `${compact3}k`;
|
|
68294
|
+
return `${compact3.toFixed(1).replace(/\.0$/, "")}k`;
|
|
68295
|
+
}
|
|
68296
|
+
const compact2 = value / 1e6;
|
|
68297
|
+
return compact2 >= 100 ? `${Math.round(compact2)}M` : `${compact2.toFixed(1).replace(/\.0$/, "")}M`;
|
|
68298
|
+
}
|
|
68299
|
+
function renderTokenStatus(tokens) {
|
|
68300
|
+
if (!tokens) return "in \u2014 out \u2014 left \u2014";
|
|
68301
|
+
const left = tokens.remaining != null ? formatTokenCount(tokens.remaining) : tokens.contextWindow ? "\u2014" : "\u2014";
|
|
68302
|
+
return `in ${formatTokenCount(tokens.input)} out ${formatTokenCount(tokens.output)} left ${left}`;
|
|
68303
|
+
}
|
|
68304
|
+
|
|
68305
|
+
// packages/cli/client/terminalStyles.ts
|
|
68306
|
+
var ANSI2 = {
|
|
68307
|
+
dim: "\x1B[2m",
|
|
68308
|
+
bold: "\x1B[1m",
|
|
68309
|
+
cyan: "\x1B[36m",
|
|
68310
|
+
green: "\x1B[32m",
|
|
68311
|
+
red: "\x1B[31m"
|
|
68312
|
+
};
|
|
68313
|
+
var RESET = "\x1B[0m";
|
|
68314
|
+
function resolveCliColorEnabled(env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
|
|
68315
|
+
const setting = (env.NOLO_CLI_COLOR ?? "").trim().toLowerCase();
|
|
68316
|
+
if (setting === "0" || setting === "false" || setting === "off") return false;
|
|
68317
|
+
if (env.NO_COLOR) return false;
|
|
68318
|
+
if (setting === "1" || setting === "true" || setting === "on") return true;
|
|
68319
|
+
return isTTY;
|
|
68320
|
+
}
|
|
68321
|
+
function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
|
|
68322
|
+
if (!enabled || !text) return text;
|
|
68323
|
+
return `${ANSI2[style]}${text}${RESET}`;
|
|
68324
|
+
}
|
|
68325
|
+
function dimCliText(text, enabled = resolveCliColorEnabled()) {
|
|
68326
|
+
return styleCliText(text, "dim", enabled);
|
|
68327
|
+
}
|
|
68328
|
+
|
|
68329
|
+
// packages/cli/client/toolOutput.ts
|
|
68330
|
+
function normalizeToolDisplayMode(raw, fallback = "compact") {
|
|
68331
|
+
const normalized = raw?.trim().toLowerCase();
|
|
68332
|
+
if (normalized === "hide" || normalized === "off" || normalized === "false" || normalized === "0") {
|
|
68333
|
+
return "hide";
|
|
68334
|
+
}
|
|
68335
|
+
if (normalized === "verbose" || normalized === "debug" || normalized === "trace" || normalized === "full") {
|
|
68336
|
+
return "verbose";
|
|
68337
|
+
}
|
|
68338
|
+
if (normalized === "compact" || normalized === "minimal" || normalized === "short") {
|
|
68339
|
+
return "compact";
|
|
68340
|
+
}
|
|
68341
|
+
return fallback;
|
|
68342
|
+
}
|
|
68343
|
+
function resolveToolDisplayMode(env = process.env) {
|
|
68344
|
+
const legacyTrace = env.NOLO_TRACE_TOOLS?.trim().toLowerCase();
|
|
68345
|
+
if (legacyTrace === "0" || legacyTrace === "false" || legacyTrace === "off") {
|
|
68346
|
+
return "hide";
|
|
68347
|
+
}
|
|
68348
|
+
if (legacyTrace === "verbose" || legacyTrace === "full") {
|
|
68349
|
+
return "verbose";
|
|
68350
|
+
}
|
|
68351
|
+
return normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact");
|
|
68352
|
+
}
|
|
68353
|
+
function shouldEmitToolEvents(mode) {
|
|
68354
|
+
return mode !== "hide";
|
|
68355
|
+
}
|
|
68356
|
+
function clip4(value, max = 72) {
|
|
68357
|
+
const compact2 = value.replace(/\s+/g, " ").trim();
|
|
68358
|
+
return compact2.length > max ? `${compact2.slice(0, max - 1)}\u2026` : compact2;
|
|
68359
|
+
}
|
|
68360
|
+
function compactResultHint(summary, toolName) {
|
|
68361
|
+
if (!summary) return "";
|
|
68362
|
+
const linesMatch = summary.match(/(\d+)\s+lines?/);
|
|
68363
|
+
if (linesMatch) {
|
|
68364
|
+
if (toolName === "readFile" || toolName === "listFiles" || toolName === "globFiles") {
|
|
68365
|
+
return `${linesMatch[1]} lines`;
|
|
68366
|
+
}
|
|
68367
|
+
if (toolName === "execShell" || toolName === "runCommand") {
|
|
68368
|
+
return `${linesMatch[1]} lines`;
|
|
68369
|
+
}
|
|
68370
|
+
}
|
|
68371
|
+
const exitMatch = summary.match(/exit=(\d+)/);
|
|
68372
|
+
if (exitMatch && exitMatch[1] !== "0") return `exit ${exitMatch[1]}`;
|
|
68373
|
+
return "";
|
|
68374
|
+
}
|
|
68375
|
+
function formatToolTraceLine(text, colorEnabled, accent = "none") {
|
|
68376
|
+
if (!colorEnabled) return `${text}
|
|
68377
|
+
`;
|
|
68378
|
+
if (accent === "error") {
|
|
68379
|
+
return `${styleCliText(text, "red", true)}
|
|
68380
|
+
`;
|
|
68381
|
+
}
|
|
68382
|
+
return `${dimCliText(text, true)}
|
|
68383
|
+
`;
|
|
68384
|
+
}
|
|
68385
|
+
function formatVerboseToolEvent(event, colorEnabled) {
|
|
68386
|
+
const round = event.round + 1;
|
|
68387
|
+
const detail = event.argumentsPreview ? ` ${event.argumentsPreview}` : "";
|
|
68388
|
+
if (event.type === "tool-call") {
|
|
68389
|
+
return formatToolTraceLine(`[nolo:tool] #${round} -> ${event.toolName}${detail}`, colorEnabled);
|
|
68390
|
+
}
|
|
68391
|
+
if (event.type === "tool-error") {
|
|
68392
|
+
const elapsed2 = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68393
|
+
return formatToolTraceLine(
|
|
68394
|
+
`[nolo:tool] #${round} !! ${event.toolName}${elapsed2}: ${event.message ?? "failed"}`,
|
|
68395
|
+
colorEnabled,
|
|
68396
|
+
"error"
|
|
68397
|
+
);
|
|
68398
|
+
}
|
|
68399
|
+
const elapsed = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68400
|
+
const summary = event.summary ? ` ${event.summary}` : "";
|
|
68401
|
+
return formatToolTraceLine(
|
|
68402
|
+
`[nolo:tool] #${round} <- ${event.toolName}${elapsed}${summary}`,
|
|
68403
|
+
colorEnabled
|
|
68404
|
+
);
|
|
68405
|
+
}
|
|
68406
|
+
function formatCompactToolLine(event, pending, colorEnabled) {
|
|
68407
|
+
const toolName = event.toolName || pending?.toolName || "tool";
|
|
68408
|
+
const args2 = clip4(event.argumentsPreview || pending?.argumentsPreview || "");
|
|
68409
|
+
const label = args2 ? `${toolName} ${args2}` : toolName;
|
|
68410
|
+
const ms = typeof event.elapsedMs === "number" ? `${event.elapsedMs}ms` : "";
|
|
68411
|
+
if (event.type === "tool-error") {
|
|
68412
|
+
const message = clip4(event.message ?? "failed", 96);
|
|
68413
|
+
const timing2 = ms ? ` \xB7 ${ms}` : "";
|
|
68414
|
+
return formatToolTraceLine(` \u25B8 ${label} \u2717 ${message}${timing2}`, colorEnabled, "error");
|
|
68415
|
+
}
|
|
68416
|
+
const hint = compactResultHint(event.summary, toolName);
|
|
68417
|
+
const timing = ms ? ` ${ms}` : "";
|
|
68418
|
+
const suffix = hint ? ` \xB7 ${hint}` : "";
|
|
68419
|
+
return formatToolTraceLine(` \u25B8 ${label} \u2713${timing}${suffix}`, colorEnabled);
|
|
68420
|
+
}
|
|
68421
|
+
function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled()) {
|
|
68422
|
+
const pending = /* @__PURE__ */ new Map();
|
|
68423
|
+
return (event) => {
|
|
68424
|
+
if (mode === "hide") return "";
|
|
68425
|
+
if (mode === "verbose") return formatVerboseToolEvent(event, colorEnabled);
|
|
68426
|
+
if (event.type === "tool-call") {
|
|
68427
|
+
pending.set(event.toolCallId, {
|
|
68428
|
+
toolName: event.toolName,
|
|
68429
|
+
argumentsPreview: event.argumentsPreview
|
|
68430
|
+
});
|
|
68431
|
+
return "";
|
|
68432
|
+
}
|
|
68433
|
+
const call = pending.get(event.toolCallId);
|
|
68434
|
+
pending.delete(event.toolCallId);
|
|
68435
|
+
return formatCompactToolLine(event, call, colorEnabled);
|
|
68436
|
+
};
|
|
68437
|
+
}
|
|
68438
|
+
|
|
67746
68439
|
// packages/cli/client/agentRun.ts
|
|
67747
68440
|
var Spinner = class {
|
|
67748
68441
|
constructor(output2, text) {
|
|
@@ -67988,10 +68681,13 @@ function buildSubjectRefs(options) {
|
|
|
67988
68681
|
}
|
|
67989
68682
|
return refs.length ? refs : void 0;
|
|
67990
68683
|
}
|
|
67991
|
-
function
|
|
67992
|
-
const
|
|
67993
|
-
|
|
67994
|
-
return
|
|
68684
|
+
function formatAssistantResponseForCli(text, options) {
|
|
68685
|
+
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
68686
|
+
const renderMode = resolveRenderDisplayMode(options.env);
|
|
68687
|
+
return formatAssistantDisplay(
|
|
68688
|
+
formatAssistantTextForCli(text, thinkingMode),
|
|
68689
|
+
renderMode
|
|
68690
|
+
);
|
|
67995
68691
|
}
|
|
67996
68692
|
function resolveAgentEventMode(options) {
|
|
67997
68693
|
if (options.eventsMode === "jsonl") return "jsonl";
|
|
@@ -68002,23 +68698,6 @@ function isMissingLocalAgentConfigError(error, agentRef) {
|
|
|
68002
68698
|
error && typeof error === "object" && "code" in error && error.code === LOCAL_AGENT_CONFIG_MISSING_CODE && error.agentRef === agentRef
|
|
68003
68699
|
);
|
|
68004
68700
|
}
|
|
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
68701
|
function formatToolJsonEvent(event) {
|
|
68023
68702
|
return `${JSON.stringify({
|
|
68024
68703
|
schemaVersion: 1,
|
|
@@ -68150,8 +68829,8 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
68150
68829
|
const contentType = res.headers.get("content-type") || "";
|
|
68151
68830
|
if (contentType.includes("text/event-stream") && res.body) {
|
|
68152
68831
|
spinner.stop();
|
|
68153
|
-
const
|
|
68154
|
-
return
|
|
68832
|
+
const result = await readStreamingAgentRun(options, res);
|
|
68833
|
+
return result;
|
|
68155
68834
|
}
|
|
68156
68835
|
spinner.stop();
|
|
68157
68836
|
let data = {};
|
|
@@ -68194,7 +68873,10 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
68194
68873
|
}
|
|
68195
68874
|
return dialogIdText ? { exitCode: 1, dialogId: dialogIdText } : { exitCode: 1 };
|
|
68196
68875
|
}
|
|
68197
|
-
const content =
|
|
68876
|
+
const content = formatAssistantResponseForCli(
|
|
68877
|
+
String(data?.content ?? data?.message ?? ""),
|
|
68878
|
+
options
|
|
68879
|
+
);
|
|
68198
68880
|
if (content) {
|
|
68199
68881
|
options.output.write(`
|
|
68200
68882
|
${options.agentName} > ${content}
|
|
@@ -68207,11 +68889,14 @@ ${options.agentName} > (no text response)
|
|
|
68207
68889
|
const usage2 = formatUsage(data?.usage, data?.dialogId);
|
|
68208
68890
|
if (usage2 && shouldShowUsage(options.env)) options.output.write(`${usage2}
|
|
68209
68891
|
`);
|
|
68210
|
-
|
|
68892
|
+
return {
|
|
68211
68893
|
exitCode: 0,
|
|
68212
|
-
...typeof data?.dialogId === "string" && data.dialogId ? { dialogId: data.dialogId } : {}
|
|
68894
|
+
...typeof data?.dialogId === "string" && data.dialogId ? { dialogId: data.dialogId } : {},
|
|
68895
|
+
turnTokens: buildTurnTokenUsage(
|
|
68896
|
+
data?.usage,
|
|
68897
|
+
typeof data?.model === "string" ? data.model : options.agentKey
|
|
68898
|
+
)
|
|
68213
68899
|
};
|
|
68214
|
-
return result;
|
|
68215
68900
|
}
|
|
68216
68901
|
async function runInjectedLocalAgentTurn(options) {
|
|
68217
68902
|
return runLocalAgentTurnForCli(options, { reportFailure: true });
|
|
@@ -68231,8 +68916,18 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68231
68916
|
const spinner = new Spinner(options.output, `${options.agentName} -> working locally`);
|
|
68232
68917
|
spinner.start();
|
|
68233
68918
|
try {
|
|
68234
|
-
const
|
|
68919
|
+
const toolDisplayMode = resolveToolDisplayMode(options.env);
|
|
68920
|
+
const traceLocalTools = shouldEmitToolEvents(toolDisplayMode);
|
|
68921
|
+
const formatToolEvent = createToolEventFormatter(toolDisplayMode);
|
|
68235
68922
|
const eventMode = resolveAgentEventMode(options);
|
|
68923
|
+
let wroteToolTrace = false;
|
|
68924
|
+
let streamedAssistantText = false;
|
|
68925
|
+
let printedAssistantLabel = false;
|
|
68926
|
+
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
68927
|
+
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
68928
|
+
(chunk) => options.output.write(chunk),
|
|
68929
|
+
thinkingMode
|
|
68930
|
+
);
|
|
68236
68931
|
const subjectRefs = buildSubjectRefs(options);
|
|
68237
68932
|
const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter((key2) => key2.trim());
|
|
68238
68933
|
const allowedToolNames = options.allowedToolNames?.filter((name) => name.trim());
|
|
@@ -68261,27 +68956,48 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68261
68956
|
...typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
|
|
68262
68957
|
...traceLocalTools ? {
|
|
68263
68958
|
onToolEvent: (event) => {
|
|
68264
|
-
|
|
68265
|
-
|
|
68266
|
-
|
|
68267
|
-
|
|
68268
|
-
);
|
|
68959
|
+
spinner.stop();
|
|
68960
|
+
const chunk = eventMode === "jsonl" ? formatToolJsonEvent(event) : formatToolEvent(event);
|
|
68961
|
+
if (chunk) {
|
|
68962
|
+
wroteToolTrace = true;
|
|
68963
|
+
options.output.write(chunk);
|
|
68269
68964
|
}
|
|
68270
68965
|
}
|
|
68966
|
+
} : {},
|
|
68967
|
+
...!options.noStream ? {
|
|
68968
|
+
onTextDelta: (chunk) => {
|
|
68969
|
+
spinner.stop();
|
|
68970
|
+
if (!printedAssistantLabel) {
|
|
68971
|
+
options.output.write(`
|
|
68972
|
+
${options.agentName} > `);
|
|
68973
|
+
printedAssistantLabel = true;
|
|
68974
|
+
}
|
|
68975
|
+
streamedAssistantText = true;
|
|
68976
|
+
thinkingFilter.push(chunk);
|
|
68977
|
+
}
|
|
68271
68978
|
} : {}
|
|
68272
68979
|
});
|
|
68273
68980
|
spinner.stop();
|
|
68274
|
-
|
|
68275
|
-
|
|
68276
|
-
options.output.write(
|
|
68981
|
+
if (streamedAssistantText) {
|
|
68982
|
+
thinkingFilter.flush();
|
|
68983
|
+
options.output.write("\n");
|
|
68984
|
+
} else {
|
|
68985
|
+
const content = formatAssistantResponseForCli(result.content.trim(), options);
|
|
68986
|
+
if (content) {
|
|
68987
|
+
options.output.write(`
|
|
68277
68988
|
${options.agentName} > ${content}
|
|
68278
68989
|
`);
|
|
68279
|
-
|
|
68280
|
-
|
|
68990
|
+
} else {
|
|
68991
|
+
options.output.write(`
|
|
68281
68992
|
${options.agentName} > (no text response)
|
|
68282
68993
|
`);
|
|
68994
|
+
}
|
|
68283
68995
|
}
|
|
68284
|
-
return {
|
|
68996
|
+
return {
|
|
68997
|
+
exitCode: 0,
|
|
68998
|
+
dialogId: result.dialogId,
|
|
68999
|
+
turnTokens: buildTurnTokenUsage(result.usage, result.model)
|
|
69000
|
+
};
|
|
68285
69001
|
} catch (error) {
|
|
68286
69002
|
spinner.stop();
|
|
68287
69003
|
if (settings.reportFailure) {
|
|
@@ -68300,9 +69016,14 @@ async function readStreamingAgentRun(options, res) {
|
|
|
68300
69016
|
return { exitCode: 1 };
|
|
68301
69017
|
}
|
|
68302
69018
|
const decoder = new TextDecoder();
|
|
69019
|
+
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
68303
69020
|
const writer = createStreamingTextWriter({
|
|
68304
69021
|
write: (chunk) => options.output.write(chunk)
|
|
68305
69022
|
});
|
|
69023
|
+
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
69024
|
+
(chunk) => writer.push(chunk),
|
|
69025
|
+
thinkingMode
|
|
69026
|
+
);
|
|
68306
69027
|
let buffer = "";
|
|
68307
69028
|
let content = "";
|
|
68308
69029
|
let dialogId;
|
|
@@ -68332,7 +69053,7 @@ ${options.agentName} > `);
|
|
|
68332
69053
|
if (!chunk) return;
|
|
68333
69054
|
printLabel();
|
|
68334
69055
|
content += chunk;
|
|
68335
|
-
|
|
69056
|
+
thinkingFilter.push(chunk);
|
|
68336
69057
|
};
|
|
68337
69058
|
try {
|
|
68338
69059
|
while (true) {
|
|
@@ -68369,6 +69090,7 @@ ${options.agentName} > `);
|
|
|
68369
69090
|
return { exitCode: 1 };
|
|
68370
69091
|
} finally {
|
|
68371
69092
|
writer.flushAll();
|
|
69093
|
+
thinkingFilter.flush();
|
|
68372
69094
|
}
|
|
68373
69095
|
if (!content) {
|
|
68374
69096
|
options.output.write(`
|
|
@@ -68382,7 +69104,8 @@ ${options.agentName} > (no text response)
|
|
|
68382
69104
|
`);
|
|
68383
69105
|
return {
|
|
68384
69106
|
exitCode: 0,
|
|
68385
|
-
...dialogId ? { dialogId } : {}
|
|
69107
|
+
...dialogId ? { dialogId } : {},
|
|
69108
|
+
turnTokens: buildTurnTokenUsage(usage2, options.agentKey)
|
|
68386
69109
|
};
|
|
68387
69110
|
}
|
|
68388
69111
|
async function runAgentTurn(options) {
|
|
@@ -68395,10 +69118,17 @@ async function runAgentTurn(options) {
|
|
|
68395
69118
|
const skipLocal = await shouldSkipAutoLocalForServerPlatformTools(options);
|
|
68396
69119
|
if (!skipLocal) {
|
|
68397
69120
|
const localResult = await runLocalAgentTurnForCli(options, { reportFailure: false });
|
|
69121
|
+
if (localResult.exitCode !== 0 && localResult.localError) {
|
|
69122
|
+
options.output.write(
|
|
69123
|
+
`[nolo] auto runtime: local run unavailable (${localResult.localError instanceof Error ? localResult.localError.message : String(localResult.localError)}); falling back to server.
|
|
69124
|
+
`
|
|
69125
|
+
);
|
|
69126
|
+
}
|
|
68398
69127
|
if (localResult.exitCode === 0) {
|
|
68399
69128
|
return {
|
|
68400
69129
|
exitCode: localResult.exitCode,
|
|
68401
|
-
...localResult.dialogId ? { dialogId: localResult.dialogId } : {}
|
|
69130
|
+
...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
|
|
69131
|
+
...localResult.turnTokens ? { turnTokens: localResult.turnTokens } : {}
|
|
68402
69132
|
};
|
|
68403
69133
|
}
|
|
68404
69134
|
if (isMissingLocalAgentConfigError(localResult.localError, options.agentKey)) {
|
|
@@ -68415,7 +69145,8 @@ async function runAgentTurn(options) {
|
|
|
68415
69145
|
if (retriedLocalResult.exitCode === 0) {
|
|
68416
69146
|
return {
|
|
68417
69147
|
exitCode: retriedLocalResult.exitCode,
|
|
68418
|
-
...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {}
|
|
69148
|
+
...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {},
|
|
69149
|
+
...retriedLocalResult.turnTokens ? { turnTokens: retriedLocalResult.turnTokens } : {}
|
|
68419
69150
|
};
|
|
68420
69151
|
}
|
|
68421
69152
|
}
|
|
@@ -69617,7 +70348,7 @@ function countByName(values) {
|
|
|
69617
70348
|
function uniq(values) {
|
|
69618
70349
|
return [...new Set(values.filter(Boolean))];
|
|
69619
70350
|
}
|
|
69620
|
-
function
|
|
70351
|
+
function parseJsonObject2(raw) {
|
|
69621
70352
|
if (typeof raw !== "string" || !raw.trim()) return null;
|
|
69622
70353
|
try {
|
|
69623
70354
|
const parsed = JSON.parse(raw);
|
|
@@ -69633,7 +70364,7 @@ function deriveWrittenFiles(toolMessages) {
|
|
|
69633
70364
|
const toolName = toToolName(message?.toolName ?? message?.name);
|
|
69634
70365
|
if (!writeToolNames.has(toolName)) continue;
|
|
69635
70366
|
const payload = message?.toolPayload ?? {};
|
|
69636
|
-
const content =
|
|
70367
|
+
const content = parseJsonObject2(message?.content);
|
|
69637
70368
|
for (const candidate of [payload?.input?.filePath, payload?.response?.filePath, content?.filePath]) {
|
|
69638
70369
|
const normalized = typeof candidate === "string" ? candidate.trim() : "";
|
|
69639
70370
|
if (normalized) files.push(normalized);
|
|
@@ -69646,7 +70377,7 @@ function deriveToolErrors(toolMessages) {
|
|
|
69646
70377
|
for (const message of toolMessages) {
|
|
69647
70378
|
const toolName = toToolName(message?.toolName ?? message?.name);
|
|
69648
70379
|
const payload = message?.toolPayload ?? {};
|
|
69649
|
-
const content =
|
|
70380
|
+
const content = parseJsonObject2(message?.content);
|
|
69650
70381
|
if (payload?.status === "failed" || content?.ok === false || content?.applied === false || content?.success === false) {
|
|
69651
70382
|
errors.push(toolName || "unknown-tool");
|
|
69652
70383
|
}
|
|
@@ -71578,6 +72309,18 @@ function getCurrentProfile(config) {
|
|
|
71578
72309
|
if (!config) return null;
|
|
71579
72310
|
return config.profiles[config.currentProfile] ?? null;
|
|
71580
72311
|
}
|
|
72312
|
+
function saveProfileAgentSelection(selection, path7 = getDefaultProfileConfigPath()) {
|
|
72313
|
+
const config = loadProfileConfig(path7);
|
|
72314
|
+
if (!config) return null;
|
|
72315
|
+
const profile = config.profiles[config.currentProfile];
|
|
72316
|
+
if (!profile) return null;
|
|
72317
|
+
profile.agentKey = selection.agentKey.trim();
|
|
72318
|
+
profile.agentName = selection.agentName.trim();
|
|
72319
|
+
mkdirSync5(dirname6(path7), { recursive: true });
|
|
72320
|
+
writeFileSync4(path7, `${JSON.stringify(config, null, 2)}
|
|
72321
|
+
`, "utf8");
|
|
72322
|
+
return config;
|
|
72323
|
+
}
|
|
71581
72324
|
|
|
71582
72325
|
// packages/cli/authCommands.ts
|
|
71583
72326
|
init_cliEnvHelpers();
|
|
@@ -73315,23 +74058,410 @@ async function compactDialog(options) {
|
|
|
73315
74058
|
// packages/cli/tui/readlineWorkspace.ts
|
|
73316
74059
|
init_processSpawn();
|
|
73317
74060
|
|
|
73318
|
-
// packages/cli/tui/
|
|
73319
|
-
|
|
74061
|
+
// packages/cli/tui/agentPicker.ts
|
|
74062
|
+
init_agentAliases();
|
|
74063
|
+
|
|
74064
|
+
// packages/cli/tui/agentCatalog.ts
|
|
74065
|
+
init_cliEnvHelpers();
|
|
73320
74066
|
var DEFAULT_TUI_AGENT_KEY = "agent-pub-01NOLOAPPBLD000000019KCKT0";
|
|
73321
|
-
var
|
|
73322
|
-
var KNOWN_AGENTS = [
|
|
74067
|
+
var PLATFORM_AGENTS = [
|
|
73323
74068
|
{
|
|
73324
74069
|
name: "nolo",
|
|
73325
|
-
key:
|
|
74070
|
+
key: DEFAULT_TUI_AGENT_KEY,
|
|
74071
|
+
model: "-",
|
|
74072
|
+
kind: "platform",
|
|
73326
74073
|
description: "one assistant that routes work across your agents and data"
|
|
73327
74074
|
},
|
|
73328
74075
|
{
|
|
73329
74076
|
name: "app-builder",
|
|
73330
74077
|
key: "agent-pub-01APPBUILDER00000001YAII3I",
|
|
74078
|
+
model: "-",
|
|
74079
|
+
kind: "platform",
|
|
73331
74080
|
description: "builds web apps, tools, charts, and product prototypes"
|
|
73332
74081
|
}
|
|
73333
74082
|
];
|
|
73334
|
-
|
|
74083
|
+
function toUpdatedAt(value) {
|
|
74084
|
+
if (value == null) return 0;
|
|
74085
|
+
const parsed = new Date(value).getTime();
|
|
74086
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
74087
|
+
}
|
|
74088
|
+
function listedAgentToCatalogEntry(agent) {
|
|
74089
|
+
return {
|
|
74090
|
+
name: agent.name,
|
|
74091
|
+
key: agent.privateKey,
|
|
74092
|
+
model: agent.model,
|
|
74093
|
+
kind: "private",
|
|
74094
|
+
updatedAt: toUpdatedAt(agent.updatedAt)
|
|
74095
|
+
};
|
|
74096
|
+
}
|
|
74097
|
+
function mergeCatalogEntries(currentKey, platformAgents, privateAgents) {
|
|
74098
|
+
const seen = /* @__PURE__ */ new Set();
|
|
74099
|
+
const merged = [];
|
|
74100
|
+
const push = (entry) => {
|
|
74101
|
+
if (seen.has(entry.key)) return;
|
|
74102
|
+
seen.add(entry.key);
|
|
74103
|
+
merged.push(entry);
|
|
74104
|
+
};
|
|
74105
|
+
const current = [...platformAgents, ...privateAgents].find((entry) => entry.key === currentKey) ?? null;
|
|
74106
|
+
if (current) push(current);
|
|
74107
|
+
for (const entry of platformAgents) {
|
|
74108
|
+
if (entry.key !== currentKey) push(entry);
|
|
74109
|
+
}
|
|
74110
|
+
const sortedPrivate = [...privateAgents].sort((a, b) => {
|
|
74111
|
+
const tb = b.updatedAt ?? 0;
|
|
74112
|
+
const ta = a.updatedAt ?? 0;
|
|
74113
|
+
if (tb !== ta) return tb - ta;
|
|
74114
|
+
return a.name.localeCompare(b.name);
|
|
74115
|
+
});
|
|
74116
|
+
for (const entry of sortedPrivate) {
|
|
74117
|
+
if (entry.key !== currentKey) push(entry);
|
|
74118
|
+
}
|
|
74119
|
+
return merged;
|
|
74120
|
+
}
|
|
74121
|
+
async function loadAgentCatalog(args2) {
|
|
74122
|
+
const env = args2.env ?? process.env;
|
|
74123
|
+
const fetchImpl = args2.fetchImpl ?? fetch;
|
|
74124
|
+
const fallbackFetchImpl = args2.fallbackFetchImpl;
|
|
74125
|
+
const authToken = resolveAuthToken([], env);
|
|
74126
|
+
const userId = authToken ? parseUserIdFromAuthToken(authToken) : null;
|
|
74127
|
+
if (!authToken || !userId) {
|
|
74128
|
+
return mergeCatalogEntries(args2.currentKey, PLATFORM_AGENTS, []);
|
|
74129
|
+
}
|
|
74130
|
+
const serverUrl = resolveServerUrl(env);
|
|
74131
|
+
const serverUrls = resolveServerCandidates([], env, serverUrl);
|
|
74132
|
+
let privateAgents = [];
|
|
74133
|
+
try {
|
|
74134
|
+
const remoteResult = await listRemoteAgentsAcrossServers({
|
|
74135
|
+
authToken,
|
|
74136
|
+
fallbackFetchImpl,
|
|
74137
|
+
fetchImpl,
|
|
74138
|
+
includeLegacy: false,
|
|
74139
|
+
serverUrls,
|
|
74140
|
+
userId
|
|
74141
|
+
});
|
|
74142
|
+
privateAgents = remoteResult.agents.map(listedAgentToCatalogEntry);
|
|
74143
|
+
} catch {
|
|
74144
|
+
try {
|
|
74145
|
+
const db = await getReadableCliDb();
|
|
74146
|
+
const cached = await listLocalCachedAgents({ db, userId });
|
|
74147
|
+
privateAgents = cached.map(listedAgentToCatalogEntry);
|
|
74148
|
+
} catch {
|
|
74149
|
+
privateAgents = (await listRemoteAgents({
|
|
74150
|
+
authToken,
|
|
74151
|
+
fallbackFetchImpl,
|
|
74152
|
+
fetchImpl,
|
|
74153
|
+
includeLegacy: false,
|
|
74154
|
+
serverUrl,
|
|
74155
|
+
userId,
|
|
74156
|
+
queryUserRecords,
|
|
74157
|
+
readDbRecord
|
|
74158
|
+
})).map(listedAgentToCatalogEntry);
|
|
74159
|
+
}
|
|
74160
|
+
}
|
|
74161
|
+
return mergeCatalogEntries(args2.currentKey, PLATFORM_AGENTS, privateAgents);
|
|
74162
|
+
}
|
|
74163
|
+
function renderAgentCatalogList(entries, currentKey) {
|
|
74164
|
+
const lines = ["Agents:"];
|
|
74165
|
+
entries.forEach((entry, index) => {
|
|
74166
|
+
const current = entry.key === currentKey ? " (current)" : "";
|
|
74167
|
+
const kind = entry.kind === "platform" ? "platform" : "private";
|
|
74168
|
+
const detail = entry.description ? ` \u2014 ${entry.description}` : "";
|
|
74169
|
+
lines.push(
|
|
74170
|
+
` ${String(index + 1).padStart(2)} ${entry.name.padEnd(18)} ${entry.model.padEnd(14)} ${kind}${detail}${current}`
|
|
74171
|
+
);
|
|
74172
|
+
});
|
|
74173
|
+
lines.push("");
|
|
74174
|
+
lines.push("Tip: run /agent in an interactive terminal to pick with \u2191\u2193.");
|
|
74175
|
+
return lines.join("\n");
|
|
74176
|
+
}
|
|
74177
|
+
function findAgentCatalogEntry(entries, rawTarget) {
|
|
74178
|
+
const target = rawTarget.trim();
|
|
74179
|
+
if (!target) return null;
|
|
74180
|
+
if (/^\d+$/.test(target)) {
|
|
74181
|
+
const entry = entries[Number(target) - 1];
|
|
74182
|
+
return entry ? { name: entry.name, key: entry.key } : null;
|
|
74183
|
+
}
|
|
74184
|
+
const lower = target.toLowerCase();
|
|
74185
|
+
const byName = entries.find(
|
|
74186
|
+
(entry) => entry.name.toLowerCase() === lower || entry.key.toLowerCase() === lower || entry.key.toLowerCase().endsWith(`-${lower}`)
|
|
74187
|
+
);
|
|
74188
|
+
if (byName) return { name: byName.name, key: byName.key };
|
|
74189
|
+
if (target.startsWith("agent-") || target.startsWith("agent-pub-") || target.startsWith("cybot-")) {
|
|
74190
|
+
return { name: target, key: target };
|
|
74191
|
+
}
|
|
74192
|
+
return null;
|
|
74193
|
+
}
|
|
74194
|
+
|
|
74195
|
+
// packages/cli/tui/selectDialog.ts
|
|
74196
|
+
var CSI_ARROW_UP = "\x1B[A";
|
|
74197
|
+
var CSI_ARROW_DOWN = "\x1B[B";
|
|
74198
|
+
var CSI_ARROW_UP_APP = "\x1BOA";
|
|
74199
|
+
var CSI_ARROW_DOWN_APP = "\x1BOB";
|
|
74200
|
+
var DEFAULT_MAX_VISIBLE = 8;
|
|
74201
|
+
function computeVisibleWindow(args2) {
|
|
74202
|
+
const maxVisible = Math.max(1, args2.maxVisible ?? DEFAULT_MAX_VISIBLE);
|
|
74203
|
+
if (args2.total <= maxVisible) {
|
|
74204
|
+
return { start: 0, end: args2.total, maxVisible };
|
|
74205
|
+
}
|
|
74206
|
+
let start = Math.max(0, args2.selectedIndex - Math.floor(maxVisible / 2));
|
|
74207
|
+
if (start + maxVisible > args2.total) {
|
|
74208
|
+
start = args2.total - maxVisible;
|
|
74209
|
+
}
|
|
74210
|
+
return { start, end: start + maxVisible, maxVisible };
|
|
74211
|
+
}
|
|
74212
|
+
function renderSelectDialog(args2) {
|
|
74213
|
+
const total = args2.items.length;
|
|
74214
|
+
const window2 = computeVisibleWindow({
|
|
74215
|
+
selectedIndex: args2.selectedIndex,
|
|
74216
|
+
total,
|
|
74217
|
+
maxVisible: args2.maxVisible
|
|
74218
|
+
});
|
|
74219
|
+
const lines = [
|
|
74220
|
+
args2.title ?? `Select agent (\u2191\u2193 Enter Esc) ${args2.selectedIndex + 1}/${total}`
|
|
74221
|
+
];
|
|
74222
|
+
if (window2.start > 0) {
|
|
74223
|
+
lines.push(` ... ${window2.start} more above`);
|
|
74224
|
+
}
|
|
74225
|
+
for (let index = window2.start; index < window2.end; index += 1) {
|
|
74226
|
+
const item = args2.items[index];
|
|
74227
|
+
const marker = index === args2.selectedIndex ? ">" : " ";
|
|
74228
|
+
const detail = item.detail ? ` ${item.detail}` : "";
|
|
74229
|
+
lines.push(`${marker} ${item.label}${detail}`);
|
|
74230
|
+
}
|
|
74231
|
+
if (window2.end < total) {
|
|
74232
|
+
lines.push(` ... ${total - window2.end} more below`);
|
|
74233
|
+
}
|
|
74234
|
+
return lines.join("\n");
|
|
74235
|
+
}
|
|
74236
|
+
function countRenderedLines(text) {
|
|
74237
|
+
return text.split("\n").length;
|
|
74238
|
+
}
|
|
74239
|
+
function clearRenderedLines(output2, lineCount) {
|
|
74240
|
+
if (!output2.isTTY || lineCount <= 0) return;
|
|
74241
|
+
for (let index = 0; index < lineCount; index += 1) {
|
|
74242
|
+
output2.write("\x1B[1A\x1B[2K");
|
|
74243
|
+
}
|
|
74244
|
+
}
|
|
74245
|
+
function isArrowUp(sequence) {
|
|
74246
|
+
return sequence === CSI_ARROW_UP || sequence === CSI_ARROW_UP_APP;
|
|
74247
|
+
}
|
|
74248
|
+
function isArrowDown(sequence) {
|
|
74249
|
+
return sequence === CSI_ARROW_DOWN || sequence === CSI_ARROW_DOWN_APP;
|
|
74250
|
+
}
|
|
74251
|
+
function isSubmit(sequence) {
|
|
74252
|
+
return sequence === "\r" || sequence === "\n";
|
|
74253
|
+
}
|
|
74254
|
+
function isCancel(sequence) {
|
|
74255
|
+
return sequence === "" || sequence === "\x1B";
|
|
74256
|
+
}
|
|
74257
|
+
function createRawKeyReader(input2) {
|
|
74258
|
+
let buffer = "";
|
|
74259
|
+
const tryParseSequence = () => {
|
|
74260
|
+
if (!buffer) return null;
|
|
74261
|
+
if (isSubmit(buffer) || isCancel(buffer)) {
|
|
74262
|
+
const sequence2 = buffer;
|
|
74263
|
+
buffer = "";
|
|
74264
|
+
return sequence2;
|
|
74265
|
+
}
|
|
74266
|
+
if (buffer.startsWith("\x1B")) {
|
|
74267
|
+
for (const candidate of [
|
|
74268
|
+
CSI_ARROW_UP,
|
|
74269
|
+
CSI_ARROW_DOWN,
|
|
74270
|
+
CSI_ARROW_UP_APP,
|
|
74271
|
+
CSI_ARROW_DOWN_APP
|
|
74272
|
+
]) {
|
|
74273
|
+
if (buffer.startsWith(candidate)) {
|
|
74274
|
+
buffer = buffer.slice(candidate.length);
|
|
74275
|
+
return candidate;
|
|
74276
|
+
}
|
|
74277
|
+
}
|
|
74278
|
+
if (buffer.length >= 8) {
|
|
74279
|
+
buffer = "";
|
|
74280
|
+
return null;
|
|
74281
|
+
}
|
|
74282
|
+
return void 0;
|
|
74283
|
+
}
|
|
74284
|
+
const sequence = buffer;
|
|
74285
|
+
buffer = "";
|
|
74286
|
+
return sequence;
|
|
74287
|
+
};
|
|
74288
|
+
return () => new Promise((resolve6) => {
|
|
74289
|
+
const finalize = (sequence) => {
|
|
74290
|
+
cleanup();
|
|
74291
|
+
resolve6(sequence ?? null);
|
|
74292
|
+
};
|
|
74293
|
+
const onReadable = () => {
|
|
74294
|
+
while (true) {
|
|
74295
|
+
const chunk = input2.read();
|
|
74296
|
+
if (chunk == null) break;
|
|
74297
|
+
buffer += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
74298
|
+
const parsed = tryParseSequence();
|
|
74299
|
+
if (parsed === void 0) return;
|
|
74300
|
+
finalize(parsed);
|
|
74301
|
+
return;
|
|
74302
|
+
}
|
|
74303
|
+
};
|
|
74304
|
+
const cleanup = () => {
|
|
74305
|
+
input2.off("readable", onReadable);
|
|
74306
|
+
};
|
|
74307
|
+
onReadable();
|
|
74308
|
+
if (buffer) {
|
|
74309
|
+
const parsed = tryParseSequence();
|
|
74310
|
+
if (parsed !== void 0) {
|
|
74311
|
+
finalize(parsed);
|
|
74312
|
+
return;
|
|
74313
|
+
}
|
|
74314
|
+
}
|
|
74315
|
+
input2.on("readable", onReadable);
|
|
74316
|
+
});
|
|
74317
|
+
}
|
|
74318
|
+
function drainInputBuffer(input2) {
|
|
74319
|
+
if (typeof input2.read !== "function") return;
|
|
74320
|
+
while (input2.read() !== null) {
|
|
74321
|
+
}
|
|
74322
|
+
}
|
|
74323
|
+
async function runSelectDialog(args2) {
|
|
74324
|
+
const items = args2.items;
|
|
74325
|
+
if (items.length === 0) {
|
|
74326
|
+
return { kind: "cancelled" };
|
|
74327
|
+
}
|
|
74328
|
+
let selectedIndex = Math.min(
|
|
74329
|
+
Math.max(args2.initialIndex ?? 0, 0),
|
|
74330
|
+
items.length - 1
|
|
74331
|
+
);
|
|
74332
|
+
const output2 = args2.output ?? process.stdout;
|
|
74333
|
+
const input2 = args2.input ?? process.stdin;
|
|
74334
|
+
const readKey = args2.readKey ?? createRawKeyReader(input2);
|
|
74335
|
+
const wasRaw = Boolean(input2.isTTY && input2.isRaw);
|
|
74336
|
+
const wasPaused = typeof input2.isPaused === "function" ? input2.isPaused() : false;
|
|
74337
|
+
let renderedLineCount = 0;
|
|
74338
|
+
const paint = () => {
|
|
74339
|
+
const frame = renderSelectDialog({
|
|
74340
|
+
items,
|
|
74341
|
+
selectedIndex,
|
|
74342
|
+
title: args2.title,
|
|
74343
|
+
maxVisible: args2.maxVisible
|
|
74344
|
+
});
|
|
74345
|
+
if (output2.isTTY && typeof output2.write === "function") {
|
|
74346
|
+
clearRenderedLines(output2, renderedLineCount);
|
|
74347
|
+
output2.write(`${frame}
|
|
74348
|
+
`);
|
|
74349
|
+
renderedLineCount = countRenderedLines(frame);
|
|
74350
|
+
return;
|
|
74351
|
+
}
|
|
74352
|
+
if (typeof output2.write === "function") {
|
|
74353
|
+
output2.write(`${frame}
|
|
74354
|
+
`);
|
|
74355
|
+
}
|
|
74356
|
+
renderedLineCount = countRenderedLines(frame);
|
|
74357
|
+
};
|
|
74358
|
+
if (input2.isTTY) {
|
|
74359
|
+
if (!wasRaw) input2.setRawMode(true);
|
|
74360
|
+
if (!wasPaused) input2.pause();
|
|
74361
|
+
}
|
|
74362
|
+
paint();
|
|
74363
|
+
try {
|
|
74364
|
+
while (true) {
|
|
74365
|
+
const sequence = await readKey();
|
|
74366
|
+
if (sequence == null) {
|
|
74367
|
+
return { kind: "cancelled" };
|
|
74368
|
+
}
|
|
74369
|
+
if (isCancel(sequence)) {
|
|
74370
|
+
return { kind: "cancelled" };
|
|
74371
|
+
}
|
|
74372
|
+
if (isSubmit(sequence)) {
|
|
74373
|
+
return { kind: "selected", index: selectedIndex, item: items[selectedIndex] };
|
|
74374
|
+
}
|
|
74375
|
+
if (isArrowUp(sequence)) {
|
|
74376
|
+
selectedIndex = selectedIndex <= 0 ? items.length - 1 : selectedIndex - 1;
|
|
74377
|
+
paint();
|
|
74378
|
+
continue;
|
|
74379
|
+
}
|
|
74380
|
+
if (isArrowDown(sequence)) {
|
|
74381
|
+
selectedIndex = selectedIndex >= items.length - 1 ? 0 : selectedIndex + 1;
|
|
74382
|
+
paint();
|
|
74383
|
+
continue;
|
|
74384
|
+
}
|
|
74385
|
+
}
|
|
74386
|
+
} finally {
|
|
74387
|
+
if (input2.isTTY) {
|
|
74388
|
+
drainInputBuffer(input2);
|
|
74389
|
+
if (!wasRaw) input2.setRawMode(false);
|
|
74390
|
+
if (!wasPaused) input2.resume();
|
|
74391
|
+
clearRenderedLines(output2, renderedLineCount);
|
|
74392
|
+
renderedLineCount = 0;
|
|
74393
|
+
}
|
|
74394
|
+
}
|
|
74395
|
+
}
|
|
74396
|
+
|
|
74397
|
+
// packages/cli/tui/agentPicker.ts
|
|
74398
|
+
function toAgentPickerItems(entries) {
|
|
74399
|
+
return entries.map((entry) => ({
|
|
74400
|
+
label: entry.name,
|
|
74401
|
+
detail: `${entry.model} ${entry.kind}`,
|
|
74402
|
+
entry
|
|
74403
|
+
}));
|
|
74404
|
+
}
|
|
74405
|
+
function formatAgentSwitchMessage(args2) {
|
|
74406
|
+
const dialog = args2.dialogId ? `Dialog kept: ${args2.dialogId}` : "Dialog kept: new";
|
|
74407
|
+
return `Switched to ${args2.name}. ${dialog}`;
|
|
74408
|
+
}
|
|
74409
|
+
async function runAgentPicker(args2) {
|
|
74410
|
+
const output2 = args2.output ?? process.stdout;
|
|
74411
|
+
const input2 = args2.input ?? process.stdin;
|
|
74412
|
+
const interactive = args2.interactive ?? Boolean(input2.isTTY && output2.isTTY);
|
|
74413
|
+
const entries = await loadAgentCatalog({
|
|
74414
|
+
env: args2.env,
|
|
74415
|
+
currentKey: args2.currentKey,
|
|
74416
|
+
fetchImpl: args2.fetchImpl,
|
|
74417
|
+
fallbackFetchImpl: args2.fallbackFetchImpl
|
|
74418
|
+
});
|
|
74419
|
+
if (!interactive) {
|
|
74420
|
+
return {
|
|
74421
|
+
kind: "list",
|
|
74422
|
+
output: renderAgentCatalogList(entries, args2.currentKey),
|
|
74423
|
+
entries
|
|
74424
|
+
};
|
|
74425
|
+
}
|
|
74426
|
+
const items = toAgentPickerItems(entries);
|
|
74427
|
+
const initialIndex = Math.max(
|
|
74428
|
+
entries.findIndex((entry) => entry.key === args2.currentKey),
|
|
74429
|
+
0
|
|
74430
|
+
);
|
|
74431
|
+
const result = await runSelectDialog({
|
|
74432
|
+
items,
|
|
74433
|
+
initialIndex,
|
|
74434
|
+
title: void 0,
|
|
74435
|
+
input: input2,
|
|
74436
|
+
output: output2,
|
|
74437
|
+
readKey: args2.readKey
|
|
74438
|
+
});
|
|
74439
|
+
if (result.kind === "cancelled") {
|
|
74440
|
+
return { kind: "cancelled", entries };
|
|
74441
|
+
}
|
|
74442
|
+
const selected = result.item.entry;
|
|
74443
|
+
return {
|
|
74444
|
+
kind: "selected",
|
|
74445
|
+
name: selected.name,
|
|
74446
|
+
key: selected.key,
|
|
74447
|
+
entries
|
|
74448
|
+
};
|
|
74449
|
+
}
|
|
74450
|
+
function resolveAgentSwitchTarget(rawTarget, catalogEntries = []) {
|
|
74451
|
+
const resolvedKey = resolveCliAgentKeyInput(rawTarget);
|
|
74452
|
+
if (resolvedKey !== rawTarget.trim()) {
|
|
74453
|
+
const aliasEntry = catalogEntries.find((entry) => entry.key === resolvedKey);
|
|
74454
|
+
return {
|
|
74455
|
+
name: aliasEntry?.name ?? rawTarget.trim().toLowerCase(),
|
|
74456
|
+
key: resolvedKey
|
|
74457
|
+
};
|
|
74458
|
+
}
|
|
74459
|
+
return findAgentCatalogEntry(catalogEntries, rawTarget);
|
|
74460
|
+
}
|
|
74461
|
+
|
|
74462
|
+
// packages/cli/tui/session.ts
|
|
74463
|
+
init_defaultServer();
|
|
74464
|
+
var DEFAULT_TUI_SERVER_URL = DEFAULT_NOLO_SERVER_URL;
|
|
73335
74465
|
function shortenDialogId(dialogId) {
|
|
73336
74466
|
return dialogId.length > 12 ? `${dialogId.slice(0, 6)}...${dialogId.slice(-4)}` : dialogId;
|
|
73337
74467
|
}
|
|
@@ -73353,25 +74483,29 @@ function createInitialTuiState(env = process.env) {
|
|
|
73353
74483
|
),
|
|
73354
74484
|
cliVersion: env.NOLO_CLI_VERSION?.trim() || void 0,
|
|
73355
74485
|
attachedDocs: [],
|
|
73356
|
-
runtimeMode: env.NOLO_RUNTIME_MODE === "local" || env.NOLO_RUNTIME_MODE === "server" ? env.NOLO_RUNTIME_MODE : "auto"
|
|
74486
|
+
runtimeMode: env.NOLO_RUNTIME_MODE === "local" || env.NOLO_RUNTIME_MODE === "server" ? env.NOLO_RUNTIME_MODE : "auto",
|
|
74487
|
+
thinkingDisplay: normalizeThinkingDisplayMode(
|
|
74488
|
+
env.NOLO_CLI_THINKING ?? env.NOLO_THINKING,
|
|
74489
|
+
"hide"
|
|
74490
|
+
),
|
|
74491
|
+
toolDisplay: normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact"),
|
|
74492
|
+
renderDisplay: normalizeRenderDisplayMode(env.NOLO_CLI_RENDER ?? env.NOLO_RENDER, "rich")
|
|
73357
74493
|
};
|
|
73358
74494
|
}
|
|
73359
74495
|
function renderStatusLine(state) {
|
|
73360
|
-
const
|
|
73361
|
-
|
|
73362
|
-
|
|
73363
|
-
|
|
73364
|
-
|
|
73365
|
-
|
|
73366
|
-
|
|
73367
|
-
].join(" | ");
|
|
74496
|
+
const colorEnabled = resolveCliColorEnabled();
|
|
74497
|
+
const agent = styleCliText(state.agentName, "cyan", colorEnabled);
|
|
74498
|
+
const tokens = dimCliText(renderTokenStatus(state.turnTokens), colorEnabled);
|
|
74499
|
+
const profile = dimCliText(`profile ${state.profileName}`, colorEnabled);
|
|
74500
|
+
return [`agent ${agent}`, tokens, profile].join(
|
|
74501
|
+
dimCliText(" | ", colorEnabled)
|
|
74502
|
+
);
|
|
73368
74503
|
}
|
|
73369
74504
|
function renderWelcome(state) {
|
|
73370
|
-
const docs = state.attachedDocs.length > 0 ? `${state.attachedDocs.length} attached` : "none";
|
|
73371
74505
|
return [
|
|
73372
74506
|
"",
|
|
73373
74507
|
`Nolo workspace${state.cliVersion ? ` nolo ${state.cliVersion}` : ""}`,
|
|
73374
|
-
`agent ${state.agentName} |
|
|
74508
|
+
`agent ${state.agentName} | ${renderTokenStatus(state.turnTokens)} | profile ${state.profileName}`,
|
|
73375
74509
|
`server ${state.serverUrl}`,
|
|
73376
74510
|
"",
|
|
73377
74511
|
"Tell nolo what you want. Use /help for commands. Use /version if this install feels stale.",
|
|
@@ -73389,9 +74523,14 @@ function renderTuiHelp() {
|
|
|
73389
74523
|
" /compact Compact current dialog and fork a new one",
|
|
73390
74524
|
" /context Show workspace context and next actions",
|
|
73391
74525
|
" /runtime <mode> Use auto, local, or server runtime",
|
|
73392
|
-
" /
|
|
73393
|
-
" /
|
|
73394
|
-
" /
|
|
74526
|
+
" /tools <mode> Control tool trace: hide, compact, verbose",
|
|
74527
|
+
" /thinking <mode> Control thinking output: hide, marker, show",
|
|
74528
|
+
" /render <mode> Control assistant output: plain, rich",
|
|
74529
|
+
" /agent Pick an agent interactively (\u2191\u2193, Enter)",
|
|
74530
|
+
" /agent list List agents as text",
|
|
74531
|
+
" /agent <name> Switch directly by name, alias, or key",
|
|
74532
|
+
" /agents List platform agent shortcuts",
|
|
74533
|
+
" /switch <agent> Switch the current agent (alias of /agent <name>)",
|
|
73395
74534
|
" /dialog Show the current dialog",
|
|
73396
74535
|
" /doc List attached docs",
|
|
73397
74536
|
" /doc attach <doc> Attach a doc to this workspace",
|
|
@@ -73410,12 +74549,16 @@ function renderContextPanel(state) {
|
|
|
73410
74549
|
return [
|
|
73411
74550
|
"Workspace context",
|
|
73412
74551
|
"-----------------",
|
|
73413
|
-
`agent
|
|
73414
|
-
`
|
|
73415
|
-
`
|
|
73416
|
-
`
|
|
73417
|
-
`
|
|
73418
|
-
`
|
|
74552
|
+
`agent ${state.agentName}`,
|
|
74553
|
+
`tokens ${renderTokenStatus(state.turnTokens)}`,
|
|
74554
|
+
`dialog ${resolveDialogLabel(state)}`,
|
|
74555
|
+
`docs ${docs}`,
|
|
74556
|
+
`profile ${state.profileName}`,
|
|
74557
|
+
`runtime ${state.runtimeMode}`,
|
|
74558
|
+
`tools ${state.toolDisplay}`,
|
|
74559
|
+
`thinking ${state.thinkingDisplay}`,
|
|
74560
|
+
`render ${state.renderDisplay}`,
|
|
74561
|
+
`server ${state.serverUrl}`,
|
|
73419
74562
|
"",
|
|
73420
74563
|
"Next:",
|
|
73421
74564
|
" /agents see specialist shortcuts",
|
|
@@ -73426,25 +74569,22 @@ function renderContextPanel(state) {
|
|
|
73426
74569
|
function renderKnownAgents() {
|
|
73427
74570
|
return [
|
|
73428
74571
|
"Agents:",
|
|
73429
|
-
...
|
|
73430
|
-
(agent, index) => ` ${index + 1} ${agent.name.padEnd(11)} ${agent.description}`
|
|
74572
|
+
...PLATFORM_AGENTS.map(
|
|
74573
|
+
(agent, index) => ` ${index + 1} ${agent.name.padEnd(11)} ${agent.description ?? ""}`
|
|
73431
74574
|
),
|
|
73432
74575
|
"",
|
|
73433
|
-
"Tip:
|
|
74576
|
+
"Tip: run /agent for the full picker, or /agent list for your private agents too."
|
|
73434
74577
|
].join("\n");
|
|
73435
74578
|
}
|
|
73436
|
-
function
|
|
73437
|
-
|
|
73438
|
-
|
|
73439
|
-
|
|
73440
|
-
|
|
73441
|
-
|
|
73442
|
-
|
|
73443
|
-
|
|
73444
|
-
|
|
73445
|
-
return { name: target, key: target };
|
|
73446
|
-
}
|
|
73447
|
-
return null;
|
|
74579
|
+
function applyAgentSwitch(state, target) {
|
|
74580
|
+
return {
|
|
74581
|
+
nextState: {
|
|
74582
|
+
...state,
|
|
74583
|
+
agentName: target.name,
|
|
74584
|
+
agentKey: target.key
|
|
74585
|
+
},
|
|
74586
|
+
output: `Switched to ${target.name}. ${state.dialogId ? `Dialog kept: ${state.dialogId}` : "Dialog kept: new"}`
|
|
74587
|
+
};
|
|
73448
74588
|
}
|
|
73449
74589
|
var DIALOG_ID_PATTERN = /[0-9A-HJKMNP-TV-Z]{26}/i;
|
|
73450
74590
|
var DIALOG_KEY_PATTERN = /dialog-[^\s"'<>]+-[0-9A-HJKMNP-TV-Z]{26}/i;
|
|
@@ -73622,6 +74762,66 @@ function handleTuiInput(input2, state) {
|
|
|
73622
74762
|
output: `Runtime: ${argText}`
|
|
73623
74763
|
};
|
|
73624
74764
|
}
|
|
74765
|
+
case "/tools": {
|
|
74766
|
+
if (!argText) {
|
|
74767
|
+
return {
|
|
74768
|
+
nextState: state,
|
|
74769
|
+
output: `Tool display: ${state.toolDisplay} (hide | compact | verbose)`
|
|
74770
|
+
};
|
|
74771
|
+
}
|
|
74772
|
+
const normalizedArg = argText.trim().toLowerCase();
|
|
74773
|
+
if (!["hide", "compact", "verbose", "on", "off"].includes(normalizedArg)) {
|
|
74774
|
+
return {
|
|
74775
|
+
nextState: state,
|
|
74776
|
+
output: "Usage: /tools <hide|compact|verbose>"
|
|
74777
|
+
};
|
|
74778
|
+
}
|
|
74779
|
+
const nextMode = normalizeToolDisplayMode(normalizedArg, state.toolDisplay);
|
|
74780
|
+
return {
|
|
74781
|
+
nextState: { ...state, toolDisplay: nextMode },
|
|
74782
|
+
output: `Tool display: ${nextMode}`
|
|
74783
|
+
};
|
|
74784
|
+
}
|
|
74785
|
+
case "/thinking": {
|
|
74786
|
+
if (!argText) {
|
|
74787
|
+
return {
|
|
74788
|
+
nextState: state,
|
|
74789
|
+
output: `Thinking display: ${state.thinkingDisplay} (hide | marker | show)`
|
|
74790
|
+
};
|
|
74791
|
+
}
|
|
74792
|
+
const normalizedArg = argText.trim().toLowerCase();
|
|
74793
|
+
if (!["hide", "marker", "show", "on", "off"].includes(normalizedArg)) {
|
|
74794
|
+
return {
|
|
74795
|
+
nextState: state,
|
|
74796
|
+
output: "Usage: /thinking <hide|marker|show>"
|
|
74797
|
+
};
|
|
74798
|
+
}
|
|
74799
|
+
const nextMode = normalizeThinkingDisplayMode(normalizedArg, state.thinkingDisplay);
|
|
74800
|
+
return {
|
|
74801
|
+
nextState: { ...state, thinkingDisplay: nextMode },
|
|
74802
|
+
output: `Thinking display: ${nextMode}`
|
|
74803
|
+
};
|
|
74804
|
+
}
|
|
74805
|
+
case "/render": {
|
|
74806
|
+
if (!argText) {
|
|
74807
|
+
return {
|
|
74808
|
+
nextState: state,
|
|
74809
|
+
output: `Render display: ${state.renderDisplay} (plain | rich)`
|
|
74810
|
+
};
|
|
74811
|
+
}
|
|
74812
|
+
const normalizedArg = argText.trim().toLowerCase();
|
|
74813
|
+
if (!["plain", "rich", "on", "off"].includes(normalizedArg)) {
|
|
74814
|
+
return {
|
|
74815
|
+
nextState: state,
|
|
74816
|
+
output: "Usage: /render <plain|rich>"
|
|
74817
|
+
};
|
|
74818
|
+
}
|
|
74819
|
+
const nextMode = normalizeRenderDisplayMode(normalizedArg, state.renderDisplay);
|
|
74820
|
+
return {
|
|
74821
|
+
nextState: { ...state, renderDisplay: nextMode },
|
|
74822
|
+
output: `Render display: ${nextMode}`
|
|
74823
|
+
};
|
|
74824
|
+
}
|
|
73625
74825
|
case "/exit":
|
|
73626
74826
|
case "/quit":
|
|
73627
74827
|
return { nextState: state, output: "Bye.", action: { type: "exit" } };
|
|
@@ -73631,7 +74831,8 @@ function handleTuiInput(input2, state) {
|
|
|
73631
74831
|
...state,
|
|
73632
74832
|
dialogId: void 0,
|
|
73633
74833
|
dialogLabel: "new",
|
|
73634
|
-
attachedDocs: []
|
|
74834
|
+
attachedDocs: [],
|
|
74835
|
+
turnTokens: void 0
|
|
73635
74836
|
},
|
|
73636
74837
|
output: "Started a fresh dialog."
|
|
73637
74838
|
};
|
|
@@ -73655,11 +74856,37 @@ ${renderTuiHelp()}`
|
|
|
73655
74856
|
output: "Compacting current dialog...",
|
|
73656
74857
|
action: { type: "compact", dialogId: state.dialogId }
|
|
73657
74858
|
};
|
|
73658
|
-
case "/agent":
|
|
73659
|
-
|
|
73660
|
-
|
|
73661
|
-
|
|
73662
|
-
|
|
74859
|
+
case "/agent": {
|
|
74860
|
+
if (!argText) {
|
|
74861
|
+
return {
|
|
74862
|
+
nextState: state,
|
|
74863
|
+
output: "",
|
|
74864
|
+
action: { type: "pick-agent" }
|
|
74865
|
+
};
|
|
74866
|
+
}
|
|
74867
|
+
if (argText === "list") {
|
|
74868
|
+
return {
|
|
74869
|
+
nextState: state,
|
|
74870
|
+
output: "",
|
|
74871
|
+
action: { type: "list-agents" }
|
|
74872
|
+
};
|
|
74873
|
+
}
|
|
74874
|
+
if (argText === "current" || argText === "show") {
|
|
74875
|
+
return {
|
|
74876
|
+
nextState: state,
|
|
74877
|
+
output: `Current agent: ${state.agentName} (${state.agentKey})`
|
|
74878
|
+
};
|
|
74879
|
+
}
|
|
74880
|
+
const resolvedTarget = resolveAgentSwitchTarget(argText, PLATFORM_AGENTS);
|
|
74881
|
+
if (!resolvedTarget) {
|
|
74882
|
+
return {
|
|
74883
|
+
nextState: state,
|
|
74884
|
+
output: `I don't know agent "${argText}" yet.
|
|
74885
|
+
Use /agent, /agent list, /agent minimax-m3, or a full agent key.`
|
|
74886
|
+
};
|
|
74887
|
+
}
|
|
74888
|
+
return applyAgentSwitch(state, resolvedTarget);
|
|
74889
|
+
}
|
|
73663
74890
|
case "/agents":
|
|
73664
74891
|
return {
|
|
73665
74892
|
nextState: state,
|
|
@@ -73669,25 +74896,18 @@ ${renderTuiHelp()}`
|
|
|
73669
74896
|
if (!argText) {
|
|
73670
74897
|
return {
|
|
73671
74898
|
nextState: state,
|
|
73672
|
-
output: "Usage: /switch <agent-key|alias>"
|
|
74899
|
+
output: "Usage: /switch <agent-key|alias> (or run /agent)"
|
|
73673
74900
|
};
|
|
73674
74901
|
}
|
|
73675
|
-
const resolvedTarget =
|
|
74902
|
+
const resolvedTarget = resolveAgentSwitchTarget(argText, PLATFORM_AGENTS);
|
|
73676
74903
|
if (!resolvedTarget) {
|
|
73677
74904
|
return {
|
|
73678
74905
|
nextState: state,
|
|
73679
74906
|
output: `I don't know agent shortcut "${argText}" yet.
|
|
73680
|
-
Use /switch nolo, /switch
|
|
74907
|
+
Use /agent, /switch nolo, /switch minimax-m3, or a full agent key.`
|
|
73681
74908
|
};
|
|
73682
74909
|
}
|
|
73683
|
-
return
|
|
73684
|
-
nextState: {
|
|
73685
|
-
...state,
|
|
73686
|
-
agentName: resolvedTarget.name,
|
|
73687
|
-
agentKey: resolvedTarget.key
|
|
73688
|
-
},
|
|
73689
|
-
output: `Switched to ${resolvedTarget.name}.`
|
|
73690
|
-
};
|
|
74910
|
+
return applyAgentSwitch(state, resolvedTarget);
|
|
73691
74911
|
}
|
|
73692
74912
|
case "/dialog":
|
|
73693
74913
|
return {
|
|
@@ -73758,8 +74978,14 @@ async function runAgentChat(scriptDir, state, message, env, output2, agentRunner
|
|
|
73758
74978
|
message,
|
|
73759
74979
|
continueDialogId: state.dialogId,
|
|
73760
74980
|
runtimeMode: state.runtimeMode,
|
|
74981
|
+
localRuntimeCwd: process.cwd(),
|
|
73761
74982
|
scriptDir,
|
|
73762
|
-
env
|
|
74983
|
+
env: {
|
|
74984
|
+
...env,
|
|
74985
|
+
NOLO_CLI_THINKING: state.thinkingDisplay,
|
|
74986
|
+
NOLO_CLI_TOOLS: state.toolDisplay,
|
|
74987
|
+
NOLO_CLI_RENDER: state.renderDisplay
|
|
74988
|
+
},
|
|
73763
74989
|
output: output2
|
|
73764
74990
|
});
|
|
73765
74991
|
return result;
|
|
@@ -73785,6 +75011,19 @@ async function runCliCommandInChildProcess(args2, context) {
|
|
|
73785
75011
|
]);
|
|
73786
75012
|
return proc.exited;
|
|
73787
75013
|
}
|
|
75014
|
+
function persistAgentSelection(state, env) {
|
|
75015
|
+
try {
|
|
75016
|
+
saveProfileAgentSelection({
|
|
75017
|
+
agentKey: state.agentKey,
|
|
75018
|
+
agentName: state.agentName
|
|
75019
|
+
});
|
|
75020
|
+
} catch {
|
|
75021
|
+
}
|
|
75022
|
+
if (env) {
|
|
75023
|
+
env.NOLO_AGENT = state.agentKey;
|
|
75024
|
+
env.NOLO_AGENT_NAME = state.agentName;
|
|
75025
|
+
}
|
|
75026
|
+
}
|
|
73788
75027
|
async function startTuiWorkspace(options) {
|
|
73789
75028
|
let state = createInitialTuiState(options.env ?? process.env);
|
|
73790
75029
|
const input2 = options.input ?? defaultInput;
|
|
@@ -73798,12 +75037,19 @@ async function startTuiWorkspace(options) {
|
|
|
73798
75037
|
rl.prompt();
|
|
73799
75038
|
try {
|
|
73800
75039
|
for await (const line of rl) {
|
|
75040
|
+
if (!line.trim()) {
|
|
75041
|
+
continue;
|
|
75042
|
+
}
|
|
73801
75043
|
const result = handleTuiInput(line, state);
|
|
75044
|
+
const previousAgentKey = state.agentKey;
|
|
73802
75045
|
state = result.nextState;
|
|
73803
75046
|
if (result.output) {
|
|
73804
75047
|
output2.write(`${result.output}
|
|
73805
75048
|
`);
|
|
73806
75049
|
}
|
|
75050
|
+
if (state.agentKey !== previousAgentKey && result.output?.startsWith("Switched to ")) {
|
|
75051
|
+
persistAgentSelection(state, options.env ?? process.env);
|
|
75052
|
+
}
|
|
73807
75053
|
if (result.action?.type === "exit") {
|
|
73808
75054
|
break;
|
|
73809
75055
|
}
|
|
@@ -73842,6 +75088,64 @@ async function startTuiWorkspace(options) {
|
|
|
73842
75088
|
output2.write("Update failed. Check the error above, then run /update again or use nolo update.\n");
|
|
73843
75089
|
}
|
|
73844
75090
|
}
|
|
75091
|
+
if (result.action?.type === "pick-agent") {
|
|
75092
|
+
rl.pause();
|
|
75093
|
+
try {
|
|
75094
|
+
const pickResult = await runAgentPicker({
|
|
75095
|
+
currentKey: state.agentKey,
|
|
75096
|
+
env: options.env ?? process.env,
|
|
75097
|
+
input: input2,
|
|
75098
|
+
output: output2
|
|
75099
|
+
});
|
|
75100
|
+
if (pickResult.kind === "list") {
|
|
75101
|
+
output2.write(`${pickResult.output}
|
|
75102
|
+
`);
|
|
75103
|
+
} else if (pickResult.kind === "selected") {
|
|
75104
|
+
state = {
|
|
75105
|
+
...state,
|
|
75106
|
+
agentName: pickResult.name,
|
|
75107
|
+
agentKey: pickResult.key
|
|
75108
|
+
};
|
|
75109
|
+
persistAgentSelection(state, options.env ?? process.env);
|
|
75110
|
+
output2.write(
|
|
75111
|
+
`${formatAgentSwitchMessage({
|
|
75112
|
+
name: pickResult.name,
|
|
75113
|
+
dialogId: state.dialogId
|
|
75114
|
+
})}
|
|
75115
|
+
`
|
|
75116
|
+
);
|
|
75117
|
+
} else {
|
|
75118
|
+
output2.write("Agent switch cancelled.\n");
|
|
75119
|
+
}
|
|
75120
|
+
} catch (error) {
|
|
75121
|
+
output2.write(
|
|
75122
|
+
`[nolo] Agent picker failed: ${error instanceof Error ? error.message : String(error)}
|
|
75123
|
+
`
|
|
75124
|
+
);
|
|
75125
|
+
} finally {
|
|
75126
|
+
rl.resume();
|
|
75127
|
+
}
|
|
75128
|
+
}
|
|
75129
|
+
if (result.action?.type === "list-agents") {
|
|
75130
|
+
try {
|
|
75131
|
+
const pickResult = await runAgentPicker({
|
|
75132
|
+
currentKey: state.agentKey,
|
|
75133
|
+
env: options.env ?? process.env,
|
|
75134
|
+
input: input2,
|
|
75135
|
+
output: output2,
|
|
75136
|
+
interactive: false
|
|
75137
|
+
});
|
|
75138
|
+
if (pickResult.kind === "list") {
|
|
75139
|
+
output2.write(`${pickResult.output}
|
|
75140
|
+
`);
|
|
75141
|
+
}
|
|
75142
|
+
} catch (error) {
|
|
75143
|
+
output2.write(
|
|
75144
|
+
`[nolo] Agent list failed: ${error instanceof Error ? error.message : String(error)}
|
|
75145
|
+
`
|
|
75146
|
+
);
|
|
75147
|
+
}
|
|
75148
|
+
}
|
|
73845
75149
|
if (result.action?.type === "cli-command") {
|
|
73846
75150
|
try {
|
|
73847
75151
|
const exitCode2 = await cliCommandRunner(result.action.args, {
|
|
@@ -73870,11 +75174,14 @@ async function startTuiWorkspace(options) {
|
|
|
73870
75174
|
output2,
|
|
73871
75175
|
options.agentRunner
|
|
73872
75176
|
);
|
|
73873
|
-
if (runResult.dialogId) {
|
|
75177
|
+
if (runResult.dialogId || runResult.turnTokens) {
|
|
73874
75178
|
state = {
|
|
73875
75179
|
...state,
|
|
73876
|
-
|
|
73877
|
-
|
|
75180
|
+
...runResult.dialogId ? {
|
|
75181
|
+
dialogId: runResult.dialogId,
|
|
75182
|
+
dialogLabel: runResult.dialogId
|
|
75183
|
+
} : {},
|
|
75184
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
73878
75185
|
};
|
|
73879
75186
|
}
|
|
73880
75187
|
}
|