nolo-cli 0.1.46 → 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 +2174 -354
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1443,6 +1443,15 @@ var init_agentAliases = __esm({
|
|
|
1443
1443
|
nolo: NOLO_DEFAULT_AGENT_KEY,
|
|
1444
1444
|
default: NOLO_DEFAULT_AGENT_KEY,
|
|
1445
1445
|
"default-nolo": NOLO_DEFAULT_AGENT_KEY,
|
|
1446
|
+
// Product implementation & coordination aliases
|
|
1447
|
+
"frontend-implementer": NOLO_FRONTEND_AGENT_KEY,
|
|
1448
|
+
"frontend-agent": NOLO_FRONTEND_AGENT_KEY,
|
|
1449
|
+
frontend: NOLO_FRONTEND_AGENT_KEY,
|
|
1450
|
+
"frontend agent": NOLO_FRONTEND_AGENT_KEY,
|
|
1451
|
+
"\u524D\u7AEFagent": NOLO_FRONTEND_AGENT_KEY,
|
|
1452
|
+
"\u524D\u7AEF agent": NOLO_FRONTEND_AGENT_KEY,
|
|
1453
|
+
"project-manager": NOLO_PROJECT_MANAGER_AGENT_KEY,
|
|
1454
|
+
pm: NOLO_PROJECT_MANAGER_AGENT_KEY,
|
|
1446
1455
|
// Explicit local CLI agents. These are ordinary private agent records that
|
|
1447
1456
|
// run through the current computer local runtime when unbound.
|
|
1448
1457
|
"local-codex": LOCAL_CODEX_AGENT_KEY,
|
|
@@ -1464,7 +1473,9 @@ var init_agentAliases = __esm({
|
|
|
1464
1473
|
grok: LOCAL_GROK_AGENT_KEY,
|
|
1465
1474
|
"grok-agent": LOCAL_GROK_AGENT_KEY,
|
|
1466
1475
|
"grok cli": LOCAL_GROK_AGENT_KEY,
|
|
1467
|
-
"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"
|
|
1468
1479
|
};
|
|
1469
1480
|
}
|
|
1470
1481
|
});
|
|
@@ -1593,6 +1604,19 @@ function buildMessages(args2) {
|
|
|
1593
1604
|
{ role: "user", content: args2.input }
|
|
1594
1605
|
];
|
|
1595
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
|
+
}
|
|
1596
1620
|
function extractUserInputText(content) {
|
|
1597
1621
|
if (typeof content === "string") return content;
|
|
1598
1622
|
if (!Array.isArray(content)) return "";
|
|
@@ -1618,11 +1642,14 @@ async function runLocalAgentTurn(input2) {
|
|
|
1618
1642
|
const userInputText = extractUserInputText(input2.input);
|
|
1619
1643
|
let toolCallCount = 0;
|
|
1620
1644
|
let result;
|
|
1645
|
+
let turnUsage;
|
|
1621
1646
|
let round = 0;
|
|
1622
1647
|
while (true) {
|
|
1623
1648
|
result = await provider.complete(messages, {
|
|
1624
|
-
...typeof input2.timeoutMs === "number" ? { timeoutMs: input2.timeoutMs } : {}
|
|
1649
|
+
...typeof input2.timeoutMs === "number" ? { timeoutMs: input2.timeoutMs } : {},
|
|
1650
|
+
...input2.onTextDelta ? { onTextDelta: input2.onTextDelta } : {}
|
|
1625
1651
|
});
|
|
1652
|
+
turnUsage = mergeTurnUsage(turnUsage, result.usage);
|
|
1626
1653
|
const toolCalls = result.tool_calls ?? [];
|
|
1627
1654
|
if (toolCalls.length === 0) break;
|
|
1628
1655
|
toolCallCount += toolCalls.length;
|
|
@@ -1715,6 +1742,7 @@ async function runLocalAgentTurn(input2) {
|
|
|
1715
1742
|
});
|
|
1716
1743
|
return {
|
|
1717
1744
|
...result,
|
|
1745
|
+
...turnUsage ? { usage: turnUsage } : {},
|
|
1718
1746
|
...toolCallCount > 0 ? { toolCallCount } : {},
|
|
1719
1747
|
...agentConfig.toolSurface ? { runtimeToolSurface: agentConfig.toolSurface } : {},
|
|
1720
1748
|
dialogId: saved.dialogId,
|
|
@@ -3350,9 +3378,10 @@ function buildOpenAiCompatibleChatCompletionRequest(args2) {
|
|
|
3350
3378
|
const body = {
|
|
3351
3379
|
model: args2.providerConfig.model,
|
|
3352
3380
|
messages: toOpenAiCompatibleMessages(args2.messages),
|
|
3353
|
-
stream: false,
|
|
3381
|
+
stream: args2.stream ?? false,
|
|
3354
3382
|
...args2.providerConfig.requestOptions,
|
|
3355
|
-
...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 } } : {}
|
|
3356
3385
|
};
|
|
3357
3386
|
return {
|
|
3358
3387
|
url: args2.providerConfig.endpoint,
|
|
@@ -3382,6 +3411,138 @@ function parseOpenAiCompatibleChatCompletionResponse(args2) {
|
|
|
3382
3411
|
trace: args2.trace
|
|
3383
3412
|
};
|
|
3384
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
|
+
}
|
|
3385
3546
|
var init_openAiCompatibleProvider = __esm({
|
|
3386
3547
|
"packages/agent-runtime/openAiCompatibleProvider.ts"() {
|
|
3387
3548
|
"use strict";
|
|
@@ -3679,7 +3840,8 @@ function buildPlatformChatCompletionRequest(args2) {
|
|
|
3679
3840
|
const body = {
|
|
3680
3841
|
model: args2.providerConfig.model,
|
|
3681
3842
|
...usesResponsesApi ? { input: convertMessagesToResponsesInput(args2.messages) } : { messages: toOpenAiCompatibleMessages2(args2.messages) },
|
|
3682
|
-
stream: false,
|
|
3843
|
+
stream: args2.stream ?? false,
|
|
3844
|
+
...args2.stream ? { stream_options: { include_usage: true } } : {},
|
|
3683
3845
|
...requestOptions,
|
|
3684
3846
|
...args2.tools && args2.tools.length > 0 ? {
|
|
3685
3847
|
tools: usesResponsesApi ? toResponsesTools(args2.tools) : args2.tools,
|
|
@@ -10109,6 +10271,8 @@ var init_ai_locale = __esm({
|
|
|
10109
10271
|
creating: "Creating...",
|
|
10110
10272
|
edit: "Edit",
|
|
10111
10273
|
delete: "Delete",
|
|
10274
|
+
favorite: "Favorite",
|
|
10275
|
+
unfavorite: "Unfavorite",
|
|
10112
10276
|
confirmDelete: "Confirm Delete",
|
|
10113
10277
|
resetToDefaults: "Reset to Defaults",
|
|
10114
10278
|
loading: "Loading...",
|
|
@@ -10420,6 +10584,8 @@ var init_ai_locale = __esm({
|
|
|
10420
10584
|
creating: "\u521B\u5EFA\u4E2D...",
|
|
10421
10585
|
edit: "\u7F16\u8F91",
|
|
10422
10586
|
delete: "\u5220\u9664",
|
|
10587
|
+
favorite: "\u6536\u85CF",
|
|
10588
|
+
unfavorite: "\u53D6\u6D88\u6536\u85CF",
|
|
10423
10589
|
confirmDelete: "\u786E\u8BA4\u5220\u9664",
|
|
10424
10590
|
resetToDefaults: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u503C",
|
|
10425
10591
|
loading: "\u52A0\u8F7D\u4E2D...",
|
|
@@ -10732,6 +10898,8 @@ var init_ai_locale = __esm({
|
|
|
10732
10898
|
creating: "\u5EFA\u7ACB\u4E2D...",
|
|
10733
10899
|
edit: "\u7DE8\u8F2F",
|
|
10734
10900
|
delete: "\u522A\u9664",
|
|
10901
|
+
favorite: "\u6536\u85CF",
|
|
10902
|
+
unfavorite: "\u53D6\u6D88\u6536\u85CF",
|
|
10735
10903
|
confirmDelete: "\u78BA\u8A8D\u522A\u9664",
|
|
10736
10904
|
resetToDefaults: "\u91CD\u8A2D\u70BA\u9810\u8A2D\u503C",
|
|
10737
10905
|
loading: "\u8F09\u5165\u4E2D...",
|
|
@@ -10967,6 +11135,8 @@ var init_ai_locale = __esm({
|
|
|
10967
11135
|
creating: "\u4F5C\u6210\u4E2D...",
|
|
10968
11136
|
edit: "\u7DE8\u96C6",
|
|
10969
11137
|
delete: "\u524A\u9664",
|
|
11138
|
+
favorite: "\u304A\u6C17\u306B\u5165\u308A",
|
|
11139
|
+
unfavorite: "\u304A\u6C17\u306B\u5165\u308A\u89E3\u9664",
|
|
10970
11140
|
confirmDelete: "\u524A\u9664\u306E\u78BA\u8A8D",
|
|
10971
11141
|
resetToDefaults: "\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u30EA\u30BB\u30C3\u30C8",
|
|
10972
11142
|
loading: "\u8AAD\u307F\u8FBC\u307F\u4E2D...",
|
|
@@ -13042,6 +13212,31 @@ var init_interface_locale = __esm({
|
|
|
13042
13212
|
stop: "Stop",
|
|
13043
13213
|
refresh: "Refresh"
|
|
13044
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
|
+
},
|
|
13045
13240
|
appearance: {
|
|
13046
13241
|
title: "Appearance",
|
|
13047
13242
|
theme: {
|
|
@@ -13735,6 +13930,31 @@ var init_interface_locale = __esm({
|
|
|
13735
13930
|
productivity: "\u6548\u7387",
|
|
13736
13931
|
secrets: "\u5BC6\u94A5"
|
|
13737
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
|
+
},
|
|
13738
13958
|
appearance: {
|
|
13739
13959
|
title: "\u5916\u89C2",
|
|
13740
13960
|
theme: {
|
|
@@ -14429,6 +14649,31 @@ var init_interface_locale = __esm({
|
|
|
14429
14649
|
productivity: "\u6548\u7387",
|
|
14430
14650
|
secrets: "\u5BC6\u9470"
|
|
14431
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
|
+
},
|
|
14432
14677
|
appearance: {
|
|
14433
14678
|
title: "\u5916\u89C0",
|
|
14434
14679
|
theme: {
|
|
@@ -15121,6 +15366,31 @@ var init_interface_locale = __esm({
|
|
|
15121
15366
|
productivity: "\u52B9\u7387",
|
|
15122
15367
|
secrets: "\u30B7\u30FC\u30AF\u30EC\u30C3\u30C8"
|
|
15123
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
|
+
},
|
|
15124
15394
|
appearance: {
|
|
15125
15395
|
title: "\u5916\u89B3",
|
|
15126
15396
|
theme: {
|
|
@@ -19818,7 +20088,7 @@ var init_userPreferenceRegister = __esm({
|
|
|
19818
20088
|
});
|
|
19819
20089
|
|
|
19820
20090
|
// packages/app/theme/colors.ts
|
|
19821
|
-
var semantic, mkLight, mkDark, neutral, ocean, iris, forest, trail, wave, rose, ember, blue, purple, green, graphite, mocha, pink, red, orange, yellow;
|
|
20091
|
+
var semantic, mkLight, mkDark, neutral, ocean, iris, forest, trail, wave, rose, ember, catppuccin, blue, purple, green, graphite, mocha, pink, red, orange, yellow;
|
|
19822
20092
|
var init_colors = __esm({
|
|
19823
20093
|
"packages/app/theme/colors.ts"() {
|
|
19824
20094
|
"use strict";
|
|
@@ -19847,7 +20117,8 @@ var init_colors = __esm({
|
|
|
19847
20117
|
codeBackground: bg3,
|
|
19848
20118
|
shadowLight: `rgba(0,0,0,0.04)`,
|
|
19849
20119
|
shadowMedium: `rgba(0,0,0,0.08)`,
|
|
19850
|
-
shadowHeavy: `rgba(0,0,0,0.14)
|
|
20120
|
+
shadowHeavy: `rgba(0,0,0,0.14)`,
|
|
20121
|
+
textOnPrimary: "#FFFFFF"
|
|
19851
20122
|
});
|
|
19852
20123
|
mkDark = (bg, bg2, bg3, textPrimary, textSec, textTer, border, borderL, shadowBase = "0,0,0") => ({
|
|
19853
20124
|
background: bg,
|
|
@@ -19870,7 +20141,8 @@ var init_colors = __esm({
|
|
|
19870
20141
|
codeBackground: bg2,
|
|
19871
20142
|
shadowLight: `rgba(${shadowBase},0.18)`,
|
|
19872
20143
|
shadowMedium: `rgba(${shadowBase},0.30)`,
|
|
19873
|
-
shadowHeavy: `rgba(${shadowBase},0.44)
|
|
20144
|
+
shadowHeavy: `rgba(${shadowBase},0.44)`,
|
|
20145
|
+
textOnPrimary: "#FFFFFF"
|
|
19874
20146
|
});
|
|
19875
20147
|
neutral = {
|
|
19876
20148
|
light: {
|
|
@@ -19881,7 +20153,8 @@ var init_colors = __esm({
|
|
|
19881
20153
|
primaryGhost: "rgba(113,113,122,0.08)",
|
|
19882
20154
|
primaryHover: "rgba(113,113,122,0.10)",
|
|
19883
20155
|
borderAccent: "#D4D4D8",
|
|
19884
|
-
...semantic.light
|
|
20156
|
+
...semantic.light,
|
|
20157
|
+
...mkLight("#FFFFFF", "#F4F4F5", "#E4E4E7", "#18181B", "#52525B", "#71717A", "#E4E4E7", "#F4F4F5")
|
|
19885
20158
|
},
|
|
19886
20159
|
dark: {
|
|
19887
20160
|
primary: "#A1A1AA",
|
|
@@ -19891,7 +20164,9 @@ var init_colors = __esm({
|
|
|
19891
20164
|
primaryGhost: "rgba(161,161,170,0.10)",
|
|
19892
20165
|
primaryHover: "rgba(161,161,170,0.12)",
|
|
19893
20166
|
borderAccent: "#52525B",
|
|
19894
|
-
...semantic.dark
|
|
20167
|
+
...semantic.dark,
|
|
20168
|
+
...mkDark("#18181B", "#27272A", "#3F3F46", "#FAFAFA", "#D4D4D8", "#A1A1AA", "#3F3F46", "#27272A", "24,24,27"),
|
|
20169
|
+
textOnPrimary: "#18181B"
|
|
19895
20170
|
}
|
|
19896
20171
|
};
|
|
19897
20172
|
ocean = {
|
|
@@ -19916,7 +20191,8 @@ var init_colors = __esm({
|
|
|
19916
20191
|
borderAccent: "#1F6FEB",
|
|
19917
20192
|
...semantic.dark,
|
|
19918
20193
|
...mkDark("#0D1117", "#161B22", "#21262D", "#E6EDF3", "#8B949E", "#6E7681", "#30363D", "#161B22", "13,17,23"),
|
|
19919
|
-
textHeading: "#E6EDF3"
|
|
20194
|
+
textHeading: "#E6EDF3",
|
|
20195
|
+
textOnPrimary: "#0D1117"
|
|
19920
20196
|
}
|
|
19921
20197
|
};
|
|
19922
20198
|
iris = {
|
|
@@ -19941,7 +20217,8 @@ var init_colors = __esm({
|
|
|
19941
20217
|
borderAccent: "#4A55C0",
|
|
19942
20218
|
...semantic.dark,
|
|
19943
20219
|
...mkDark("#0F0E17", "#16141F", "#1E1B2E", "#E8E5F7", "#A8A4C8", "#7B7698", "#272435", "#16141F", "15,14,23"),
|
|
19944
|
-
textHeading: "#E8E5F7"
|
|
20220
|
+
textHeading: "#E8E5F7",
|
|
20221
|
+
textOnPrimary: "#0F0E17"
|
|
19945
20222
|
}
|
|
19946
20223
|
};
|
|
19947
20224
|
forest = {
|
|
@@ -19967,10 +20244,12 @@ var init_colors = __esm({
|
|
|
19967
20244
|
...semantic.dark,
|
|
19968
20245
|
...mkDark("#0C1209", "#121A0E", "#1A2416", "#E4F0E2", "#87A882", "#5E7A5A", "#1A2416", "#121A0E", "12,18,9"),
|
|
19969
20246
|
success: "#4ADE80",
|
|
19970
|
-
textHeading: "#C8EEC4"
|
|
20247
|
+
textHeading: "#C8EEC4",
|
|
20248
|
+
textOnPrimary: "#0C1209"
|
|
19971
20249
|
}
|
|
19972
20250
|
};
|
|
19973
20251
|
trail = {
|
|
20252
|
+
meta: { radiusBoost: 1, motionEase: "cubic-bezier(0.22, 1, 0.36, 1)" },
|
|
19974
20253
|
light: {
|
|
19975
20254
|
primary: "#2E7DB5",
|
|
19976
20255
|
primaryLight: "#6BB5E0",
|
|
@@ -20007,7 +20286,8 @@ var init_colors = __esm({
|
|
|
20007
20286
|
shadowLight: "rgba(28, 36, 48, 0.05)",
|
|
20008
20287
|
shadowMedium: "rgba(28, 36, 48, 0.09)",
|
|
20009
20288
|
shadowHeavy: "rgba(28, 36, 48, 0.14)",
|
|
20010
|
-
textHeading: "#1C2430"
|
|
20289
|
+
textHeading: "#1C2430",
|
|
20290
|
+
textOnPrimary: "#FFFFFF"
|
|
20011
20291
|
},
|
|
20012
20292
|
dark: {
|
|
20013
20293
|
primary: "#5BA3D9",
|
|
@@ -20045,7 +20325,8 @@ var init_colors = __esm({
|
|
|
20045
20325
|
shadowLight: "rgba(4, 8, 12, 0.22)",
|
|
20046
20326
|
shadowMedium: "rgba(4, 8, 12, 0.34)",
|
|
20047
20327
|
shadowHeavy: "rgba(4, 8, 12, 0.46)",
|
|
20048
|
-
textHeading: "#E8F4FC"
|
|
20328
|
+
textHeading: "#E8F4FC",
|
|
20329
|
+
textOnPrimary: "#0B1218"
|
|
20049
20330
|
}
|
|
20050
20331
|
};
|
|
20051
20332
|
wave = {
|
|
@@ -20082,7 +20363,8 @@ var init_colors = __esm({
|
|
|
20082
20363
|
codeBackground: "#ECEAE3",
|
|
20083
20364
|
shadowLight: "rgba(26, 26, 34, 0.05)",
|
|
20084
20365
|
shadowMedium: "rgba(26, 26, 34, 0.09)",
|
|
20085
|
-
shadowHeavy: "rgba(26, 26, 34, 0.14)"
|
|
20366
|
+
shadowHeavy: "rgba(26, 26, 34, 0.14)",
|
|
20367
|
+
textOnPrimary: "#FFFFFF"
|
|
20086
20368
|
},
|
|
20087
20369
|
dark: {
|
|
20088
20370
|
// Kanagawa Wave — crystalBlue accent(#7E9CD8 是函数名颜色,最标志性的 Kanagawa 蓝)
|
|
@@ -20129,8 +20411,9 @@ var init_colors = __esm({
|
|
|
20129
20411
|
shadowLight: "rgba(13, 12, 12, 0.18)",
|
|
20130
20412
|
shadowMedium: "rgba(13, 12, 12, 0.28)",
|
|
20131
20413
|
shadowHeavy: "rgba(13, 12, 12, 0.38)",
|
|
20132
|
-
textHeading: "#DCD7BA"
|
|
20414
|
+
textHeading: "#DCD7BA",
|
|
20133
20415
|
// fujiWhite — 暖色标题
|
|
20416
|
+
textOnPrimary: "#1F1F28"
|
|
20134
20417
|
}
|
|
20135
20418
|
};
|
|
20136
20419
|
rose = {
|
|
@@ -20166,7 +20449,8 @@ var init_colors = __esm({
|
|
|
20166
20449
|
codeBackground: "#F2E9E1",
|
|
20167
20450
|
shadowLight: "rgba(87, 82, 121, 0.05)",
|
|
20168
20451
|
shadowMedium: "rgba(87, 82, 121, 0.09)",
|
|
20169
|
-
shadowHeavy: "rgba(87, 82, 121, 0.14)"
|
|
20452
|
+
shadowHeavy: "rgba(87, 82, 121, 0.14)",
|
|
20453
|
+
textOnPrimary: "#FFFFFF"
|
|
20170
20454
|
},
|
|
20171
20455
|
dark: {
|
|
20172
20456
|
// Rosé Pine main
|
|
@@ -20201,7 +20485,8 @@ var init_colors = __esm({
|
|
|
20201
20485
|
shadowLight: "rgba(12, 10, 20, 0.20)",
|
|
20202
20486
|
shadowMedium: "rgba(12, 10, 20, 0.30)",
|
|
20203
20487
|
shadowHeavy: "rgba(12, 10, 20, 0.44)",
|
|
20204
|
-
textHeading: "#E0DEF4"
|
|
20488
|
+
textHeading: "#E0DEF4",
|
|
20489
|
+
textOnPrimary: "#191724"
|
|
20205
20490
|
}
|
|
20206
20491
|
};
|
|
20207
20492
|
ember = {
|
|
@@ -20226,14 +20511,54 @@ var init_colors = __esm({
|
|
|
20226
20511
|
borderAccent: "#92400E",
|
|
20227
20512
|
...semantic.dark,
|
|
20228
20513
|
...mkDark("#1A1207", "#221809", "#2E220C", "#F0E2C0", "#C4A056", "#8A7040", "#3A2A10", "#221809", "26,18,7"),
|
|
20229
|
-
textHeading: "#FCD34D"
|
|
20514
|
+
textHeading: "#FCD34D",
|
|
20515
|
+
textOnPrimary: "#1A1207"
|
|
20516
|
+
}
|
|
20517
|
+
};
|
|
20518
|
+
catppuccin = {
|
|
20519
|
+
light: {
|
|
20520
|
+
// Catppuccin Latte
|
|
20521
|
+
primary: "#1e66f5",
|
|
20522
|
+
// Blue
|
|
20523
|
+
primaryLight: "#89b4fa",
|
|
20524
|
+
// Blue Light
|
|
20525
|
+
primaryDark: "#4c4f69",
|
|
20526
|
+
// Text
|
|
20527
|
+
primaryGradient: "linear-gradient(135deg, #1e66f5, #89b4fa)",
|
|
20528
|
+
primaryGhost: "rgba(30, 102, 245, 0.08)",
|
|
20529
|
+
primaryHover: "rgba(30, 102, 245, 0.10)",
|
|
20530
|
+
borderAccent: "#ccd0da",
|
|
20531
|
+
success: "#40a02b",
|
|
20532
|
+
warning: "#df8e1d",
|
|
20533
|
+
info: "#1e66f5",
|
|
20534
|
+
error: "#d20f39",
|
|
20535
|
+
...mkLight("#eff1f5", "#e6e9ef", "#dce0e8", "#4c4f69", "#5c5f77", "#6c6f85", "#ccd0da", "#e6e9ef")
|
|
20536
|
+
},
|
|
20537
|
+
dark: {
|
|
20538
|
+
// Catppuccin Mocha
|
|
20539
|
+
primary: "#89b4fa",
|
|
20540
|
+
// Blue
|
|
20541
|
+
primaryLight: "#b4befe",
|
|
20542
|
+
// Lavender
|
|
20543
|
+
primaryDark: "#1e66f5",
|
|
20544
|
+
primaryGradient: "linear-gradient(135deg, #89b4fa, #b4befe)",
|
|
20545
|
+
primaryGhost: "rgba(137, 180, 250, 0.10)",
|
|
20546
|
+
primaryHover: "rgba(137, 180, 250, 0.14)",
|
|
20547
|
+
borderAccent: "#313244",
|
|
20548
|
+
success: "#a6e3a1",
|
|
20549
|
+
warning: "#f9e2af",
|
|
20550
|
+
info: "#89b4fa",
|
|
20551
|
+
error: "#f38ba8",
|
|
20552
|
+
...mkDark("#1e1e2e", "#181825", "#11111b", "#cdd6f4", "#bac2de", "#a6adc8", "#313244", "#181825", "30,30,46"),
|
|
20553
|
+
textHeading: "#f5e0dc",
|
|
20554
|
+
textOnPrimary: "#11111b"
|
|
20230
20555
|
}
|
|
20231
20556
|
};
|
|
20232
20557
|
blue = ocean;
|
|
20233
20558
|
purple = iris;
|
|
20234
20559
|
green = forest;
|
|
20235
20560
|
graphite = neutral;
|
|
20236
|
-
mocha =
|
|
20561
|
+
mocha = catppuccin;
|
|
20237
20562
|
pink = rose;
|
|
20238
20563
|
red = ember;
|
|
20239
20564
|
orange = ember;
|
|
@@ -20242,7 +20567,7 @@ var init_colors = __esm({
|
|
|
20242
20567
|
});
|
|
20243
20568
|
|
|
20244
20569
|
// packages/app/theme/theme.config.ts
|
|
20245
|
-
var SPACE, THEME_COLORS, THEME_NAME_ALIASES, DEFAULT_THEME_NAME
|
|
20570
|
+
var SPACE, THEME_COLORS, THEME_NAME_ALIASES, DEFAULT_THEME_NAME;
|
|
20246
20571
|
var init_theme_config = __esm({
|
|
20247
20572
|
"packages/app/theme/theme.config.ts"() {
|
|
20248
20573
|
"use strict";
|
|
@@ -20273,6 +20598,7 @@ var init_theme_config = __esm({
|
|
|
20273
20598
|
wave,
|
|
20274
20599
|
rose,
|
|
20275
20600
|
ember,
|
|
20601
|
+
catppuccin,
|
|
20276
20602
|
// alias — DB 中可能存了旧 key,映射到最近似的新主题
|
|
20277
20603
|
blue,
|
|
20278
20604
|
purple,
|
|
@@ -20285,7 +20611,8 @@ var init_theme_config = __esm({
|
|
|
20285
20611
|
mocha
|
|
20286
20612
|
};
|
|
20287
20613
|
THEME_NAME_ALIASES = {
|
|
20288
|
-
blue: "
|
|
20614
|
+
blue: "catppuccin",
|
|
20615
|
+
ocean: "catppuccin",
|
|
20289
20616
|
purple: "iris",
|
|
20290
20617
|
green: "forest",
|
|
20291
20618
|
orange: "ember",
|
|
@@ -20293,86 +20620,9 @@ var init_theme_config = __esm({
|
|
|
20293
20620
|
graphite: "neutral",
|
|
20294
20621
|
pink: "rose",
|
|
20295
20622
|
red: "ember",
|
|
20296
|
-
mocha: "
|
|
20623
|
+
mocha: "catppuccin"
|
|
20297
20624
|
};
|
|
20298
|
-
DEFAULT_THEME_NAME = "
|
|
20299
|
-
BASE_COLORS = {
|
|
20300
|
-
light: {
|
|
20301
|
-
background: "#FFFFFF",
|
|
20302
|
-
backgroundSecondary: "#F4F4F5",
|
|
20303
|
-
// zinc-100
|
|
20304
|
-
backgroundTertiary: "#E4E4E7",
|
|
20305
|
-
// zinc-200
|
|
20306
|
-
backgroundGhost: "rgba(255, 255, 255, 0.94)",
|
|
20307
|
-
backgroundHover: "#D4D4D8",
|
|
20308
|
-
// zinc-300
|
|
20309
|
-
backgroundSelected: "#A1A1AA",
|
|
20310
|
-
// zinc-400
|
|
20311
|
-
text: "#18181B",
|
|
20312
|
-
// zinc-900
|
|
20313
|
-
textSecondary: "#52525B",
|
|
20314
|
-
// zinc-600
|
|
20315
|
-
textTertiary: "#71717A",
|
|
20316
|
-
// zinc-500
|
|
20317
|
-
textQuaternary: "#A1A1AA",
|
|
20318
|
-
// zinc-400
|
|
20319
|
-
textLight: "#D4D4D8",
|
|
20320
|
-
// zinc-300
|
|
20321
|
-
placeholder: "#A1A1AA",
|
|
20322
|
-
// zinc-400
|
|
20323
|
-
border: "#E4E4E7",
|
|
20324
|
-
// zinc-200
|
|
20325
|
-
borderHover: "#A1A1AA",
|
|
20326
|
-
// zinc-400
|
|
20327
|
-
borderLight: "#F4F4F5",
|
|
20328
|
-
// zinc-100
|
|
20329
|
-
error: "#DC2626",
|
|
20330
|
-
shadowLight: "rgba(0, 0, 0, 0.04)",
|
|
20331
|
-
shadowMedium: "rgba(0, 0, 0, 0.08)",
|
|
20332
|
-
shadowHeavy: "rgba(0, 0, 0, 0.14)",
|
|
20333
|
-
messageBackground: "#FFFFFF",
|
|
20334
|
-
codeBackground: "#F4F4F5"
|
|
20335
|
-
},
|
|
20336
|
-
dark: {
|
|
20337
|
-
background: "#18181B",
|
|
20338
|
-
// zinc-900
|
|
20339
|
-
backgroundSecondary: "#27272A",
|
|
20340
|
-
// zinc-800
|
|
20341
|
-
backgroundTertiary: "#3F3F46",
|
|
20342
|
-
// zinc-700
|
|
20343
|
-
backgroundGhost: "rgba(24, 24, 27, 0.94)",
|
|
20344
|
-
backgroundHover: "#52525B",
|
|
20345
|
-
// zinc-600
|
|
20346
|
-
backgroundSelected: "#3F3F46",
|
|
20347
|
-
// zinc-700
|
|
20348
|
-
text: "#FAFAFA",
|
|
20349
|
-
// zinc-50
|
|
20350
|
-
textSecondary: "#D4D4D8",
|
|
20351
|
-
// zinc-300
|
|
20352
|
-
textTertiary: "#A1A1AA",
|
|
20353
|
-
// zinc-400
|
|
20354
|
-
textQuaternary: "#71717A",
|
|
20355
|
-
// zinc-500
|
|
20356
|
-
textLight: "#52525B",
|
|
20357
|
-
// zinc-600
|
|
20358
|
-
placeholder: "#71717A",
|
|
20359
|
-
// zinc-500
|
|
20360
|
-
border: "#3F3F46",
|
|
20361
|
-
// zinc-700
|
|
20362
|
-
borderHover: "#71717A",
|
|
20363
|
-
// zinc-500
|
|
20364
|
-
borderLight: "#27272A",
|
|
20365
|
-
// zinc-800
|
|
20366
|
-
error: "#F87171",
|
|
20367
|
-
shadowLight: "rgba(0, 0, 0, 0.16)",
|
|
20368
|
-
shadowMedium: "rgba(0, 0, 0, 0.28)",
|
|
20369
|
-
shadowHeavy: "rgba(0, 0, 0, 0.40)",
|
|
20370
|
-
messageBackground: "#27272A",
|
|
20371
|
-
codeBackground: "#09090B"
|
|
20372
|
-
// zinc-950
|
|
20373
|
-
}
|
|
20374
|
-
};
|
|
20375
|
-
MODE_COLORS = BASE_COLORS;
|
|
20625
|
+
DEFAULT_THEME_NAME = "catppuccin";
|
|
20376
20626
|
}
|
|
20377
20627
|
});
|
|
20378
20628
|
|
|
@@ -20779,6 +21029,7 @@ __export(settingSlice_exports, {
|
|
|
20779
21029
|
selectDefaultAgentId: () => selectDefaultAgentId,
|
|
20780
21030
|
selectDefaultAgentPreference: () => selectDefaultAgentPreference,
|
|
20781
21031
|
selectDefaultSpaceId: () => selectDefaultSpaceId,
|
|
21032
|
+
selectDeleteShortcut: () => selectDeleteShortcut,
|
|
20782
21033
|
selectDensity: () => selectDensity,
|
|
20783
21034
|
selectDesktopChromeConnectorEnabled: () => selectDesktopChromeConnectorEnabled,
|
|
20784
21035
|
selectEditorAutoSave: () => selectEditorAutoSave,
|
|
@@ -20847,7 +21098,7 @@ import {
|
|
|
20847
21098
|
asyncThunkCreator,
|
|
20848
21099
|
createSelector as createSelector2
|
|
20849
21100
|
} from "@reduxjs/toolkit";
|
|
20850
|
-
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;
|
|
20851
21102
|
var init_settingSlice = __esm({
|
|
20852
21103
|
"packages/app/settings/settingSlice.tsx"() {
|
|
20853
21104
|
"use strict";
|
|
@@ -20920,7 +21171,8 @@ var init_settingSlice = __esm({
|
|
|
20920
21171
|
showScrollToTopButton: false,
|
|
20921
21172
|
showScrollToBottomButton: false,
|
|
20922
21173
|
createMenuOpenCount: 0,
|
|
20923
|
-
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"
|
|
20924
21176
|
};
|
|
20925
21177
|
createSliceWithThunks = buildCreateSlice({
|
|
20926
21178
|
creators: { asyncThunk: asyncThunkCreator }
|
|
@@ -21548,6 +21800,7 @@ var init_settingSlice = __esm({
|
|
|
21548
21800
|
);
|
|
21549
21801
|
selectEditorWordCountEnabled = (state) => state.settings.editorWordCountEnabled;
|
|
21550
21802
|
selectEditorShortcuts = (state) => state.settings.editorShortcuts;
|
|
21803
|
+
selectDeleteShortcut = (state) => state.settings.deleteShortcut;
|
|
21551
21804
|
selectEditorFontSize = (state) => state.settings.editorFontSize;
|
|
21552
21805
|
selectEditorAutoSave = (state) => state.settings.editorAutoSave;
|
|
21553
21806
|
selectEditorAutoSaveInterval = (state) => state.settings.editorAutoSaveInterval;
|
|
@@ -21564,9 +21817,9 @@ var init_settingSlice = __esm({
|
|
|
21564
21817
|
const mode = isDark ? "dark" : "light";
|
|
21565
21818
|
const validThemeName = THEME_COLORS[themeName] ? themeName : DEFAULT_THEME_NAME;
|
|
21566
21819
|
const validFontPreset = normalizeFontPreset(fontPreset) ?? DEFAULT_FONT_PRESET;
|
|
21567
|
-
const
|
|
21568
|
-
const
|
|
21569
|
-
const
|
|
21820
|
+
const themeData = THEME_COLORS[validThemeName];
|
|
21821
|
+
const c = themeData[mode];
|
|
21822
|
+
const meta = themeData.meta;
|
|
21570
21823
|
const compact2 = density === "compact";
|
|
21571
21824
|
return {
|
|
21572
21825
|
sidebarWidth: `${sidebarWidth}px`,
|
|
@@ -21618,14 +21871,14 @@ var init_settingSlice = __esm({
|
|
|
21618
21871
|
},
|
|
21619
21872
|
// Border radius scale — xs/sm/md map to control/surface/overlay tiers.
|
|
21620
21873
|
// lg/xl remain as aliases for gradual migration of legacy CSS.
|
|
21621
|
-
radius:
|
|
21622
|
-
const
|
|
21874
|
+
radius: (() => {
|
|
21875
|
+
const boost = meta?.radiusBoost ?? 0;
|
|
21623
21876
|
const xs = compact2 ? "10px" : "12px";
|
|
21624
|
-
const sm =
|
|
21877
|
+
const sm = compact2 ? `${14 + boost}px` : `${16 + boost}px`;
|
|
21625
21878
|
const md = compact2 ? "20px" : "24px";
|
|
21626
21879
|
return { xs, sm, md, lg: sm, xl: md };
|
|
21627
21880
|
})(),
|
|
21628
|
-
motionEase:
|
|
21881
|
+
motionEase: meta?.motionEase ?? "cubic-bezier(0.33, 0, 0.2, 1)",
|
|
21629
21882
|
motionEaseTide: "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
21630
21883
|
motionEaseBreath: "cubic-bezier(0.4, 0, 0.6, 1)",
|
|
21631
21884
|
motionDuration: "0.32s",
|
|
@@ -22130,7 +22383,7 @@ var init_addContentAction = __esm({
|
|
|
22130
22383
|
contentKey,
|
|
22131
22384
|
fileCategory,
|
|
22132
22385
|
mimeType,
|
|
22133
|
-
fileSize,
|
|
22386
|
+
fileSize: fileSize2,
|
|
22134
22387
|
originalName,
|
|
22135
22388
|
categoryId: rawCategoryId,
|
|
22136
22389
|
pinned = false,
|
|
@@ -22168,7 +22421,7 @@ var init_addContentAction = __esm({
|
|
|
22168
22421
|
contentKey,
|
|
22169
22422
|
...fileCategory !== void 0 ? { fileCategory } : {},
|
|
22170
22423
|
...mimeType !== void 0 ? { mimeType } : {},
|
|
22171
|
-
...
|
|
22424
|
+
...fileSize2 !== void 0 ? { fileSize: fileSize2 } : {},
|
|
22172
22425
|
...originalName !== void 0 ? { originalName } : {},
|
|
22173
22426
|
...categoryIdForStorage !== void 0 && {
|
|
22174
22427
|
categoryId: categoryIdForStorage
|
|
@@ -43545,7 +43798,7 @@ function appendCliCapabilityWarnings(content, warnings) {
|
|
|
43545
43798
|
${warnings.map((warning) => `- ${warning}`).join("\n")}`;
|
|
43546
43799
|
return `${content}${warningBlock}`;
|
|
43547
43800
|
}
|
|
43548
|
-
var buildParallelMessageMetadata, filterMessagesForParallelBranch, buildDesktopRuntimeToolMessagesForUi, extractDesktopRuntimeToolCallsForUi, shouldUseDesktopLocalRuntime, resolveWebAgentRuntimeToolSurface, formatMachineAgentRunError, normalizeThreadMetadataPatch, patchDialogThreadMetadata, patchDialogActiveAgent, QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS, QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS, EMPTY_DYNAMIC_CONTEXTS, logQuickChatPerfStage4, readAgentConfigForTurn, buildDynamicContextsForTurn, finalizeQuickChatAgentTurnFailure, normalizeAgentRunUserInput, isSimpleTextInput, canUseQuickChatEmptyDynamicContexts, QUICK_CHAT_DIRECT_ANSWER_PATTERN, QUICK_CHAT_TOOL_INTENT_PATTERN, shouldDisableQuickChatToolsForDirectAnswer, classifyQuickChatAccessError, isUsableAgentConfig, extractAgentRunUserText, hasAgentRunUserInputContent, setLoopStopReason2, streamAgentChatTurnHandler;
|
|
43801
|
+
var buildParallelMessageMetadata, filterMessagesForParallelBranch, buildDesktopRuntimeToolMessagesForUi, extractDesktopRuntimeToolCallsForUi, shouldUseDesktopLocalRuntime, readCurrentDesktopMachineId, resolveRemoteBoundMachineId, resolveWebAgentRuntimeToolSurface, formatMachineAgentRunError, normalizeThreadMetadataPatch, patchDialogThreadMetadata, patchDialogActiveAgent, QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS, QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS, EMPTY_DYNAMIC_CONTEXTS, logQuickChatPerfStage4, readAgentConfigForTurn, buildDynamicContextsForTurn, finalizeQuickChatAgentTurnFailure, normalizeAgentRunUserInput, isSimpleTextInput, canUseQuickChatEmptyDynamicContexts, QUICK_CHAT_DIRECT_ANSWER_PATTERN, QUICK_CHAT_TOOL_INTENT_PATTERN, shouldDisableQuickChatToolsForDirectAnswer, classifyQuickChatAccessError, isUsableAgentConfig, extractAgentRunUserText, hasAgentRunUserInputContent, setLoopStopReason2, streamAgentChatTurnHandler;
|
|
43549
43802
|
var init_streamAgentChatTurn = __esm({
|
|
43550
43803
|
"packages/ai/agent/streamAgentChatTurn.ts"() {
|
|
43551
43804
|
"use strict";
|
|
@@ -43675,6 +43928,18 @@ var init_streamAgentChatTurn = __esm({
|
|
|
43675
43928
|
if (!getIsDesktopApp()) return false;
|
|
43676
43929
|
return agentConfig?.apiSource !== "cli";
|
|
43677
43930
|
};
|
|
43931
|
+
readCurrentDesktopMachineId = () => {
|
|
43932
|
+
const fromProcess = typeof process !== "undefined" ? (process.env?.NOLO_CURRENT_MACHINE_ID || process.env?.NOLO_MACHINE_ID || "").trim() : "";
|
|
43933
|
+
if (fromProcess) return fromProcess;
|
|
43934
|
+
const w = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
|
|
43935
|
+
const fromWindow = typeof w?.__NOLO_CURRENT_MACHINE_ID__ === "string" ? w.__NOLO_CURRENT_MACHINE_ID__.trim() : typeof w?.__NOLO_MACHINE_ID__ === "string" ? w.__NOLO_MACHINE_ID__.trim() : "";
|
|
43936
|
+
return fromWindow;
|
|
43937
|
+
};
|
|
43938
|
+
resolveRemoteBoundMachineId = (machineId) => {
|
|
43939
|
+
if (!machineId || !getIsDesktopApp()) return machineId;
|
|
43940
|
+
const currentMachineId = readCurrentDesktopMachineId();
|
|
43941
|
+
return currentMachineId && currentMachineId === machineId ? "" : machineId;
|
|
43942
|
+
};
|
|
43678
43943
|
resolveWebAgentRuntimeToolSurface = (agentConfig, state) => {
|
|
43679
43944
|
const toolSurface = resolveRuntimeToolSurfaceForAgent({
|
|
43680
43945
|
explicitToolNames: Array.isArray(agentConfig.tools) ? agentConfig.tools : [],
|
|
@@ -43999,7 +44264,8 @@ var init_streamAgentChatTurn = __esm({
|
|
|
43999
44264
|
apiSource: agentConfig.apiSource,
|
|
44000
44265
|
source: cachedAgentConfig === rawAgentConfig ? "cache" : "read"
|
|
44001
44266
|
});
|
|
44002
|
-
const
|
|
44267
|
+
const configuredBoundMachineId = typeof agentConfig.runtimeBinding?.machineId === "string" ? agentConfig.runtimeBinding.machineId.trim() : "";
|
|
44268
|
+
const boundMachineId = resolveRemoteBoundMachineId(configuredBoundMachineId);
|
|
44003
44269
|
if (agentConfig.apiSource === "cli" || boundMachineId && !getIsDesktopApp()) {
|
|
44004
44270
|
console.info("[streamAgentChatTurn] Triggered CLI/machine route. apiSource:", agentConfig.apiSource, "boundMachineId:", boundMachineId, "agentKey:", agentKey);
|
|
44005
44271
|
const currentState = getState();
|
|
@@ -63688,14 +63954,6 @@ function summarizeEndpoint(value) {
|
|
|
63688
63954
|
return "invalid-url";
|
|
63689
63955
|
}
|
|
63690
63956
|
}
|
|
63691
|
-
function parseJsonObject2(raw) {
|
|
63692
|
-
try {
|
|
63693
|
-
const parsed = JSON.parse(raw);
|
|
63694
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
63695
|
-
} catch {
|
|
63696
|
-
return {};
|
|
63697
|
-
}
|
|
63698
|
-
}
|
|
63699
63957
|
function isCliProviderAgent(agentConfig) {
|
|
63700
63958
|
return Boolean(
|
|
63701
63959
|
agentConfig.apiSource === "cli" || agentConfig.provider === "cli" || agentConfig.cliProvider
|
|
@@ -64419,6 +64677,9 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64419
64677
|
raw: result.raw
|
|
64420
64678
|
};
|
|
64421
64679
|
} catch (error) {
|
|
64680
|
+
if (error instanceof CliProviderQuotaError) {
|
|
64681
|
+
throw error;
|
|
64682
|
+
}
|
|
64422
64683
|
const message = error instanceof Error ? error.message : String(error);
|
|
64423
64684
|
throw new Error(
|
|
64424
64685
|
`Local CLI provider "${provider}" is unavailable or failed: ${message}`
|
|
@@ -64458,12 +64719,15 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64458
64719
|
toolNames: requestedToolNames,
|
|
64459
64720
|
env: deps.env
|
|
64460
64721
|
});
|
|
64722
|
+
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64723
|
+
const usesResponsesApi = providerConfig2.endpoint.includes("/responses");
|
|
64724
|
+
const stream = Boolean(options?.onTextDelta) && !usesResponsesApi;
|
|
64461
64725
|
const request = buildPlatformChatCompletionRequest({
|
|
64462
64726
|
providerConfig: providerConfig2,
|
|
64463
64727
|
messages,
|
|
64464
|
-
tools
|
|
64728
|
+
tools,
|
|
64729
|
+
stream
|
|
64465
64730
|
});
|
|
64466
|
-
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64467
64731
|
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
64468
64732
|
agentKey: agentConfig.key,
|
|
64469
64733
|
transport: "platform-proxy",
|
|
@@ -64474,32 +64738,62 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64474
64738
|
toolCount: tools.length,
|
|
64475
64739
|
requestedToolNames,
|
|
64476
64740
|
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
64477
|
-
timeoutMs: options?.timeoutMs ?? null
|
|
64741
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
64742
|
+
stream
|
|
64478
64743
|
});
|
|
64479
|
-
|
|
64480
|
-
|
|
64481
|
-
|
|
64482
|
-
|
|
64483
|
-
|
|
64484
|
-
|
|
64485
|
-
|
|
64486
|
-
|
|
64487
|
-
|
|
64488
|
-
|
|
64489
|
-
|
|
64490
|
-
|
|
64491
|
-
|
|
64492
|
-
|
|
64493
|
-
|
|
64494
|
-
|
|
64495
|
-
|
|
64496
|
-
|
|
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();
|
|
64497
64796
|
}
|
|
64498
|
-
return parsePlatformChatCompletionResponse({
|
|
64499
|
-
providerConfig: providerConfig2,
|
|
64500
|
-
data,
|
|
64501
|
-
trace: messages
|
|
64502
|
-
});
|
|
64503
64797
|
}
|
|
64504
64798
|
};
|
|
64505
64799
|
}
|
|
@@ -64531,47 +64825,45 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
64531
64825
|
toolNames: requestedToolNames,
|
|
64532
64826
|
env: deps.env
|
|
64533
64827
|
});
|
|
64534
|
-
const request = buildOpenAiCompatibleChatCompletionRequest({
|
|
64535
|
-
providerConfig,
|
|
64536
|
-
messages,
|
|
64537
|
-
tools
|
|
64538
|
-
});
|
|
64539
64828
|
const timeoutSignal = buildRequestTimeoutSignal(options?.timeoutMs);
|
|
64829
|
+
const stream = Boolean(options?.onTextDelta);
|
|
64540
64830
|
logLocalRuntimeDiagnostic("provider.request.start", {
|
|
64541
64831
|
agentKey: agentConfig.key,
|
|
64542
64832
|
transport: "direct-openai-compatible",
|
|
64543
|
-
requestUrl: summarizeEndpoint(
|
|
64833
|
+
requestUrl: summarizeEndpoint(providerConfig.endpoint) ?? null,
|
|
64544
64834
|
model: providerConfig.model,
|
|
64545
64835
|
messageCount: messages.length,
|
|
64546
64836
|
toolCount: tools.length,
|
|
64547
64837
|
requestedToolNames,
|
|
64548
64838
|
openAiToolNames: summarizeOpenAiToolNames(tools),
|
|
64549
|
-
timeoutMs: options?.timeoutMs ?? null
|
|
64839
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
64840
|
+
stream
|
|
64550
64841
|
});
|
|
64551
|
-
|
|
64552
|
-
|
|
64553
|
-
|
|
64554
|
-
|
|
64555
|
-
|
|
64556
|
-
|
|
64557
|
-
|
|
64558
|
-
|
|
64559
|
-
|
|
64560
|
-
|
|
64561
|
-
|
|
64562
|
-
|
|
64563
|
-
|
|
64564
|
-
|
|
64565
|
-
|
|
64566
|
-
|
|
64567
|
-
|
|
64568
|
-
|
|
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();
|
|
64569
64866
|
}
|
|
64570
|
-
return parseOpenAiCompatibleChatCompletionResponse({
|
|
64571
|
-
providerConfig,
|
|
64572
|
-
data,
|
|
64573
|
-
trace: messages
|
|
64574
|
-
});
|
|
64575
64867
|
}
|
|
64576
64868
|
};
|
|
64577
64869
|
},
|
|
@@ -65989,8 +66281,8 @@ var init_localDialogRead = __esm({
|
|
|
65989
66281
|
});
|
|
65990
66282
|
|
|
65991
66283
|
// packages/cli/index.ts
|
|
65992
|
-
import { dirname as
|
|
65993
|
-
import { fileURLToPath as
|
|
66284
|
+
import { dirname as dirname9, join as join13 } from "node:path";
|
|
66285
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
65994
66286
|
|
|
65995
66287
|
// packages/cli/cliCommandDispatch.ts
|
|
65996
66288
|
import { fileURLToPath } from "node:url";
|
|
@@ -66155,17 +66447,6 @@ function parseIsoTimestampOption(raw, flag) {
|
|
|
66155
66447
|
}
|
|
66156
66448
|
return new Date(time).toISOString();
|
|
66157
66449
|
}
|
|
66158
|
-
function buildUsageProbeConfig(kind) {
|
|
66159
|
-
if (!kind) return void 0;
|
|
66160
|
-
if (kind !== "qoder-local-quota-log") {
|
|
66161
|
-
throw new Error("--usage-probe currently supports qoder-local-quota-log.");
|
|
66162
|
-
}
|
|
66163
|
-
return {
|
|
66164
|
-
kind,
|
|
66165
|
-
command: "nolo agent usage qoder",
|
|
66166
|
-
capability: "qoder-usage"
|
|
66167
|
-
};
|
|
66168
|
-
}
|
|
66169
66450
|
async function curlFetch(url, init) {
|
|
66170
66451
|
const method = init?.method ?? "GET";
|
|
66171
66452
|
const headers = new Headers(init?.headers ?? {});
|
|
@@ -66422,7 +66703,6 @@ function parseAgentUpdateArgs(args2) {
|
|
|
66422
66703
|
"--max-concurrent"
|
|
66423
66704
|
);
|
|
66424
66705
|
const expiresAt = parseIsoTimestampOption(readOption2(args2, "--expires-at"), "--expires-at");
|
|
66425
|
-
const usageProbe = buildUsageProbeConfig(readOption2(args2, "--usage-probe"));
|
|
66426
66706
|
const handle = readOption2(args2, "--handle")?.trim();
|
|
66427
66707
|
const promptSources = [prompt, promptFile, promptDoc].filter(Boolean);
|
|
66428
66708
|
if (promptSources.length > 1) {
|
|
@@ -66439,11 +66719,8 @@ function parseAgentUpdateArgs(args2) {
|
|
|
66439
66719
|
if (customProviderUrl) updates.customProviderUrl = customProviderUrl;
|
|
66440
66720
|
if (apiKey) updates.apiKey = apiKey;
|
|
66441
66721
|
if (maxConcurrent != null) updates.admission = { maxConcurrent };
|
|
66442
|
-
if (expiresAt
|
|
66443
|
-
updates.scheduling = {
|
|
66444
|
-
...expiresAt ? { expiresAt } : {},
|
|
66445
|
-
...usageProbe ? { usageProbe } : {}
|
|
66446
|
-
};
|
|
66722
|
+
if (expiresAt) {
|
|
66723
|
+
updates.scheduling = { expiresAt };
|
|
66447
66724
|
}
|
|
66448
66725
|
if (handle) updates.handle = handle;
|
|
66449
66726
|
for (const entry of readRepeatedOption(args2, "--field")) {
|
|
@@ -67582,7 +67859,7 @@ async function runAgentUpdateCommand(args2, deps = {}) {
|
|
|
67582
67859
|
}
|
|
67583
67860
|
if (!parsed) {
|
|
67584
67861
|
output2.write(
|
|
67585
|
-
"Usage: nolo agent update <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--
|
|
67862
|
+
"Usage: nolo agent update <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--prompt <text> | --prompt-file <path> | --prompt-doc <pageKey>] [--tools <json>] [--copy-provider-from <agent>] [--field key=value]\n".replace("[--field key=value]", "[--handle <name>] [--field key=value]")
|
|
67586
67863
|
);
|
|
67587
67864
|
return args2[0] ? 0 : 1;
|
|
67588
67865
|
}
|
|
@@ -67654,7 +67931,7 @@ async function runAgentCreateCommand(args2, deps = {}) {
|
|
|
67654
67931
|
}
|
|
67655
67932
|
if (!parsed) {
|
|
67656
67933
|
output2.write(
|
|
67657
|
-
"Usage: nolo agent create <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--
|
|
67934
|
+
"Usage: nolo agent create <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--prompt <text> | --prompt-file <path> | --prompt-doc <pageKey>] [--tools <json>] [--copy-provider-from <agent>] [--name <name>] [--custom-provider-url <url>] [--provider-api-key <key>] [--field key=value]\n".replace("[--field key=value]", "[--handle <name>] [--field key=value]")
|
|
67658
67935
|
);
|
|
67659
67936
|
return args2[0] ? 0 : 1;
|
|
67660
67937
|
}
|
|
@@ -67753,6 +68030,412 @@ function createStreamingTextWriter({
|
|
|
67753
68030
|
};
|
|
67754
68031
|
}
|
|
67755
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
|
+
|
|
67756
68439
|
// packages/cli/client/agentRun.ts
|
|
67757
68440
|
var Spinner = class {
|
|
67758
68441
|
constructor(output2, text) {
|
|
@@ -67858,6 +68541,23 @@ function isCliProviderAgentConfig(agentConfig) {
|
|
|
67858
68541
|
const provider = typeof agentConfig?.provider === "string" ? agentConfig.provider.trim() : "";
|
|
67859
68542
|
return Boolean(cliProvider) || provider === "agy" || provider === "codex" || provider === "claude";
|
|
67860
68543
|
}
|
|
68544
|
+
function resolveBoundMachineId(agentConfig) {
|
|
68545
|
+
return agentConfig?.runtimeBinding && typeof agentConfig.runtimeBinding === "object" ? String(agentConfig.runtimeBinding.machineId ?? "").trim() : "";
|
|
68546
|
+
}
|
|
68547
|
+
async function detectCurrentMachineId(env) {
|
|
68548
|
+
const fromEnv = (env.NOLO_CURRENT_MACHINE_ID || env.NOLO_MACHINE_ID || "").trim();
|
|
68549
|
+
if (fromEnv) return fromEnv;
|
|
68550
|
+
try {
|
|
68551
|
+
const { detectMachineInfo: detectMachineInfo2 } = await Promise.resolve().then(() => (init_machineInfo(), machineInfo_exports));
|
|
68552
|
+
const machine = await detectMachineInfo2({ probeLaunchable: true });
|
|
68553
|
+
return typeof machine?.machineId === "string" && machine.machineId.trim() ? machine.machineId.trim() : void 0;
|
|
68554
|
+
} catch {
|
|
68555
|
+
return void 0;
|
|
68556
|
+
}
|
|
68557
|
+
}
|
|
68558
|
+
async function resolveCurrentMachineId(options) {
|
|
68559
|
+
return options.currentMachineIdResolver ? options.currentMachineIdResolver(options.env) : detectCurrentMachineId(options.env);
|
|
68560
|
+
}
|
|
67861
68561
|
function resolveAuthToken5(env) {
|
|
67862
68562
|
return env.AUTH_TOKEN || env.AUTH || env.BENCHMARK_AUTH_TOKEN || "";
|
|
67863
68563
|
}
|
|
@@ -67902,7 +68602,16 @@ async function shouldSkipAutoLocalForServerPlatformTools(options) {
|
|
|
67902
68602
|
}
|
|
67903
68603
|
return false;
|
|
67904
68604
|
}
|
|
67905
|
-
if (isCliProviderAgentConfig(agentConfig))
|
|
68605
|
+
if (isCliProviderAgentConfig(agentConfig)) {
|
|
68606
|
+
const boundMachineId = resolveBoundMachineId(agentConfig);
|
|
68607
|
+
if (!boundMachineId) return false;
|
|
68608
|
+
const currentMachineId = (await resolveCurrentMachineId(options))?.trim() || "";
|
|
68609
|
+
if (currentMachineId && currentMachineId === boundMachineId) return false;
|
|
68610
|
+
options.output.write(
|
|
68611
|
+
`[nolo] auto runtime: skipping local runtime because ${options.agentKey} is bound to ${boundMachineId}` + (currentMachineId ? ` and this machine is ${currentMachineId}.` : ".") + " Use --local explicitly to force the current machine.\n"
|
|
68612
|
+
);
|
|
68613
|
+
return true;
|
|
68614
|
+
}
|
|
67906
68615
|
if (knownServerPlatformAgent) {
|
|
67907
68616
|
options.output.write(
|
|
67908
68617
|
`[nolo] auto runtime: skipping local runtime because ${options.agentKey} is a known platform agent. Use --local explicitly to force local workspace tools.
|
|
@@ -67972,10 +68681,13 @@ function buildSubjectRefs(options) {
|
|
|
67972
68681
|
}
|
|
67973
68682
|
return refs.length ? refs : void 0;
|
|
67974
68683
|
}
|
|
67975
|
-
function
|
|
67976
|
-
const
|
|
67977
|
-
|
|
67978
|
-
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
|
+
);
|
|
67979
68691
|
}
|
|
67980
68692
|
function resolveAgentEventMode(options) {
|
|
67981
68693
|
if (options.eventsMode === "jsonl") return "jsonl";
|
|
@@ -67986,23 +68698,6 @@ function isMissingLocalAgentConfigError(error, agentRef) {
|
|
|
67986
68698
|
error && typeof error === "object" && "code" in error && error.code === LOCAL_AGENT_CONFIG_MISSING_CODE && error.agentRef === agentRef
|
|
67987
68699
|
);
|
|
67988
68700
|
}
|
|
67989
|
-
function formatToolTraceEvent(event) {
|
|
67990
|
-
const round = event.round + 1;
|
|
67991
|
-
const detail = event.argumentsPreview ? ` ${event.argumentsPreview}` : "";
|
|
67992
|
-
if (event.type === "tool-call") {
|
|
67993
|
-
return `[nolo:tool] #${round} -> ${event.toolName}${detail}
|
|
67994
|
-
`;
|
|
67995
|
-
}
|
|
67996
|
-
if (event.type === "tool-error") {
|
|
67997
|
-
const elapsed2 = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
67998
|
-
return `[nolo:tool] #${round} !! ${event.toolName}${elapsed2}: ${event.message ?? "failed"}
|
|
67999
|
-
`;
|
|
68000
|
-
}
|
|
68001
|
-
const elapsed = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
|
|
68002
|
-
const summary = event.summary ? ` ${event.summary}` : "";
|
|
68003
|
-
return `[nolo:tool] #${round} <- ${event.toolName}${elapsed}${summary}
|
|
68004
|
-
`;
|
|
68005
|
-
}
|
|
68006
68701
|
function formatToolJsonEvent(event) {
|
|
68007
68702
|
return `${JSON.stringify({
|
|
68008
68703
|
schemaVersion: 1,
|
|
@@ -68023,6 +68718,9 @@ function shouldAttemptAutoLocal(options) {
|
|
|
68023
68718
|
if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && isBuiltinNoloAgentRef(options.agentKey) && resolveAuthToken5(options.env)) {
|
|
68024
68719
|
return true;
|
|
68025
68720
|
}
|
|
68721
|
+
if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && resolveAuthToken5(options.env) && !isKnownServerPlatformAgent(options)) {
|
|
68722
|
+
return true;
|
|
68723
|
+
}
|
|
68026
68724
|
return Boolean(
|
|
68027
68725
|
options.env.NOLO_LOCAL_OPENAI_API_KEY || options.env.OPENAI_API_KEY || options.env.NOLO_LOCAL_OPENAI_BASE_URL || options.env.OPENAI_BASE_URL || options.env.NOLO_LOCAL_AGENT_KEY
|
|
68028
68726
|
);
|
|
@@ -68131,8 +68829,8 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
68131
68829
|
const contentType = res.headers.get("content-type") || "";
|
|
68132
68830
|
if (contentType.includes("text/event-stream") && res.body) {
|
|
68133
68831
|
spinner.stop();
|
|
68134
|
-
const
|
|
68135
|
-
return
|
|
68832
|
+
const result = await readStreamingAgentRun(options, res);
|
|
68833
|
+
return result;
|
|
68136
68834
|
}
|
|
68137
68835
|
spinner.stop();
|
|
68138
68836
|
let data = {};
|
|
@@ -68175,7 +68873,10 @@ async function runHttpAgentTurn(options, authToken) {
|
|
|
68175
68873
|
}
|
|
68176
68874
|
return dialogIdText ? { exitCode: 1, dialogId: dialogIdText } : { exitCode: 1 };
|
|
68177
68875
|
}
|
|
68178
|
-
const content =
|
|
68876
|
+
const content = formatAssistantResponseForCli(
|
|
68877
|
+
String(data?.content ?? data?.message ?? ""),
|
|
68878
|
+
options
|
|
68879
|
+
);
|
|
68179
68880
|
if (content) {
|
|
68180
68881
|
options.output.write(`
|
|
68181
68882
|
${options.agentName} > ${content}
|
|
@@ -68188,11 +68889,14 @@ ${options.agentName} > (no text response)
|
|
|
68188
68889
|
const usage2 = formatUsage(data?.usage, data?.dialogId);
|
|
68189
68890
|
if (usage2 && shouldShowUsage(options.env)) options.output.write(`${usage2}
|
|
68190
68891
|
`);
|
|
68191
|
-
|
|
68892
|
+
return {
|
|
68192
68893
|
exitCode: 0,
|
|
68193
|
-
...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
|
+
)
|
|
68194
68899
|
};
|
|
68195
|
-
return result;
|
|
68196
68900
|
}
|
|
68197
68901
|
async function runInjectedLocalAgentTurn(options) {
|
|
68198
68902
|
return runLocalAgentTurnForCli(options, { reportFailure: true });
|
|
@@ -68212,8 +68916,18 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68212
68916
|
const spinner = new Spinner(options.output, `${options.agentName} -> working locally`);
|
|
68213
68917
|
spinner.start();
|
|
68214
68918
|
try {
|
|
68215
|
-
const
|
|
68919
|
+
const toolDisplayMode = resolveToolDisplayMode(options.env);
|
|
68920
|
+
const traceLocalTools = shouldEmitToolEvents(toolDisplayMode);
|
|
68921
|
+
const formatToolEvent = createToolEventFormatter(toolDisplayMode);
|
|
68216
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
|
+
);
|
|
68217
68931
|
const subjectRefs = buildSubjectRefs(options);
|
|
68218
68932
|
const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter((key2) => key2.trim());
|
|
68219
68933
|
const allowedToolNames = options.allowedToolNames?.filter((name) => name.trim());
|
|
@@ -68242,27 +68956,48 @@ async function runLocalAgentTurnForCli(options, settings) {
|
|
|
68242
68956
|
...typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
|
|
68243
68957
|
...traceLocalTools ? {
|
|
68244
68958
|
onToolEvent: (event) => {
|
|
68245
|
-
|
|
68246
|
-
|
|
68247
|
-
|
|
68248
|
-
|
|
68249
|
-
);
|
|
68959
|
+
spinner.stop();
|
|
68960
|
+
const chunk = eventMode === "jsonl" ? formatToolJsonEvent(event) : formatToolEvent(event);
|
|
68961
|
+
if (chunk) {
|
|
68962
|
+
wroteToolTrace = true;
|
|
68963
|
+
options.output.write(chunk);
|
|
68964
|
+
}
|
|
68965
|
+
}
|
|
68966
|
+
} : {},
|
|
68967
|
+
...!options.noStream ? {
|
|
68968
|
+
onTextDelta: (chunk) => {
|
|
68969
|
+
spinner.stop();
|
|
68970
|
+
if (!printedAssistantLabel) {
|
|
68971
|
+
options.output.write(`
|
|
68972
|
+
${options.agentName} > `);
|
|
68973
|
+
printedAssistantLabel = true;
|
|
68250
68974
|
}
|
|
68975
|
+
streamedAssistantText = true;
|
|
68976
|
+
thinkingFilter.push(chunk);
|
|
68251
68977
|
}
|
|
68252
68978
|
} : {}
|
|
68253
68979
|
});
|
|
68254
68980
|
spinner.stop();
|
|
68255
|
-
|
|
68256
|
-
|
|
68257
|
-
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(`
|
|
68258
68988
|
${options.agentName} > ${content}
|
|
68259
68989
|
`);
|
|
68260
|
-
|
|
68261
|
-
|
|
68990
|
+
} else {
|
|
68991
|
+
options.output.write(`
|
|
68262
68992
|
${options.agentName} > (no text response)
|
|
68263
68993
|
`);
|
|
68994
|
+
}
|
|
68264
68995
|
}
|
|
68265
|
-
return {
|
|
68996
|
+
return {
|
|
68997
|
+
exitCode: 0,
|
|
68998
|
+
dialogId: result.dialogId,
|
|
68999
|
+
turnTokens: buildTurnTokenUsage(result.usage, result.model)
|
|
69000
|
+
};
|
|
68266
69001
|
} catch (error) {
|
|
68267
69002
|
spinner.stop();
|
|
68268
69003
|
if (settings.reportFailure) {
|
|
@@ -68281,9 +69016,14 @@ async function readStreamingAgentRun(options, res) {
|
|
|
68281
69016
|
return { exitCode: 1 };
|
|
68282
69017
|
}
|
|
68283
69018
|
const decoder = new TextDecoder();
|
|
69019
|
+
const thinkingMode = resolveThinkingDisplayMode(options.env);
|
|
68284
69020
|
const writer = createStreamingTextWriter({
|
|
68285
69021
|
write: (chunk) => options.output.write(chunk)
|
|
68286
69022
|
});
|
|
69023
|
+
const thinkingFilter = createThinkingAwareStreamFilter(
|
|
69024
|
+
(chunk) => writer.push(chunk),
|
|
69025
|
+
thinkingMode
|
|
69026
|
+
);
|
|
68287
69027
|
let buffer = "";
|
|
68288
69028
|
let content = "";
|
|
68289
69029
|
let dialogId;
|
|
@@ -68313,7 +69053,7 @@ ${options.agentName} > `);
|
|
|
68313
69053
|
if (!chunk) return;
|
|
68314
69054
|
printLabel();
|
|
68315
69055
|
content += chunk;
|
|
68316
|
-
|
|
69056
|
+
thinkingFilter.push(chunk);
|
|
68317
69057
|
};
|
|
68318
69058
|
try {
|
|
68319
69059
|
while (true) {
|
|
@@ -68350,6 +69090,7 @@ ${options.agentName} > `);
|
|
|
68350
69090
|
return { exitCode: 1 };
|
|
68351
69091
|
} finally {
|
|
68352
69092
|
writer.flushAll();
|
|
69093
|
+
thinkingFilter.flush();
|
|
68353
69094
|
}
|
|
68354
69095
|
if (!content) {
|
|
68355
69096
|
options.output.write(`
|
|
@@ -68363,7 +69104,8 @@ ${options.agentName} > (no text response)
|
|
|
68363
69104
|
`);
|
|
68364
69105
|
return {
|
|
68365
69106
|
exitCode: 0,
|
|
68366
|
-
...dialogId ? { dialogId } : {}
|
|
69107
|
+
...dialogId ? { dialogId } : {},
|
|
69108
|
+
turnTokens: buildTurnTokenUsage(usage2, options.agentKey)
|
|
68367
69109
|
};
|
|
68368
69110
|
}
|
|
68369
69111
|
async function runAgentTurn(options) {
|
|
@@ -68376,10 +69118,17 @@ async function runAgentTurn(options) {
|
|
|
68376
69118
|
const skipLocal = await shouldSkipAutoLocalForServerPlatformTools(options);
|
|
68377
69119
|
if (!skipLocal) {
|
|
68378
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
|
+
}
|
|
68379
69127
|
if (localResult.exitCode === 0) {
|
|
68380
69128
|
return {
|
|
68381
69129
|
exitCode: localResult.exitCode,
|
|
68382
|
-
...localResult.dialogId ? { dialogId: localResult.dialogId } : {}
|
|
69130
|
+
...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
|
|
69131
|
+
...localResult.turnTokens ? { turnTokens: localResult.turnTokens } : {}
|
|
68383
69132
|
};
|
|
68384
69133
|
}
|
|
68385
69134
|
if (isMissingLocalAgentConfigError(localResult.localError, options.agentKey)) {
|
|
@@ -68396,7 +69145,8 @@ async function runAgentTurn(options) {
|
|
|
68396
69145
|
if (retriedLocalResult.exitCode === 0) {
|
|
68397
69146
|
return {
|
|
68398
69147
|
exitCode: retriedLocalResult.exitCode,
|
|
68399
|
-
...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {}
|
|
69148
|
+
...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {},
|
|
69149
|
+
...retriedLocalResult.turnTokens ? { turnTokens: retriedLocalResult.turnTokens } : {}
|
|
68400
69150
|
};
|
|
68401
69151
|
}
|
|
68402
69152
|
}
|
|
@@ -69598,7 +70348,7 @@ function countByName(values) {
|
|
|
69598
70348
|
function uniq(values) {
|
|
69599
70349
|
return [...new Set(values.filter(Boolean))];
|
|
69600
70350
|
}
|
|
69601
|
-
function
|
|
70351
|
+
function parseJsonObject2(raw) {
|
|
69602
70352
|
if (typeof raw !== "string" || !raw.trim()) return null;
|
|
69603
70353
|
try {
|
|
69604
70354
|
const parsed = JSON.parse(raw);
|
|
@@ -69614,7 +70364,7 @@ function deriveWrittenFiles(toolMessages) {
|
|
|
69614
70364
|
const toolName = toToolName(message?.toolName ?? message?.name);
|
|
69615
70365
|
if (!writeToolNames.has(toolName)) continue;
|
|
69616
70366
|
const payload = message?.toolPayload ?? {};
|
|
69617
|
-
const content =
|
|
70367
|
+
const content = parseJsonObject2(message?.content);
|
|
69618
70368
|
for (const candidate of [payload?.input?.filePath, payload?.response?.filePath, content?.filePath]) {
|
|
69619
70369
|
const normalized = typeof candidate === "string" ? candidate.trim() : "";
|
|
69620
70370
|
if (normalized) files.push(normalized);
|
|
@@ -69627,7 +70377,7 @@ function deriveToolErrors(toolMessages) {
|
|
|
69627
70377
|
for (const message of toolMessages) {
|
|
69628
70378
|
const toolName = toToolName(message?.toolName ?? message?.name);
|
|
69629
70379
|
const payload = message?.toolPayload ?? {};
|
|
69630
|
-
const content =
|
|
70380
|
+
const content = parseJsonObject2(message?.content);
|
|
69631
70381
|
if (payload?.status === "failed" || content?.ok === false || content?.applied === false || content?.success === false) {
|
|
69632
70382
|
errors.push(toolName || "unknown-tool");
|
|
69633
70383
|
}
|
|
@@ -71467,7 +72217,6 @@ function getSpaceInternalCommandEntries() {
|
|
|
71467
72217
|
// packages/cli/authCommands.ts
|
|
71468
72218
|
import { createInterface } from "node:readline/promises";
|
|
71469
72219
|
import { stdin as input, stdout as output } from "node:process";
|
|
71470
|
-
import { rmSync as rmSync2 } from "node:fs";
|
|
71471
72220
|
import { spawn as spawn5 } from "node:child_process";
|
|
71472
72221
|
|
|
71473
72222
|
// packages/cli/client/profileConfig.ts
|
|
@@ -71502,16 +72251,31 @@ function loadProfileConfig(path7 = getDefaultProfileConfigPath()) {
|
|
|
71502
72251
|
}
|
|
71503
72252
|
return parsed;
|
|
71504
72253
|
}
|
|
72254
|
+
function clearProfileAuthToken(path7 = getDefaultProfileConfigPath()) {
|
|
72255
|
+
const config = loadProfileConfig(path7);
|
|
72256
|
+
if (!config) return false;
|
|
72257
|
+
const profile = config.profiles[config.currentProfile];
|
|
72258
|
+
if (!profile?.authToken?.trim()) return false;
|
|
72259
|
+
delete profile.authToken;
|
|
72260
|
+
mkdirSync5(dirname6(path7), { recursive: true });
|
|
72261
|
+
writeFileSync4(path7, `${JSON.stringify(config, null, 2)}
|
|
72262
|
+
`, "utf8");
|
|
72263
|
+
return true;
|
|
72264
|
+
}
|
|
71505
72265
|
function saveDefaultProfile(path7, profile) {
|
|
72266
|
+
const existing = loadProfileConfig(path7);
|
|
72267
|
+
const mergedDefault = {
|
|
72268
|
+
...existing?.profiles?.default ?? {},
|
|
72269
|
+
serverUrl: normalizeProfileServerUrl(profile.serverUrl),
|
|
72270
|
+
authToken: profile.authToken.trim()
|
|
72271
|
+
};
|
|
71506
72272
|
const config = {
|
|
71507
72273
|
currentProfile: "default",
|
|
71508
72274
|
profiles: {
|
|
71509
|
-
|
|
72275
|
+
...existing?.profiles ?? {},
|
|
72276
|
+
default: mergedDefault
|
|
71510
72277
|
}
|
|
71511
72278
|
};
|
|
71512
|
-
config.profiles.default.serverUrl = normalizeProfileServerUrl(
|
|
71513
|
-
config.profiles.default.serverUrl
|
|
71514
|
-
);
|
|
71515
72279
|
mkdirSync5(dirname6(path7), { recursive: true });
|
|
71516
72280
|
writeFileSync4(path7, `${JSON.stringify(config, null, 2)}
|
|
71517
72281
|
`, "utf8");
|
|
@@ -71524,7 +72288,7 @@ function buildEnvFromProfile(config) {
|
|
|
71524
72288
|
return {
|
|
71525
72289
|
NOLO_PROFILE: config.currentProfile,
|
|
71526
72290
|
NOLO_SERVER: profile.serverUrl,
|
|
71527
|
-
AUTH_TOKEN: profile.authToken,
|
|
72291
|
+
...profile.authToken?.trim() ? { AUTH_TOKEN: profile.authToken.trim() } : {},
|
|
71528
72292
|
...profile.agentKey ? { NOLO_AGENT: profile.agentKey } : {},
|
|
71529
72293
|
...profile.agentName ? { NOLO_AGENT_NAME: profile.agentName } : {}
|
|
71530
72294
|
};
|
|
@@ -71545,9 +72309,65 @@ function getCurrentProfile(config) {
|
|
|
71545
72309
|
if (!config) return null;
|
|
71546
72310
|
return config.profiles[config.currentProfile] ?? null;
|
|
71547
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
|
+
}
|
|
71548
72324
|
|
|
71549
72325
|
// packages/cli/authCommands.ts
|
|
72326
|
+
init_cliEnvHelpers();
|
|
71550
72327
|
init_defaultServer();
|
|
72328
|
+
var LOGIN_HELP_TEXT = `Log in to Nolo and save a local profile.
|
|
72329
|
+
|
|
72330
|
+
Usage:
|
|
72331
|
+
nolo login [--server <url>] [--no-browser] [--token <jwt>] [--manual]
|
|
72332
|
+
|
|
72333
|
+
Options:
|
|
72334
|
+
--server <url> Nolo server URL (default: ${DEFAULT_NOLO_SERVER_URL})
|
|
72335
|
+
--no-browser Print the authorization URL instead of opening a browser
|
|
72336
|
+
--token <jwt> Save a token directly without browser authorization
|
|
72337
|
+
--manual Prompt to paste a token interactively
|
|
72338
|
+
|
|
72339
|
+
By default, opens the Nolo website and polls until authorization completes.
|
|
72340
|
+
In SSH sessions, use --no-browser and open the printed URL on a machine with a browser
|
|
72341
|
+
where you are already logged into Nolo.
|
|
72342
|
+
`;
|
|
72343
|
+
var LOGOUT_HELP_TEXT = `Log out of Nolo by clearing the saved auth token.
|
|
72344
|
+
|
|
72345
|
+
Usage:
|
|
72346
|
+
nolo logout
|
|
72347
|
+
|
|
72348
|
+
Keeps other profile settings such as server URL and default agent preferences.
|
|
72349
|
+
Does not unset AUTH_TOKEN or other auth-related environment variables.
|
|
72350
|
+
`;
|
|
72351
|
+
var WHOAMI_HELP_TEXT = `Show the current login state.
|
|
72352
|
+
|
|
72353
|
+
Usage:
|
|
72354
|
+
nolo whoami
|
|
72355
|
+
`;
|
|
72356
|
+
function wantsHelp(args2) {
|
|
72357
|
+
return args2.includes("--help") || args2.includes("-h");
|
|
72358
|
+
}
|
|
72359
|
+
function formatDuration(ms) {
|
|
72360
|
+
const totalSec = Math.max(0, Math.ceil(ms / 1e3));
|
|
72361
|
+
const minutes = Math.floor(totalSec / 60);
|
|
72362
|
+
const seconds = totalSec % 60;
|
|
72363
|
+
if (minutes > 0) return `${minutes}m ${seconds}s`;
|
|
72364
|
+
return `${seconds}s`;
|
|
72365
|
+
}
|
|
72366
|
+
function formatTokenPreview(token) {
|
|
72367
|
+
const trimmed = token.trim();
|
|
72368
|
+
if (!trimmed) return "";
|
|
72369
|
+
return `${trimmed.slice(0, 8)}...`;
|
|
72370
|
+
}
|
|
71551
72371
|
function getArg(args2, flag) {
|
|
71552
72372
|
const index = args2.indexOf(flag);
|
|
71553
72373
|
return index >= 0 ? args2[index + 1] : void 0;
|
|
@@ -71609,6 +72429,11 @@ async function runWebLogin(args2) {
|
|
|
71609
72429
|
const intervalMs = Math.max(1, Number(start.interval) || 2) * 1e3;
|
|
71610
72430
|
const timeoutMs = Math.max(1, Number(start.expiresIn) || 600) * 1e3;
|
|
71611
72431
|
const deadline = args2.now() + timeoutMs;
|
|
72432
|
+
const statusLogIntervalMs = 15e3;
|
|
72433
|
+
let lastStatusLogAt = 0;
|
|
72434
|
+
args2.output.log(
|
|
72435
|
+
`[nolo] Waiting for browser authorization (${formatDuration(timeoutMs)} remaining)...`
|
|
72436
|
+
);
|
|
71612
72437
|
while (args2.now() <= deadline) {
|
|
71613
72438
|
const pollResponse = await postJson(
|
|
71614
72439
|
args2.fetchImpl,
|
|
@@ -71617,6 +72442,16 @@ async function runWebLogin(args2) {
|
|
|
71617
72442
|
);
|
|
71618
72443
|
const poll = await pollResponse.json().catch(() => ({}));
|
|
71619
72444
|
if (pollResponse.status === 202) {
|
|
72445
|
+
const currentTime = args2.now();
|
|
72446
|
+
if (lastStatusLogAt > 0 && currentTime - lastStatusLogAt >= statusLogIntervalMs) {
|
|
72447
|
+
const remainingMs = Math.max(0, deadline - currentTime);
|
|
72448
|
+
args2.output.log(
|
|
72449
|
+
`[nolo] Still waiting... (${formatDuration(remainingMs)} remaining)`
|
|
72450
|
+
);
|
|
72451
|
+
lastStatusLogAt = currentTime;
|
|
72452
|
+
} else if (lastStatusLogAt === 0) {
|
|
72453
|
+
lastStatusLogAt = currentTime;
|
|
72454
|
+
}
|
|
71620
72455
|
await args2.sleep(intervalMs);
|
|
71621
72456
|
continue;
|
|
71622
72457
|
}
|
|
@@ -71639,12 +72474,16 @@ async function runWebLogin(args2) {
|
|
|
71639
72474
|
return 1;
|
|
71640
72475
|
}
|
|
71641
72476
|
async function runLoginCommand(args2, deps = {}) {
|
|
72477
|
+
const outputTarget = deps.output ?? console;
|
|
72478
|
+
const errorTarget = deps.error ?? console;
|
|
72479
|
+
if (wantsHelp(args2)) {
|
|
72480
|
+
outputTarget.log(LOGIN_HELP_TEXT);
|
|
72481
|
+
return 0;
|
|
72482
|
+
}
|
|
71642
72483
|
const configPath = deps.configPath ?? getDefaultProfileConfigPath();
|
|
71643
72484
|
const serverArg = getArg(args2, "--server");
|
|
71644
72485
|
const tokenArg = getArg(args2, "--token");
|
|
71645
72486
|
const noBrowser = args2.includes("--no-browser");
|
|
71646
|
-
const outputTarget = deps.output ?? console;
|
|
71647
|
-
const errorTarget = deps.error ?? console;
|
|
71648
72487
|
const serverUrl = (serverArg || DEFAULT_NOLO_SERVER_URL).replace(/\/+$/, "");
|
|
71649
72488
|
if (tokenArg) {
|
|
71650
72489
|
return saveTokenLogin({
|
|
@@ -71684,33 +72523,68 @@ async function runLoginCommand(args2, deps = {}) {
|
|
|
71684
72523
|
});
|
|
71685
72524
|
}
|
|
71686
72525
|
function runWhoamiCommand(deps = {}) {
|
|
71687
|
-
const env = deps.env ?? process.env;
|
|
71688
72526
|
const output2 = deps.output ?? console;
|
|
72527
|
+
if (wantsHelp(deps.args ?? [])) {
|
|
72528
|
+
output2.log(WHOAMI_HELP_TEXT);
|
|
72529
|
+
return 0;
|
|
72530
|
+
}
|
|
72531
|
+
const env = deps.env ?? process.env;
|
|
71689
72532
|
const config = loadProfileConfig(deps.configPath);
|
|
71690
72533
|
const profile = getCurrentProfile(config);
|
|
71691
|
-
|
|
72534
|
+
const profileToken = profile?.authToken?.trim() ?? "";
|
|
72535
|
+
const envToken = resolveAuthTokenFromEnv(env);
|
|
72536
|
+
if (!profileToken && !envToken) {
|
|
71692
72537
|
output2.log("Not logged in. Run: nolo login");
|
|
71693
72538
|
return 1;
|
|
71694
72539
|
}
|
|
71695
72540
|
const runtimeEnv2 = buildCliRuntimeEnv(env, config);
|
|
71696
|
-
const effectiveServer = runtimeEnv2.NOLO_SERVER ?? profile.serverUrl;
|
|
71697
72541
|
const explicitServer = env.NOLO_SERVER || env.NOLO_SERVER_URL || env.BASE_URL;
|
|
72542
|
+
if (!profileToken && envToken) {
|
|
72543
|
+
output2.log("profile: not logged in (no saved token)");
|
|
72544
|
+
if (profile?.serverUrl) {
|
|
72545
|
+
output2.log(`profile server: ${profile.serverUrl}`);
|
|
72546
|
+
}
|
|
72547
|
+
output2.log(`effective server: ${runtimeEnv2.NOLO_SERVER ?? resolveServerUrlFallback(profile)}`);
|
|
72548
|
+
output2.log(`server source: ${explicitServer ? "env" : profile?.serverUrl ? "profile" : "default"}`);
|
|
72549
|
+
output2.log(`env token: ${formatTokenPreview(envToken)} (source: environment)`);
|
|
72550
|
+
return 0;
|
|
72551
|
+
}
|
|
72552
|
+
const effectiveServer = runtimeEnv2.NOLO_SERVER ?? profile.serverUrl;
|
|
71698
72553
|
output2.log(`profile: ${config.currentProfile}`);
|
|
71699
72554
|
output2.log(`profile server: ${profile.serverUrl}`);
|
|
71700
72555
|
output2.log(`effective server: ${effectiveServer}`);
|
|
71701
72556
|
output2.log(`server source: ${explicitServer ? "env" : "profile"}`);
|
|
71702
|
-
output2.log(`token: ${
|
|
72557
|
+
output2.log(`token: ${formatTokenPreview(profileToken)} (source: profile)`);
|
|
72558
|
+
if (envToken && envToken !== profileToken) {
|
|
72559
|
+
output2.log(`env token: ${formatTokenPreview(envToken)} (source: environment, unused while profile token is set)`);
|
|
72560
|
+
}
|
|
71703
72561
|
return 0;
|
|
71704
72562
|
}
|
|
71705
|
-
function
|
|
71706
|
-
|
|
71707
|
-
|
|
71708
|
-
|
|
72563
|
+
function resolveServerUrlFallback(profile) {
|
|
72564
|
+
return profile?.serverUrl ?? DEFAULT_NOLO_SERVER_URL;
|
|
72565
|
+
}
|
|
72566
|
+
function runLogoutCommand(deps = {}) {
|
|
72567
|
+
const output2 = deps.output ?? console;
|
|
72568
|
+
if (wantsHelp(deps.args ?? [])) {
|
|
72569
|
+
output2.log(LOGOUT_HELP_TEXT);
|
|
72570
|
+
return 0;
|
|
72571
|
+
}
|
|
72572
|
+
const env = deps.env ?? process.env;
|
|
72573
|
+
const configPath = deps.configPath ?? getDefaultProfileConfigPath();
|
|
72574
|
+
if (!clearProfileAuthToken(configPath)) {
|
|
72575
|
+
output2.log("Not logged in.");
|
|
72576
|
+
return 0;
|
|
72577
|
+
}
|
|
72578
|
+
output2.log("Logged out.");
|
|
72579
|
+
if (resolveAuthTokenFromEnv(env)) {
|
|
72580
|
+
output2.log(
|
|
72581
|
+
"Note: AUTH_TOKEN in the environment is unchanged and may still authenticate commands."
|
|
72582
|
+
);
|
|
72583
|
+
}
|
|
71709
72584
|
return 0;
|
|
71710
72585
|
}
|
|
71711
72586
|
|
|
71712
72587
|
// packages/cli/systemInternalCommandEntries.ts
|
|
71713
|
-
init_defaultServer();
|
|
71714
72588
|
init_machineCommands();
|
|
71715
72589
|
|
|
71716
72590
|
// packages/cli/runtimeDoctorCommands.ts
|
|
@@ -71871,15 +72745,352 @@ async function runDoctorRuntimeCommand(args2, deps = {}) {
|
|
|
71871
72745
|
return decision.runnable ? 0 : 1;
|
|
71872
72746
|
}
|
|
71873
72747
|
|
|
71874
|
-
// packages/cli/
|
|
72748
|
+
// packages/cli/standaloneBundle.ts
|
|
71875
72749
|
init_processSpawn();
|
|
71876
|
-
import {
|
|
72750
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
72751
|
+
import {
|
|
72752
|
+
cpSync,
|
|
72753
|
+
existsSync as existsSync9,
|
|
72754
|
+
mkdirSync as mkdirSync6,
|
|
72755
|
+
readFileSync as readFileSync8,
|
|
72756
|
+
readdirSync as readdirSync3,
|
|
72757
|
+
renameSync,
|
|
72758
|
+
rmSync as rmSync2,
|
|
72759
|
+
statSync as statSync2,
|
|
72760
|
+
writeFileSync as writeFileSync5
|
|
72761
|
+
} from "node:fs";
|
|
72762
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
71877
72763
|
import { dirname as dirname7, join as join10 } from "node:path";
|
|
71878
72764
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
71879
|
-
var
|
|
71880
|
-
|
|
72765
|
+
var CLI_DOWNLOADS_SUBPATH = "cli";
|
|
72766
|
+
function getCliInstallChannel(serverUrl) {
|
|
72767
|
+
const normalized = typeof serverUrl === "string" ? serverUrl.trim().replace(/\/+$/, "") : "";
|
|
72768
|
+
if (!normalized) {
|
|
72769
|
+
return "latest";
|
|
72770
|
+
}
|
|
72771
|
+
try {
|
|
72772
|
+
const hostname2 = new URL(normalized).hostname.toLowerCase();
|
|
72773
|
+
if (hostname2 === "us.nolo.chat" || hostname2.endsWith(".us.nolo.chat")) {
|
|
72774
|
+
return "alpha";
|
|
72775
|
+
}
|
|
72776
|
+
} catch {
|
|
72777
|
+
if (/us\.nolo\.chat/i.test(normalized)) {
|
|
72778
|
+
return "alpha";
|
|
72779
|
+
}
|
|
72780
|
+
}
|
|
72781
|
+
return "latest";
|
|
72782
|
+
}
|
|
72783
|
+
function resolveBundleUpdateChannel(args2) {
|
|
72784
|
+
const fromServer = getCliInstallChannel(args2.serverUrl);
|
|
72785
|
+
const fromInstall = args2.install.manifest.channel;
|
|
72786
|
+
if (fromInstall && fromInstall !== fromServer) {
|
|
72787
|
+
args2.output?.write(
|
|
72788
|
+
`[nolo] Warning: server channel (${fromServer}) differs from installed bundle channel (${fromInstall}); using installed channel.
|
|
72789
|
+
`
|
|
72790
|
+
);
|
|
72791
|
+
return fromInstall;
|
|
72792
|
+
}
|
|
72793
|
+
return fromServer;
|
|
72794
|
+
}
|
|
72795
|
+
function resolveCliBundlePlatform() {
|
|
72796
|
+
const { platform: platform2, arch: arch2 } = process;
|
|
72797
|
+
if (platform2 === "linux" && (arch2 === "x64" || arch2 === "amd64")) {
|
|
72798
|
+
return "linux-x64";
|
|
72799
|
+
}
|
|
72800
|
+
if (platform2 === "darwin" && arch2 === "arm64") {
|
|
72801
|
+
return "darwin-arm64";
|
|
72802
|
+
}
|
|
72803
|
+
if (platform2 === "darwin" && (arch2 === "x64" || arch2 === "amd64")) {
|
|
72804
|
+
return "darwin-x64";
|
|
72805
|
+
}
|
|
72806
|
+
if (platform2 === "win32" && (arch2 === "x64" || arch2 === "amd64")) {
|
|
72807
|
+
return "win-x64";
|
|
72808
|
+
}
|
|
72809
|
+
return null;
|
|
72810
|
+
}
|
|
72811
|
+
function detectStandaloneBundleInstall(entrypointPath) {
|
|
72812
|
+
const cliDir = entrypointPath ? entrypointPath.startsWith("file:") ? dirname7(fileURLToPath4(entrypointPath)) : dirname7(entrypointPath) : dirname7(fileURLToPath4(import.meta.url));
|
|
72813
|
+
const bundleRoot = join10(cliDir, "..", "..");
|
|
72814
|
+
const manifestPath = join10(bundleRoot, "manifest.json");
|
|
72815
|
+
if (!existsSync9(manifestPath)) {
|
|
72816
|
+
return null;
|
|
72817
|
+
}
|
|
72818
|
+
try {
|
|
72819
|
+
const manifest = JSON.parse(
|
|
72820
|
+
readFileSync8(manifestPath, "utf8")
|
|
72821
|
+
);
|
|
72822
|
+
if (manifest?.name !== "nolo-cli" || manifest?.schemaVersion !== 1) {
|
|
72823
|
+
return null;
|
|
72824
|
+
}
|
|
72825
|
+
const entrypoint = join10(cliDir, "index.js");
|
|
72826
|
+
if (!existsSync9(entrypoint)) {
|
|
72827
|
+
return null;
|
|
72828
|
+
}
|
|
72829
|
+
return { bundleRoot, cliDir, manifest };
|
|
72830
|
+
} catch {
|
|
72831
|
+
return null;
|
|
72832
|
+
}
|
|
72833
|
+
}
|
|
72834
|
+
function buildBundleManifestUrl(args2) {
|
|
72835
|
+
const origin = args2.serverUrl.trim().replace(/\/+$/, "");
|
|
72836
|
+
return `${origin}/public/downloads/${CLI_DOWNLOADS_SUBPATH}/nolo-cli-${args2.channel}-${args2.platform}-manifest.json`;
|
|
72837
|
+
}
|
|
72838
|
+
function buildNpmSelfUpdateCommand(channel = "latest") {
|
|
72839
|
+
return ["npm", "install", "-g", `nolo-cli@${channel}`, "--force"];
|
|
72840
|
+
}
|
|
72841
|
+
function validatePublishedBundleManifest(args2) {
|
|
72842
|
+
if (args2.published.schemaVersion !== 1) {
|
|
72843
|
+
throw new Error(
|
|
72844
|
+
`Unsupported standalone bundle manifest schema: ${args2.published.schemaVersion}`
|
|
72845
|
+
);
|
|
72846
|
+
}
|
|
72847
|
+
if (args2.published.channel !== args2.expectedChannel) {
|
|
72848
|
+
throw new Error(
|
|
72849
|
+
`Standalone bundle manifest channel mismatch (expected ${args2.expectedChannel}, got ${args2.published.channel})`
|
|
72850
|
+
);
|
|
72851
|
+
}
|
|
72852
|
+
if (args2.published.platform !== args2.expectedPlatform) {
|
|
72853
|
+
throw new Error(
|
|
72854
|
+
`Standalone bundle manifest platform mismatch (expected ${args2.expectedPlatform}, got ${args2.published.platform})`
|
|
72855
|
+
);
|
|
72856
|
+
}
|
|
72857
|
+
if (!args2.published.fileName || !args2.published.url || !args2.published.sha256) {
|
|
72858
|
+
throw new Error("Standalone bundle manifest is missing required fields");
|
|
72859
|
+
}
|
|
72860
|
+
}
|
|
72861
|
+
async function runCommand(command2, spawn6 = resolveDefaultSpawn(), env = process.env) {
|
|
72862
|
+
const proc = spawn6({
|
|
72863
|
+
cmd: command2,
|
|
72864
|
+
stdin: "ignore",
|
|
72865
|
+
stdout: "inherit",
|
|
72866
|
+
stderr: "inherit",
|
|
72867
|
+
env
|
|
72868
|
+
});
|
|
72869
|
+
return proc.exited;
|
|
72870
|
+
}
|
|
72871
|
+
function hashFile(path7) {
|
|
72872
|
+
const hash = createHash3("sha256");
|
|
72873
|
+
hash.update(readFileSync8(path7));
|
|
72874
|
+
return hash.digest("hex");
|
|
72875
|
+
}
|
|
72876
|
+
function fileSize(path7) {
|
|
72877
|
+
return statSync2(path7).size;
|
|
72878
|
+
}
|
|
72879
|
+
async function downloadFile(url, destinationPath) {
|
|
72880
|
+
const response = await fetch(url);
|
|
72881
|
+
if (!response.ok) {
|
|
72882
|
+
throw new Error(`Download failed (${response.status}): ${url}`);
|
|
72883
|
+
}
|
|
72884
|
+
const bytes = await response.arrayBuffer();
|
|
72885
|
+
mkdirSync6(dirname7(destinationPath), { recursive: true });
|
|
72886
|
+
writeFileSync5(destinationPath, Buffer.from(bytes));
|
|
72887
|
+
}
|
|
72888
|
+
function assertCliDir(cliDir) {
|
|
72889
|
+
const entrypoint = join10(cliDir, "index.js");
|
|
72890
|
+
if (!existsSync9(entrypoint)) {
|
|
72891
|
+
throw new Error(`Standalone CLI layout is invalid: missing ${entrypoint}`);
|
|
72892
|
+
}
|
|
72893
|
+
}
|
|
72894
|
+
async function extractArchive(args2) {
|
|
72895
|
+
mkdirSync6(args2.destDir, { recursive: true });
|
|
72896
|
+
const spawn6 = args2.spawn ?? resolveDefaultSpawn();
|
|
72897
|
+
const env = args2.env ?? process.env;
|
|
72898
|
+
if (args2.archivePath.endsWith(".zip")) {
|
|
72899
|
+
if (process.platform === "win32") {
|
|
72900
|
+
const command2 = [
|
|
72901
|
+
"powershell",
|
|
72902
|
+
"-NoProfile",
|
|
72903
|
+
"-Command",
|
|
72904
|
+
`Expand-Archive -Path '${args2.archivePath.replace(/'/g, "''")}' -DestinationPath '${args2.destDir.replace(/'/g, "''")}' -Force`
|
|
72905
|
+
];
|
|
72906
|
+
return runCommand(command2, spawn6, env);
|
|
72907
|
+
}
|
|
72908
|
+
return runCommand(["unzip", "-qo", args2.archivePath, "-d", args2.destDir], spawn6, env);
|
|
72909
|
+
}
|
|
72910
|
+
return runCommand(["tar", "--zstd", "-xf", args2.archivePath, "-C", args2.destDir], spawn6, env);
|
|
72911
|
+
}
|
|
72912
|
+
function findExtractedBundleRoot(extractDir) {
|
|
72913
|
+
const matches = readdirSync3(extractDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("nolo-cli-")).map((entry) => join10(extractDir, entry.name));
|
|
72914
|
+
if (matches.length === 1) {
|
|
72915
|
+
return matches[0];
|
|
72916
|
+
}
|
|
72917
|
+
throw new Error(
|
|
72918
|
+
`Could not locate extracted standalone CLI bundle under ${extractDir}`
|
|
72919
|
+
);
|
|
72920
|
+
}
|
|
72921
|
+
function atomicReplaceDirectory(args2) {
|
|
72922
|
+
assertCliDir(args2.sourceDir);
|
|
72923
|
+
const parent = dirname7(args2.targetDir);
|
|
72924
|
+
mkdirSync6(parent, { recursive: true });
|
|
72925
|
+
const stagingDir = `${args2.targetDir}.staging-${process.pid}`;
|
|
72926
|
+
const backupDir = `${args2.targetDir}.backup-${process.pid}`;
|
|
72927
|
+
rmSync2(stagingDir, { recursive: true, force: true });
|
|
72928
|
+
cpSync(args2.sourceDir, stagingDir, { recursive: true });
|
|
72929
|
+
assertCliDir(stagingDir);
|
|
72930
|
+
if (existsSync9(args2.targetDir)) {
|
|
72931
|
+
rmSync2(backupDir, { recursive: true, force: true });
|
|
72932
|
+
renameSync(args2.targetDir, backupDir);
|
|
72933
|
+
}
|
|
72934
|
+
try {
|
|
72935
|
+
renameSync(stagingDir, args2.targetDir);
|
|
72936
|
+
} catch (error) {
|
|
72937
|
+
if (existsSync9(backupDir) && !existsSync9(args2.targetDir)) {
|
|
72938
|
+
renameSync(backupDir, args2.targetDir);
|
|
72939
|
+
}
|
|
72940
|
+
throw error;
|
|
72941
|
+
}
|
|
72942
|
+
rmSync2(backupDir, { recursive: true, force: true });
|
|
72943
|
+
rmSync2(stagingDir, { recursive: true, force: true });
|
|
72944
|
+
}
|
|
72945
|
+
function replaceFileWithFallback(args2) {
|
|
72946
|
+
if (!existsSync9(args2.sourcePath)) {
|
|
72947
|
+
return;
|
|
72948
|
+
}
|
|
72949
|
+
mkdirSync6(dirname7(args2.targetPath), { recursive: true });
|
|
72950
|
+
const pendingPath = `${args2.targetPath}.pending-${process.pid}`;
|
|
72951
|
+
cpSync(args2.sourcePath, pendingPath);
|
|
72952
|
+
try {
|
|
72953
|
+
rmSync2(args2.targetPath, { force: true });
|
|
72954
|
+
renameSync(pendingPath, args2.targetPath);
|
|
72955
|
+
} catch (error) {
|
|
72956
|
+
rmSync2(pendingPath, { force: true });
|
|
72957
|
+
args2.output?.write(
|
|
72958
|
+
`[nolo] Warning: could not replace ${args2.targetPath} (${error instanceof Error ? error.message : String(error)}). Restart all nolo processes and run nolo update again.
|
|
72959
|
+
`
|
|
72960
|
+
);
|
|
72961
|
+
}
|
|
72962
|
+
}
|
|
72963
|
+
function replaceStandaloneBundleContents(args2) {
|
|
72964
|
+
const nextCliDir = join10(args2.nextRoot, "lib", "nolo-cli");
|
|
72965
|
+
const currentCliDir = join10(args2.currentRoot, "lib", "nolo-cli");
|
|
72966
|
+
if (!existsSync9(nextCliDir)) {
|
|
72967
|
+
throw new Error(`Downloaded bundle is missing ${nextCliDir}`);
|
|
72968
|
+
}
|
|
72969
|
+
atomicReplaceDirectory({
|
|
72970
|
+
targetDir: currentCliDir,
|
|
72971
|
+
sourceDir: nextCliDir
|
|
72972
|
+
});
|
|
72973
|
+
for (const relativePath of ["VERSION", "manifest.json"]) {
|
|
72974
|
+
const source = join10(args2.nextRoot, relativePath);
|
|
72975
|
+
if (existsSync9(source)) {
|
|
72976
|
+
replaceFileWithFallback({
|
|
72977
|
+
sourcePath: source,
|
|
72978
|
+
targetPath: join10(args2.currentRoot, relativePath),
|
|
72979
|
+
output: args2.output
|
|
72980
|
+
});
|
|
72981
|
+
}
|
|
72982
|
+
}
|
|
72983
|
+
const bunName = process.platform === "win32" ? "bun.exe" : "bun";
|
|
72984
|
+
replaceFileWithFallback({
|
|
72985
|
+
sourcePath: join10(args2.nextRoot, "bin", bunName),
|
|
72986
|
+
targetPath: join10(args2.currentRoot, "bin", bunName),
|
|
72987
|
+
output: args2.output
|
|
72988
|
+
});
|
|
72989
|
+
const launcherName = process.platform === "win32" ? "nolo.cmd" : "nolo";
|
|
72990
|
+
replaceFileWithFallback({
|
|
72991
|
+
sourcePath: join10(args2.nextRoot, "bin", launcherName),
|
|
72992
|
+
targetPath: join10(args2.currentRoot, "bin", launcherName),
|
|
72993
|
+
output: args2.output
|
|
72994
|
+
});
|
|
72995
|
+
}
|
|
72996
|
+
async function runStandaloneBundleUpdate(args2) {
|
|
72997
|
+
const output2 = args2.output ?? process.stdout;
|
|
72998
|
+
const env = args2.env ?? process.env;
|
|
72999
|
+
const platform2 = resolveCliBundlePlatform() ?? args2.install.manifest.platform ?? null;
|
|
73000
|
+
if (!platform2) {
|
|
73001
|
+
throw new Error(
|
|
73002
|
+
`Standalone CLI self-update is not supported on ${process.platform}/${process.arch}`
|
|
73003
|
+
);
|
|
73004
|
+
}
|
|
73005
|
+
const channel = resolveBundleUpdateChannel({
|
|
73006
|
+
install: args2.install,
|
|
73007
|
+
serverUrl: args2.serverUrl,
|
|
73008
|
+
output: output2
|
|
73009
|
+
});
|
|
73010
|
+
const manifestUrl = buildBundleManifestUrl({
|
|
73011
|
+
serverUrl: args2.serverUrl,
|
|
73012
|
+
channel,
|
|
73013
|
+
platform: platform2
|
|
73014
|
+
});
|
|
73015
|
+
output2.write(`Checking standalone bundle update: ${manifestUrl}
|
|
73016
|
+
`);
|
|
73017
|
+
const response = await fetch(manifestUrl, { cache: "no-store" });
|
|
73018
|
+
if (!response.ok) {
|
|
73019
|
+
throw new Error(
|
|
73020
|
+
`Standalone bundle manifest not found (${response.status}). Publish the CLI bundle for ${channel}/${platform2} first.`
|
|
73021
|
+
);
|
|
73022
|
+
}
|
|
73023
|
+
const published = await response.json();
|
|
73024
|
+
validatePublishedBundleManifest({
|
|
73025
|
+
published,
|
|
73026
|
+
expectedChannel: channel,
|
|
73027
|
+
expectedPlatform: platform2
|
|
73028
|
+
});
|
|
73029
|
+
const currentVersion = args2.install.manifest.version;
|
|
73030
|
+
if (published.version === currentVersion) {
|
|
73031
|
+
output2.write(`Already on latest standalone bundle (${currentVersion}).
|
|
73032
|
+
`);
|
|
73033
|
+
return 0;
|
|
73034
|
+
}
|
|
73035
|
+
const workDir = join10(tmpdir2(), `nolo-cli-update-${process.pid}`);
|
|
73036
|
+
rmSync2(workDir, { recursive: true, force: true });
|
|
73037
|
+
mkdirSync6(workDir, { recursive: true });
|
|
73038
|
+
try {
|
|
73039
|
+
const archivePath = join10(workDir, published.fileName);
|
|
73040
|
+
output2.write(
|
|
73041
|
+
`Updating standalone bundle ${currentVersion} -> ${published.version}
|
|
73042
|
+
`
|
|
73043
|
+
);
|
|
73044
|
+
output2.write(`Downloading ${published.url}
|
|
73045
|
+
`);
|
|
73046
|
+
await downloadFile(published.url, archivePath);
|
|
73047
|
+
const actualSize = fileSize(archivePath);
|
|
73048
|
+
if (actualSize !== published.size) {
|
|
73049
|
+
throw new Error(
|
|
73050
|
+
`Downloaded bundle size mismatch (expected ${published.size} bytes, got ${actualSize} bytes)`
|
|
73051
|
+
);
|
|
73052
|
+
}
|
|
73053
|
+
const actualSha256 = hashFile(archivePath);
|
|
73054
|
+
if (actualSha256 !== published.sha256) {
|
|
73055
|
+
throw new Error(
|
|
73056
|
+
`Downloaded bundle checksum mismatch (expected ${published.sha256}, got ${actualSha256})`
|
|
73057
|
+
);
|
|
73058
|
+
}
|
|
73059
|
+
const extractDir = join10(workDir, "extracted");
|
|
73060
|
+
const exitCode2 = await extractArchive({
|
|
73061
|
+
archivePath,
|
|
73062
|
+
destDir: extractDir,
|
|
73063
|
+
spawn: args2.spawn,
|
|
73064
|
+
env
|
|
73065
|
+
});
|
|
73066
|
+
if (exitCode2 !== 0) {
|
|
73067
|
+
throw new Error("Failed to extract standalone bundle archive");
|
|
73068
|
+
}
|
|
73069
|
+
const nextRoot = findExtractedBundleRoot(extractDir);
|
|
73070
|
+
replaceStandaloneBundleContents({
|
|
73071
|
+
currentRoot: args2.install.bundleRoot,
|
|
73072
|
+
nextRoot,
|
|
73073
|
+
output: output2
|
|
73074
|
+
});
|
|
73075
|
+
output2.write(`Standalone bundle updated to ${published.version}.
|
|
73076
|
+
`);
|
|
73077
|
+
output2.write("Restart open nolo sessions to use the new version.\n");
|
|
73078
|
+
return 0;
|
|
73079
|
+
} finally {
|
|
73080
|
+
rmSync2(workDir, { recursive: true, force: true });
|
|
73081
|
+
}
|
|
73082
|
+
}
|
|
73083
|
+
|
|
73084
|
+
// packages/cli/updateCommands.ts
|
|
73085
|
+
init_defaultServer();
|
|
73086
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
73087
|
+
import { dirname as dirname8, join as join11 } from "node:path";
|
|
73088
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
73089
|
+
init_processSpawn();
|
|
73090
|
+
var CLI_DIR2 = dirname8(fileURLToPath5(import.meta.url));
|
|
73091
|
+
var PACKAGE_JSON_PATH = join11(CLI_DIR2, "package.json");
|
|
71881
73092
|
function readPackageInfo() {
|
|
71882
|
-
const raw =
|
|
73093
|
+
const raw = readFileSync9(PACKAGE_JSON_PATH, "utf8");
|
|
71883
73094
|
const parsed = JSON.parse(raw);
|
|
71884
73095
|
return {
|
|
71885
73096
|
name: parsed.name || "nolo-cli",
|
|
@@ -71889,28 +73100,42 @@ function readPackageInfo() {
|
|
|
71889
73100
|
function buildCliVersionText(info) {
|
|
71890
73101
|
return `${info.name} ${info.version}`;
|
|
71891
73102
|
}
|
|
71892
|
-
function
|
|
71893
|
-
|
|
73103
|
+
function resolveSelfUpdateServerUrl(env = process.env, override) {
|
|
73104
|
+
if (override?.trim()) {
|
|
73105
|
+
return override.trim().replace(/\/+$/, "");
|
|
73106
|
+
}
|
|
73107
|
+
const fromEnv = env.NOLO_SERVER || env.BASE_URL;
|
|
73108
|
+
if (typeof fromEnv === "string" && fromEnv.trim()) {
|
|
73109
|
+
return fromEnv.trim().replace(/\/+$/, "");
|
|
73110
|
+
}
|
|
73111
|
+
const profile = loadProfileConfig();
|
|
73112
|
+
const profileUrl = profile?.profiles?.[profile.currentProfile]?.serverUrl;
|
|
73113
|
+
if (profileUrl?.trim()) {
|
|
73114
|
+
return profileUrl.trim().replace(/\/+$/, "");
|
|
73115
|
+
}
|
|
73116
|
+
return DEFAULT_NOLO_SERVER_URL;
|
|
71894
73117
|
}
|
|
71895
73118
|
function buildCliDoctorText(info) {
|
|
71896
|
-
const updateCommand =
|
|
73119
|
+
const updateCommand = info.installKind === "standalone-bundle" ? "nolo update" : buildNpmSelfUpdateCommand(info.updateChannel).join(" ");
|
|
71897
73120
|
return [
|
|
71898
73121
|
"Nolo CLI doctor",
|
|
71899
73122
|
"---------------",
|
|
71900
73123
|
`version ${info.packageName} ${info.version}`,
|
|
73124
|
+
`install ${info.installKind}`,
|
|
73125
|
+
`channel ${info.updateChannel}`,
|
|
71901
73126
|
`entry ${info.entrypoint}`,
|
|
71902
73127
|
`server ${info.serverUrl}`,
|
|
71903
73128
|
`profile ${info.profileName}`,
|
|
71904
73129
|
`update nolo update`,
|
|
71905
73130
|
"",
|
|
71906
73131
|
"If direct `nolo` differs from repo-local `bun ./packages/cli/index.ts`,",
|
|
71907
|
-
"the global
|
|
73132
|
+
"the global install is older than this checkout.",
|
|
71908
73133
|
"",
|
|
71909
73134
|
`Manual update: ${updateCommand}`
|
|
71910
73135
|
].join("\n");
|
|
71911
73136
|
}
|
|
71912
73137
|
function isRunSelfUpdateOptions(value) {
|
|
71913
|
-
return typeof value === "object" && value !== null && ("output" in value || "spawn" in value);
|
|
73138
|
+
return typeof value === "object" && value !== null && ("output" in value || "spawn" in value || "entrypointPath" in value || "serverUrl" in value || "env" in value);
|
|
71914
73139
|
}
|
|
71915
73140
|
async function forwardSpawnOutput(stream, output2) {
|
|
71916
73141
|
if (!stream) {
|
|
@@ -71933,7 +73158,20 @@ async function runSelfUpdate(outputOrOptions) {
|
|
|
71933
73158
|
const options = outputOrOptions === void 0 ? {} : isRunSelfUpdateOptions(outputOrOptions) ? outputOrOptions : { output: outputOrOptions };
|
|
71934
73159
|
const output2 = options.output ?? process.stdout;
|
|
71935
73160
|
const spawn6 = options.spawn ?? resolveDefaultSpawn();
|
|
71936
|
-
const
|
|
73161
|
+
const env = options.env ?? process.env;
|
|
73162
|
+
const serverUrl = resolveSelfUpdateServerUrl(env, options.serverUrl);
|
|
73163
|
+
const entrypointPath = options.entrypointPath ?? join11(CLI_DIR2, "index.js");
|
|
73164
|
+
const bundleInstall = detectStandaloneBundleInstall(entrypointPath);
|
|
73165
|
+
if (bundleInstall) {
|
|
73166
|
+
return runStandaloneBundleUpdate({
|
|
73167
|
+
install: bundleInstall,
|
|
73168
|
+
serverUrl,
|
|
73169
|
+
output: output2,
|
|
73170
|
+
spawn: spawn6,
|
|
73171
|
+
env
|
|
73172
|
+
});
|
|
73173
|
+
}
|
|
73174
|
+
const command2 = buildNpmSelfUpdateCommand(getCliInstallChannel(serverUrl));
|
|
71937
73175
|
output2.write(`Updating nolo with: ${command2.join(" ")}
|
|
71938
73176
|
`);
|
|
71939
73177
|
const useCustomSink = options.output !== void 0;
|
|
@@ -71942,7 +73180,7 @@ async function runSelfUpdate(outputOrOptions) {
|
|
|
71942
73180
|
stdin: "inherit",
|
|
71943
73181
|
stdout: useCustomSink ? "pipe" : "inherit",
|
|
71944
73182
|
stderr: useCustomSink ? "pipe" : "inherit",
|
|
71945
|
-
env
|
|
73183
|
+
env
|
|
71946
73184
|
});
|
|
71947
73185
|
if (!useCustomSink) {
|
|
71948
73186
|
return await proc.exited;
|
|
@@ -71960,24 +73198,43 @@ function getSystemInternalCommandEntries(renderHelpText2) {
|
|
|
71960
73198
|
return [
|
|
71961
73199
|
createEnvCommand(["doctor", "runtime"], "Diagnose local-first agent runtime selection", runDoctorRuntimeCommand),
|
|
71962
73200
|
createArgsCommand(["login"], "Log in to Nolo", (args2) => Promise.resolve(runLoginCommand(args2))),
|
|
71963
|
-
|
|
71964
|
-
|
|
73201
|
+
createContextCommand(
|
|
73202
|
+
["logout"],
|
|
73203
|
+
"Log out of Nolo",
|
|
73204
|
+
async (args2, ctx) => runLogoutCommand({ args: args2, env: ctx.env })
|
|
73205
|
+
),
|
|
73206
|
+
createContextCommand(
|
|
73207
|
+
["whoami"],
|
|
73208
|
+
"Show the current login state",
|
|
73209
|
+
async (args2, ctx) => runWhoamiCommand({ args: args2, env: ctx.env })
|
|
73210
|
+
),
|
|
71965
73211
|
createEntrypointEnvCommand(["connect"], "Send machine heartbeats or hold a connector websocket", runMachineConnectCommand),
|
|
71966
73212
|
createDaemonShortcutCommand(["daemon"], "Run the connector daemon shortcut", runMachineConnectCommand),
|
|
71967
73213
|
createEnvCommand(["machine", "status"], "List machines registered to the current profile", runMachineStatusCommand),
|
|
71968
73214
|
createContextCommand(["doctor"], "Show CLI doctor information", async (_args, ctx) => {
|
|
73215
|
+
const serverUrl = resolveSelfUpdateServerUrl(ctx.env);
|
|
71969
73216
|
console.log(
|
|
71970
73217
|
buildCliDoctorText({
|
|
71971
73218
|
packageName: ctx.packageInfo.name,
|
|
71972
73219
|
version: ctx.packageInfo.version,
|
|
71973
73220
|
entrypoint: ctx.entrypointPath,
|
|
71974
|
-
serverUrl
|
|
71975
|
-
profileName: ctx.env.NOLO_PROFILE || "local"
|
|
73221
|
+
serverUrl,
|
|
73222
|
+
profileName: ctx.env.NOLO_PROFILE || "local",
|
|
73223
|
+
installKind: detectStandaloneBundleInstall(ctx.entrypointPath) ? "standalone-bundle" : "npm-global",
|
|
73224
|
+
updateChannel: getCliInstallChannel(serverUrl)
|
|
71976
73225
|
})
|
|
71977
73226
|
);
|
|
71978
73227
|
return 0;
|
|
71979
73228
|
}),
|
|
71980
|
-
|
|
73229
|
+
createContextCommand(
|
|
73230
|
+
["update"],
|
|
73231
|
+
"Update the CLI",
|
|
73232
|
+
async (_args, ctx) => runSelfUpdate({
|
|
73233
|
+
entrypointPath: ctx.entrypointPath,
|
|
73234
|
+
serverUrl: resolveSelfUpdateServerUrl(ctx.env),
|
|
73235
|
+
env: ctx.env
|
|
73236
|
+
})
|
|
73237
|
+
),
|
|
71981
73238
|
createContextCommand(["version"], "Show CLI version", async (_args, ctx) => {
|
|
71982
73239
|
console.log(buildCliVersionText(ctx.packageInfo));
|
|
71983
73240
|
return 0;
|
|
@@ -72559,7 +73816,6 @@ function renderHelpText() {
|
|
|
72559
73816
|
" nolo space list --json",
|
|
72560
73817
|
" nolo agent pull agent-pub-01APPBUILDER00000001YAII3I",
|
|
72561
73818
|
" nolo agent read agent-pub-01APPBUILDER00000001YAII3I",
|
|
72562
|
-
" nolo agent usage qoder",
|
|
72563
73819
|
' nolo agent run frontend-implementer --msg "polish notifications"',
|
|
72564
73820
|
" nolo agent bind-current agent-user-1-agent-1",
|
|
72565
73821
|
" nolo agent runtime-doctor agent-user-1-agent-1",
|
|
@@ -72654,7 +73910,7 @@ function resolveTuiLaunchMode(args2) {
|
|
|
72654
73910
|
// packages/cli/tui/readlineWorkspace.ts
|
|
72655
73911
|
import { createInterface as createInterface2 } from "node:readline";
|
|
72656
73912
|
import { stdin as defaultInput, stdout as defaultOutput } from "node:process";
|
|
72657
|
-
import { join as
|
|
73913
|
+
import { join as join12 } from "node:path";
|
|
72658
73914
|
|
|
72659
73915
|
// packages/cli/client/compactDialog.ts
|
|
72660
73916
|
import { ulid as ulid11 } from "ulid";
|
|
@@ -72802,23 +74058,410 @@ async function compactDialog(options) {
|
|
|
72802
74058
|
// packages/cli/tui/readlineWorkspace.ts
|
|
72803
74059
|
init_processSpawn();
|
|
72804
74060
|
|
|
72805
|
-
// packages/cli/tui/
|
|
72806
|
-
|
|
74061
|
+
// packages/cli/tui/agentPicker.ts
|
|
74062
|
+
init_agentAliases();
|
|
74063
|
+
|
|
74064
|
+
// packages/cli/tui/agentCatalog.ts
|
|
74065
|
+
init_cliEnvHelpers();
|
|
72807
74066
|
var DEFAULT_TUI_AGENT_KEY = "agent-pub-01NOLOAPPBLD000000019KCKT0";
|
|
72808
|
-
var
|
|
72809
|
-
var KNOWN_AGENTS = [
|
|
74067
|
+
var PLATFORM_AGENTS = [
|
|
72810
74068
|
{
|
|
72811
74069
|
name: "nolo",
|
|
72812
|
-
key:
|
|
74070
|
+
key: DEFAULT_TUI_AGENT_KEY,
|
|
74071
|
+
model: "-",
|
|
74072
|
+
kind: "platform",
|
|
72813
74073
|
description: "one assistant that routes work across your agents and data"
|
|
72814
74074
|
},
|
|
72815
74075
|
{
|
|
72816
74076
|
name: "app-builder",
|
|
72817
74077
|
key: "agent-pub-01APPBUILDER00000001YAII3I",
|
|
74078
|
+
model: "-",
|
|
74079
|
+
kind: "platform",
|
|
72818
74080
|
description: "builds web apps, tools, charts, and product prototypes"
|
|
72819
74081
|
}
|
|
72820
74082
|
];
|
|
72821
|
-
|
|
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;
|
|
72822
74465
|
function shortenDialogId(dialogId) {
|
|
72823
74466
|
return dialogId.length > 12 ? `${dialogId.slice(0, 6)}...${dialogId.slice(-4)}` : dialogId;
|
|
72824
74467
|
}
|
|
@@ -72840,25 +74483,29 @@ function createInitialTuiState(env = process.env) {
|
|
|
72840
74483
|
),
|
|
72841
74484
|
cliVersion: env.NOLO_CLI_VERSION?.trim() || void 0,
|
|
72842
74485
|
attachedDocs: [],
|
|
72843
|
-
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")
|
|
72844
74493
|
};
|
|
72845
74494
|
}
|
|
72846
74495
|
function renderStatusLine(state) {
|
|
72847
|
-
const
|
|
72848
|
-
|
|
72849
|
-
|
|
72850
|
-
|
|
72851
|
-
|
|
72852
|
-
|
|
72853
|
-
|
|
72854
|
-
].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
|
+
);
|
|
72855
74503
|
}
|
|
72856
74504
|
function renderWelcome(state) {
|
|
72857
|
-
const docs = state.attachedDocs.length > 0 ? `${state.attachedDocs.length} attached` : "none";
|
|
72858
74505
|
return [
|
|
72859
74506
|
"",
|
|
72860
74507
|
`Nolo workspace${state.cliVersion ? ` nolo ${state.cliVersion}` : ""}`,
|
|
72861
|
-
`agent ${state.agentName} |
|
|
74508
|
+
`agent ${state.agentName} | ${renderTokenStatus(state.turnTokens)} | profile ${state.profileName}`,
|
|
72862
74509
|
`server ${state.serverUrl}`,
|
|
72863
74510
|
"",
|
|
72864
74511
|
"Tell nolo what you want. Use /help for commands. Use /version if this install feels stale.",
|
|
@@ -72876,16 +74523,21 @@ function renderTuiHelp() {
|
|
|
72876
74523
|
" /compact Compact current dialog and fork a new one",
|
|
72877
74524
|
" /context Show workspace context and next actions",
|
|
72878
74525
|
" /runtime <mode> Use auto, local, or server runtime",
|
|
72879
|
-
" /
|
|
72880
|
-
" /
|
|
72881
|
-
" /
|
|
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>)",
|
|
72882
74534
|
" /dialog Show the current dialog",
|
|
72883
74535
|
" /doc List attached docs",
|
|
72884
74536
|
" /doc attach <doc> Attach a doc to this workspace",
|
|
72885
74537
|
" /customize Describe how you want to tune nolo",
|
|
72886
74538
|
" /login Show login/profile hint",
|
|
72887
74539
|
" /profile Show active profile",
|
|
72888
|
-
" /update Update the
|
|
74540
|
+
" /update Update the nolo CLI install",
|
|
72889
74541
|
" /version Show version/update hint",
|
|
72890
74542
|
" /exit Leave the workspace",
|
|
72891
74543
|
"",
|
|
@@ -72897,12 +74549,16 @@ function renderContextPanel(state) {
|
|
|
72897
74549
|
return [
|
|
72898
74550
|
"Workspace context",
|
|
72899
74551
|
"-----------------",
|
|
72900
|
-
`agent
|
|
72901
|
-
`
|
|
72902
|
-
`
|
|
72903
|
-
`
|
|
72904
|
-
`
|
|
72905
|
-
`
|
|
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}`,
|
|
72906
74562
|
"",
|
|
72907
74563
|
"Next:",
|
|
72908
74564
|
" /agents see specialist shortcuts",
|
|
@@ -72913,25 +74569,22 @@ function renderContextPanel(state) {
|
|
|
72913
74569
|
function renderKnownAgents() {
|
|
72914
74570
|
return [
|
|
72915
74571
|
"Agents:",
|
|
72916
|
-
...
|
|
72917
|
-
(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 ?? ""}`
|
|
72918
74574
|
),
|
|
72919
74575
|
"",
|
|
72920
|
-
"Tip:
|
|
74576
|
+
"Tip: run /agent for the full picker, or /agent list for your private agents too."
|
|
72921
74577
|
].join("\n");
|
|
72922
74578
|
}
|
|
72923
|
-
function
|
|
72924
|
-
|
|
72925
|
-
|
|
72926
|
-
|
|
72927
|
-
|
|
72928
|
-
|
|
72929
|
-
|
|
72930
|
-
|
|
72931
|
-
|
|
72932
|
-
return { name: target, key: target };
|
|
72933
|
-
}
|
|
72934
|
-
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
|
+
};
|
|
72935
74588
|
}
|
|
72936
74589
|
var DIALOG_ID_PATTERN = /[0-9A-HJKMNP-TV-Z]{26}/i;
|
|
72937
74590
|
var DIALOG_KEY_PATTERN = /dialog-[^\s"'<>]+-[0-9A-HJKMNP-TV-Z]{26}/i;
|
|
@@ -73109,6 +74762,66 @@ function handleTuiInput(input2, state) {
|
|
|
73109
74762
|
output: `Runtime: ${argText}`
|
|
73110
74763
|
};
|
|
73111
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
|
+
}
|
|
73112
74825
|
case "/exit":
|
|
73113
74826
|
case "/quit":
|
|
73114
74827
|
return { nextState: state, output: "Bye.", action: { type: "exit" } };
|
|
@@ -73118,7 +74831,8 @@ function handleTuiInput(input2, state) {
|
|
|
73118
74831
|
...state,
|
|
73119
74832
|
dialogId: void 0,
|
|
73120
74833
|
dialogLabel: "new",
|
|
73121
|
-
attachedDocs: []
|
|
74834
|
+
attachedDocs: [],
|
|
74835
|
+
turnTokens: void 0
|
|
73122
74836
|
},
|
|
73123
74837
|
output: "Started a fresh dialog."
|
|
73124
74838
|
};
|
|
@@ -73142,11 +74856,37 @@ ${renderTuiHelp()}`
|
|
|
73142
74856
|
output: "Compacting current dialog...",
|
|
73143
74857
|
action: { type: "compact", dialogId: state.dialogId }
|
|
73144
74858
|
};
|
|
73145
|
-
case "/agent":
|
|
73146
|
-
|
|
73147
|
-
|
|
73148
|
-
|
|
73149
|
-
|
|
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
|
+
}
|
|
73150
74890
|
case "/agents":
|
|
73151
74891
|
return {
|
|
73152
74892
|
nextState: state,
|
|
@@ -73156,25 +74896,18 @@ ${renderTuiHelp()}`
|
|
|
73156
74896
|
if (!argText) {
|
|
73157
74897
|
return {
|
|
73158
74898
|
nextState: state,
|
|
73159
|
-
output: "Usage: /switch <agent-key|alias>"
|
|
74899
|
+
output: "Usage: /switch <agent-key|alias> (or run /agent)"
|
|
73160
74900
|
};
|
|
73161
74901
|
}
|
|
73162
|
-
const resolvedTarget =
|
|
74902
|
+
const resolvedTarget = resolveAgentSwitchTarget(argText, PLATFORM_AGENTS);
|
|
73163
74903
|
if (!resolvedTarget) {
|
|
73164
74904
|
return {
|
|
73165
74905
|
nextState: state,
|
|
73166
74906
|
output: `I don't know agent shortcut "${argText}" yet.
|
|
73167
|
-
Use /switch nolo, /switch
|
|
74907
|
+
Use /agent, /switch nolo, /switch minimax-m3, or a full agent key.`
|
|
73168
74908
|
};
|
|
73169
74909
|
}
|
|
73170
|
-
return
|
|
73171
|
-
nextState: {
|
|
73172
|
-
...state,
|
|
73173
|
-
agentName: resolvedTarget.name,
|
|
73174
|
-
agentKey: resolvedTarget.key
|
|
73175
|
-
},
|
|
73176
|
-
output: `Switched to ${resolvedTarget.name}.`
|
|
73177
|
-
};
|
|
74910
|
+
return applyAgentSwitch(state, resolvedTarget);
|
|
73178
74911
|
}
|
|
73179
74912
|
case "/dialog":
|
|
73180
74913
|
return {
|
|
@@ -73245,8 +74978,14 @@ async function runAgentChat(scriptDir, state, message, env, output2, agentRunner
|
|
|
73245
74978
|
message,
|
|
73246
74979
|
continueDialogId: state.dialogId,
|
|
73247
74980
|
runtimeMode: state.runtimeMode,
|
|
74981
|
+
localRuntimeCwd: process.cwd(),
|
|
73248
74982
|
scriptDir,
|
|
73249
|
-
env
|
|
74983
|
+
env: {
|
|
74984
|
+
...env,
|
|
74985
|
+
NOLO_CLI_THINKING: state.thinkingDisplay,
|
|
74986
|
+
NOLO_CLI_TOOLS: state.toolDisplay,
|
|
74987
|
+
NOLO_CLI_RENDER: state.renderDisplay
|
|
74988
|
+
},
|
|
73250
74989
|
output: output2
|
|
73251
74990
|
});
|
|
73252
74991
|
return result;
|
|
@@ -73257,7 +74996,7 @@ async function pipeReadableToOutput(stream, output2) {
|
|
|
73257
74996
|
}
|
|
73258
74997
|
function resolveDefaultCliEntrypoint(scriptDir) {
|
|
73259
74998
|
if (process.argv[1]) return process.argv[1];
|
|
73260
|
-
return
|
|
74999
|
+
return join12(scriptDir, "..", "packages", "cli", "index.ts");
|
|
73261
75000
|
}
|
|
73262
75001
|
async function runCliCommandInChildProcess(args2, context) {
|
|
73263
75002
|
const proc = spawnProcess({
|
|
@@ -73272,6 +75011,19 @@ async function runCliCommandInChildProcess(args2, context) {
|
|
|
73272
75011
|
]);
|
|
73273
75012
|
return proc.exited;
|
|
73274
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
|
+
}
|
|
73275
75027
|
async function startTuiWorkspace(options) {
|
|
73276
75028
|
let state = createInitialTuiState(options.env ?? process.env);
|
|
73277
75029
|
const input2 = options.input ?? defaultInput;
|
|
@@ -73285,12 +75037,19 @@ async function startTuiWorkspace(options) {
|
|
|
73285
75037
|
rl.prompt();
|
|
73286
75038
|
try {
|
|
73287
75039
|
for await (const line of rl) {
|
|
75040
|
+
if (!line.trim()) {
|
|
75041
|
+
continue;
|
|
75042
|
+
}
|
|
73288
75043
|
const result = handleTuiInput(line, state);
|
|
75044
|
+
const previousAgentKey = state.agentKey;
|
|
73289
75045
|
state = result.nextState;
|
|
73290
75046
|
if (result.output) {
|
|
73291
75047
|
output2.write(`${result.output}
|
|
73292
75048
|
`);
|
|
73293
75049
|
}
|
|
75050
|
+
if (state.agentKey !== previousAgentKey && result.output?.startsWith("Switched to ")) {
|
|
75051
|
+
persistAgentSelection(state, options.env ?? process.env);
|
|
75052
|
+
}
|
|
73294
75053
|
if (result.action?.type === "exit") {
|
|
73295
75054
|
break;
|
|
73296
75055
|
}
|
|
@@ -73321,12 +75080,70 @@ async function startTuiWorkspace(options) {
|
|
|
73321
75080
|
if (exitCode2 === 0) {
|
|
73322
75081
|
output2.write("Update finished. Restart nolo to use the new version.\n");
|
|
73323
75082
|
} else {
|
|
73324
|
-
output2.write("Update failed.
|
|
75083
|
+
output2.write("Update failed. Check the error above, then run /update again or use nolo update.\n");
|
|
73325
75084
|
}
|
|
73326
75085
|
} catch (error) {
|
|
73327
75086
|
output2.write(`${error instanceof Error ? error.message : String(error)}
|
|
73328
75087
|
`);
|
|
73329
|
-
output2.write("Update failed.
|
|
75088
|
+
output2.write("Update failed. Check the error above, then run /update again or use nolo update.\n");
|
|
75089
|
+
}
|
|
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
|
+
);
|
|
73330
75147
|
}
|
|
73331
75148
|
}
|
|
73332
75149
|
if (result.action?.type === "cli-command") {
|
|
@@ -73357,11 +75174,14 @@ async function startTuiWorkspace(options) {
|
|
|
73357
75174
|
output2,
|
|
73358
75175
|
options.agentRunner
|
|
73359
75176
|
);
|
|
73360
|
-
if (runResult.dialogId) {
|
|
75177
|
+
if (runResult.dialogId || runResult.turnTokens) {
|
|
73361
75178
|
state = {
|
|
73362
75179
|
...state,
|
|
73363
|
-
|
|
73364
|
-
|
|
75180
|
+
...runResult.dialogId ? {
|
|
75181
|
+
dialogId: runResult.dialogId,
|
|
75182
|
+
dialogLabel: runResult.dialogId
|
|
75183
|
+
} : {},
|
|
75184
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
73365
75185
|
};
|
|
73366
75186
|
}
|
|
73367
75187
|
}
|
|
@@ -73377,12 +75197,12 @@ ${renderStatusLine(state)}
|
|
|
73377
75197
|
}
|
|
73378
75198
|
|
|
73379
75199
|
// packages/cli/index.ts
|
|
73380
|
-
var CLI_DIR3 =
|
|
73381
|
-
var ROOT_DIR =
|
|
73382
|
-
var SCRIPT_DIR =
|
|
75200
|
+
var CLI_DIR3 = dirname9(fileURLToPath6(import.meta.url));
|
|
75201
|
+
var ROOT_DIR = join13(CLI_DIR3, "..", "..");
|
|
75202
|
+
var SCRIPT_DIR = join13(ROOT_DIR, "scripts");
|
|
73383
75203
|
var packageInfo = readPackageInfo();
|
|
73384
75204
|
async function runScript(script, forwardedArgs, env) {
|
|
73385
|
-
const scriptPath =
|
|
75205
|
+
const scriptPath = join13(SCRIPT_DIR, script);
|
|
73386
75206
|
const proc = spawnProcess({
|
|
73387
75207
|
cmd: [process.execPath, scriptPath, ...forwardedArgs],
|
|
73388
75208
|
stdin: "inherit",
|
|
@@ -73400,7 +75220,7 @@ var runtimeEnv = {
|
|
|
73400
75220
|
var runtimeContext = createCliRuntimeContext({
|
|
73401
75221
|
env: runtimeEnv,
|
|
73402
75222
|
scriptDir: SCRIPT_DIR,
|
|
73403
|
-
entrypointPath:
|
|
75223
|
+
entrypointPath: fileURLToPath6(import.meta.url),
|
|
73404
75224
|
packageInfo
|
|
73405
75225
|
});
|
|
73406
75226
|
if (args.length === 0) {
|