msapling 2.3.6-beta.60 → 2.3.6-beta.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +525 -197
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -14450,6 +14450,14 @@ var init_Settings = __esm({
|
|
|
14450
14450
|
});
|
|
14451
14451
|
|
|
14452
14452
|
// ../core/src/agent/localModelPolicy.ts
|
|
14453
|
+
function buildDeterministicReadPlan(prompt4, availableTools) {
|
|
14454
|
+
if (MUTATING_INTENT.test(prompt4) || !LIST_DIRECTORY_INTENT.test(prompt4)) return null;
|
|
14455
|
+
if (!new Set(availableTools).has("list_directory")) return null;
|
|
14456
|
+
const absolute = (prompt4.match(QUOTED_WINDOWS_PATH)?.[1] ?? prompt4.match(WINDOWS_DRIVE_ROOT)?.[1] ?? prompt4.match(WINDOWS_ABSOLUTE_TOKEN)?.[1])?.trim();
|
|
14457
|
+
const drive = prompt4.match(WINDOWS_DRIVE_WORDS)?.[1] ?? prompt4.match(WINDOWS_DIRECTORY_THEN_DRIVE)?.[1];
|
|
14458
|
+
const path3 = absolute || (drive ? `${drive.toUpperCase()}:\\` : ".");
|
|
14459
|
+
return { tool: "list_directory", args: { path: path3 } };
|
|
14460
|
+
}
|
|
14453
14461
|
function buildReadToolRecovery(prompt4, response, availableTools) {
|
|
14454
14462
|
if (MUTATING_INTENT.test(prompt4)) return null;
|
|
14455
14463
|
const hasReadIntent = SAFE_READ_INTENT.test(prompt4) || SAFE_READ_VERB.test(prompt4);
|
|
@@ -14478,7 +14486,7 @@ function inferCapability(model) {
|
|
|
14478
14486
|
if (sizes.some((size) => size <= 7)) return "small";
|
|
14479
14487
|
return "unknown";
|
|
14480
14488
|
}
|
|
14481
|
-
var LOCAL_ACCESS_DENIAL, SAFE_READ_INTENT, SAFE_READ_VERB, PATH_LIKE_INTENT, MUTATING_INTENT, READ_RECOVERY_TOOLS, SAFE_TOOLS;
|
|
14489
|
+
var LOCAL_ACCESS_DENIAL, SAFE_READ_INTENT, SAFE_READ_VERB, PATH_LIKE_INTENT, MUTATING_INTENT, READ_RECOVERY_TOOLS, LIST_DIRECTORY_INTENT, QUOTED_WINDOWS_PATH, WINDOWS_DRIVE_ROOT, WINDOWS_ABSOLUTE_TOKEN, WINDOWS_DRIVE_WORDS, WINDOWS_DIRECTORY_THEN_DRIVE, SAFE_TOOLS;
|
|
14482
14490
|
var init_localModelPolicy = __esm({
|
|
14483
14491
|
"../core/src/agent/localModelPolicy.ts"() {
|
|
14484
14492
|
"use strict";
|
|
@@ -14489,6 +14497,12 @@ var init_localModelPolicy = __esm({
|
|
|
14489
14497
|
PATH_LIKE_INTENT = /(?:[A-Za-z]:[\\/]|\/{1,2}[A-Za-z0-9_.-]+\/|\.\.?[\\/])[A-Za-z0-9_.\\/ -]*/;
|
|
14490
14498
|
MUTATING_INTENT = /\b(?:create|overwrite|write|edit|modify|change|delete|remove|move|rename|execute|run|install|uninstall|commit|push|upload)\b/i;
|
|
14491
14499
|
READ_RECOVERY_TOOLS = ["read_file", "list_directory", "glob_files", "grep_search"];
|
|
14500
|
+
LIST_DIRECTORY_INTENT = /\b(?:list|show|display|enumerate|review|inspect|what(?:'s| is)? (?:in|inside))\b[^\n]{0,120}\b(?:files?|folders?|director(?:y|ies)|drive|workspace|project)\b/i;
|
|
14501
|
+
QUOTED_WINDOWS_PATH = /["']([A-Za-z]:[\\/][^"']*)["']/;
|
|
14502
|
+
WINDOWS_DRIVE_ROOT = /\b([A-Za-z]:[\\/])(?=\s|$|[.,;:)])/;
|
|
14503
|
+
WINDOWS_ABSOLUTE_TOKEN = /\b([A-Za-z]:[\\/][^\s,;]*)/;
|
|
14504
|
+
WINDOWS_DRIVE_WORDS = /\b([A-Za-z])\s+(?:drive|directory)\b/i;
|
|
14505
|
+
WINDOWS_DIRECTORY_THEN_DRIVE = /\b(?:drive|directory)\s+([A-Za-z])\b/i;
|
|
14492
14506
|
SAFE_TOOLS = /* @__PURE__ */ new Set([
|
|
14493
14507
|
"read_file",
|
|
14494
14508
|
"list_directory",
|
|
@@ -15028,6 +15042,33 @@ var init_Agent = __esm({
|
|
|
15028
15042
|
}
|
|
15029
15043
|
return this.executor.execute(toolName, args2, this.projectRoot);
|
|
15030
15044
|
}
|
|
15045
|
+
async executeDeterministicReadAdapter(chatId, turnId, plan) {
|
|
15046
|
+
const toolCallId = `client-read-${randomUUID6()}`;
|
|
15047
|
+
const request = {
|
|
15048
|
+
toolName: plan.tool,
|
|
15049
|
+
toolCallId,
|
|
15050
|
+
turnId,
|
|
15051
|
+
input: plan.args
|
|
15052
|
+
};
|
|
15053
|
+
await this.modeContract?.recordToolRequest(request);
|
|
15054
|
+
try {
|
|
15055
|
+
const result = await this.executeTurnTool(plan.tool, plan.args, false);
|
|
15056
|
+
await this.modeContract?.recordToolResult(request, result.content, !!result.isError);
|
|
15057
|
+
this.recordRemoteToolTelemetry(
|
|
15058
|
+
chatId,
|
|
15059
|
+
turnId,
|
|
15060
|
+
toolCallId,
|
|
15061
|
+
plan.tool,
|
|
15062
|
+
result.isError ? "failed" : "completed"
|
|
15063
|
+
);
|
|
15064
|
+
return result;
|
|
15065
|
+
} catch (error) {
|
|
15066
|
+
const content = SafetyGuard.redact(error instanceof Error ? error.message : String(error));
|
|
15067
|
+
await this.modeContract?.recordToolResult(request, content, true);
|
|
15068
|
+
this.recordRemoteToolTelemetry(chatId, turnId, toolCallId, plan.tool, "failed");
|
|
15069
|
+
throw error;
|
|
15070
|
+
}
|
|
15071
|
+
}
|
|
15031
15072
|
recordRemoteToolTelemetry(chatId, turnId, toolCallId, toolName, outcome) {
|
|
15032
15073
|
if (this.executionMode !== "remote") return;
|
|
15033
15074
|
if (this.toolTelemetryQueue.length >= TOOL_TELEMETRY_QUEUE_MAX) {
|
|
@@ -15277,7 +15318,37 @@ var init_Agent = __esm({
|
|
|
15277
15318
|
structuredToolResults = false;
|
|
15278
15319
|
}
|
|
15279
15320
|
}
|
|
15280
|
-
|
|
15321
|
+
let initialQueueItem = { prompt: prompt4, allowReadRecovery: true };
|
|
15322
|
+
if (!localTurn) {
|
|
15323
|
+
const initialToolNames = this.getTurnToolSchemas(false).map((tool) => String(tool.name));
|
|
15324
|
+
const deterministicPlan = buildDeterministicReadPlan(prompt4, initialToolNames);
|
|
15325
|
+
if (deterministicPlan) {
|
|
15326
|
+
const diagnostic = `[MSapling: running safe local ${deterministicPlan.tool} before the connected model.]
|
|
15327
|
+
`;
|
|
15328
|
+
await this.modeContract?.recordOutput(chatId, contractTurnId, diagnostic);
|
|
15329
|
+
onContent(diagnostic);
|
|
15330
|
+
const result = await this.executeDeterministicReadAdapter(
|
|
15331
|
+
chatId,
|
|
15332
|
+
contractTurnId,
|
|
15333
|
+
deterministicPlan
|
|
15334
|
+
);
|
|
15335
|
+
const evidence = boundToolResultForModel(result.content);
|
|
15336
|
+
initialQueueItem = {
|
|
15337
|
+
prompt: `A trusted MSapling client read-only adapter executed ${deterministicPlan.tool} with ${JSON.stringify(deterministicPlan.args)} for the original request below.
|
|
15338
|
+
|
|
15339
|
+
<client_tool_result error="${result.isError === true}">
|
|
15340
|
+
${evidence}
|
|
15341
|
+
</client_tool_result>
|
|
15342
|
+
|
|
15343
|
+
Original request: ${prompt4}
|
|
15344
|
+
|
|
15345
|
+
Answer directly from the tool result. Do not claim local access is unavailable, do not emit a patch or diff, and do not invent entries.`,
|
|
15346
|
+
allowedToolNames: [],
|
|
15347
|
+
allowReadRecovery: false
|
|
15348
|
+
};
|
|
15349
|
+
}
|
|
15350
|
+
}
|
|
15351
|
+
const queue = [initialQueueItem];
|
|
15281
15352
|
let rounds = 0;
|
|
15282
15353
|
let toolCallSeq = 0;
|
|
15283
15354
|
let streamUsage = null;
|
|
@@ -15450,16 +15521,44 @@ ${next.prompt}`
|
|
|
15450
15521
|
const recovery = !localTurn && allowReadRecovery && !remoteReadRecoveryUsed && !assistantResponse.includes("[MSapling: local model denied available file tools;") ? buildReadToolRecovery(prompt4, assistantResponse, turnTools.map((tool) => String(tool.name))) : null;
|
|
15451
15522
|
if (recovery) {
|
|
15452
15523
|
remoteReadRecoveryUsed = true;
|
|
15453
|
-
const
|
|
15524
|
+
const deterministicPlan = buildDeterministicReadPlan(prompt4, recovery.tools);
|
|
15525
|
+
if (deterministicPlan) {
|
|
15526
|
+
const diagnostic = `
|
|
15527
|
+
|
|
15528
|
+
[MSapling: connected model did not use the required read tool; running safe local ${deterministicPlan.tool}.]
|
|
15529
|
+
`;
|
|
15530
|
+
await this.modeContract?.recordOutput(chatId, contractTurnId, diagnostic);
|
|
15531
|
+
onContent(diagnostic);
|
|
15532
|
+
const result = await this.executeDeterministicReadAdapter(
|
|
15533
|
+
chatId,
|
|
15534
|
+
contractTurnId,
|
|
15535
|
+
deterministicPlan
|
|
15536
|
+
);
|
|
15537
|
+
const evidence = boundToolResultForModel(result.content);
|
|
15538
|
+
queue.push({
|
|
15539
|
+
prompt: `A trusted MSapling client read-only adapter executed ${deterministicPlan.tool} with ${JSON.stringify(deterministicPlan.args)} for the original request below.
|
|
15540
|
+
|
|
15541
|
+
<client_tool_result error="${result.isError === true}">
|
|
15542
|
+
${evidence}
|
|
15543
|
+
</client_tool_result>
|
|
15544
|
+
|
|
15545
|
+
Original request: ${prompt4}
|
|
15546
|
+
|
|
15547
|
+
Answer from the tool result. Do not claim local access is unavailable.`,
|
|
15548
|
+
allowedToolNames: []
|
|
15549
|
+
});
|
|
15550
|
+
} else {
|
|
15551
|
+
const diagnostic = `
|
|
15454
15552
|
|
|
15455
15553
|
[MSapling: connected model did not use required client file tools; retrying once with ${recovery.tools.join(", ")}.]
|
|
15456
15554
|
`;
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15555
|
+
await this.modeContract?.recordOutput(chatId, contractTurnId, diagnostic);
|
|
15556
|
+
onContent(diagnostic);
|
|
15557
|
+
queue.push({
|
|
15558
|
+
prompt: recovery.instruction,
|
|
15559
|
+
allowedToolNames: recovery.tools
|
|
15560
|
+
});
|
|
15561
|
+
}
|
|
15463
15562
|
}
|
|
15464
15563
|
continue;
|
|
15465
15564
|
}
|
|
@@ -19163,6 +19262,105 @@ var init_src3 = __esm({
|
|
|
19163
19262
|
}
|
|
19164
19263
|
});
|
|
19165
19264
|
|
|
19265
|
+
// src/runtime/terminalScreen.ts
|
|
19266
|
+
function sanitizeTerminalText(value, preserveNewlines = true) {
|
|
19267
|
+
const text = String(value ?? "");
|
|
19268
|
+
const escape = String.fromCharCode(27);
|
|
19269
|
+
const bell = String.fromCharCode(7);
|
|
19270
|
+
const withoutEscapes = text.replace(new RegExp(`${escape}\\](?:[^${bell}${escape}]|${escape}(?!\\\\))*?(?:${bell}|${escape}\\\\)`, "g"), "").replace(new RegExp(`${escape}P(?:[^${escape}]|${escape}(?!\\\\))*?(?:${escape}\\\\)`, "g"), "").replace(new RegExp(`${escape}\\[[0-?]*[ -/]*[@-~]`, "g"), "").replace(new RegExp(`${escape}[()][0-2A-Z]`, "g"), "").replace(new RegExp(`${escape}.`, "g"), "");
|
|
19271
|
+
let safe = "";
|
|
19272
|
+
for (const character of withoutEscapes) {
|
|
19273
|
+
const code = character.codePointAt(0) ?? 0;
|
|
19274
|
+
const isNewline = code === 10;
|
|
19275
|
+
const isControl = code < 32 || code === 127;
|
|
19276
|
+
if (isControl && (!preserveNewlines || !isNewline)) continue;
|
|
19277
|
+
safe += character;
|
|
19278
|
+
}
|
|
19279
|
+
return safe;
|
|
19280
|
+
}
|
|
19281
|
+
function enterAlternateScreen(output = process.stdout, env = process.env) {
|
|
19282
|
+
if (alternateScreenActive || !output.isTTY || env.MSAPLING_NO_ALT_SCREEN === "1" || env.TERM === "dumb") return false;
|
|
19283
|
+
output.write(ENTER_ALTERNATE_SCREEN + (env.MSAPLING_NO_MOUSE_SCROLL === "1" ? "" : ENABLE_MOUSE_SCROLL));
|
|
19284
|
+
alternateScreenActive = true;
|
|
19285
|
+
return true;
|
|
19286
|
+
}
|
|
19287
|
+
function isSgrMouseReport(input) {
|
|
19288
|
+
const escape = String.fromCharCode(27);
|
|
19289
|
+
return new RegExp(`${escape}\\[<[0-9]+;[0-9]+;[0-9]+[mM]`).test(input);
|
|
19290
|
+
}
|
|
19291
|
+
function parseMouseWheel(input) {
|
|
19292
|
+
const escape = String.fromCharCode(27);
|
|
19293
|
+
const match = new RegExp(`${escape}\\[<([0-9]+);[0-9]+;[0-9]+[mM]`).exec(input);
|
|
19294
|
+
if (!match) return null;
|
|
19295
|
+
const button = Number(match[1]);
|
|
19296
|
+
if (button === 64) return "up";
|
|
19297
|
+
if (button === 65) return "down";
|
|
19298
|
+
return null;
|
|
19299
|
+
}
|
|
19300
|
+
function leaveAlternateScreen(output = process.stdout) {
|
|
19301
|
+
if (!alternateScreenActive) return false;
|
|
19302
|
+
output.write(LEAVE_ALTERNATE_SCREEN);
|
|
19303
|
+
alternateScreenActive = false;
|
|
19304
|
+
return true;
|
|
19305
|
+
}
|
|
19306
|
+
var ENTER_ALTERNATE_SCREEN, ENABLE_MOUSE_SCROLL, LEAVE_ALTERNATE_SCREEN, alternateScreenActive, MAX_PROTOCOL_BUFFER, TerminalInputDecoder;
|
|
19307
|
+
var init_terminalScreen = __esm({
|
|
19308
|
+
"src/runtime/terminalScreen.ts"() {
|
|
19309
|
+
"use strict";
|
|
19310
|
+
init_esm_shims();
|
|
19311
|
+
ENTER_ALTERNATE_SCREEN = "\x1B[?1049h\x1B[H";
|
|
19312
|
+
ENABLE_MOUSE_SCROLL = "\x1B[?1000h\x1B[?1006h";
|
|
19313
|
+
LEAVE_ALTERNATE_SCREEN = "\x1B[?1006l\x1B[?1000l\x1B[?1049l\x1B[?25h";
|
|
19314
|
+
alternateScreenActive = false;
|
|
19315
|
+
MAX_PROTOCOL_BUFFER = 64 * 1024;
|
|
19316
|
+
TerminalInputDecoder = class {
|
|
19317
|
+
pending = "";
|
|
19318
|
+
inBracketedPaste = false;
|
|
19319
|
+
feed(input) {
|
|
19320
|
+
const escape = String.fromCharCode(27);
|
|
19321
|
+
if (this.inBracketedPaste) {
|
|
19322
|
+
const candidate2 = this.pending + input;
|
|
19323
|
+
const endMarker = `${escape}[201~`;
|
|
19324
|
+
const end = candidate2.indexOf(endMarker);
|
|
19325
|
+
if (end < 0) {
|
|
19326
|
+
if (candidate2.length > MAX_PROTOCOL_BUFFER) this.reset();
|
|
19327
|
+
else this.pending = candidate2;
|
|
19328
|
+
return { protocol: true, text: "", mouseWheel: null };
|
|
19329
|
+
}
|
|
19330
|
+
const text = candidate2.slice(0, end);
|
|
19331
|
+
const remainder = candidate2.slice(end + endMarker.length);
|
|
19332
|
+
this.reset();
|
|
19333
|
+
return { protocol: true, text: text + remainder, mouseWheel: null };
|
|
19334
|
+
}
|
|
19335
|
+
const candidate = this.pending + input;
|
|
19336
|
+
this.pending = "";
|
|
19337
|
+
const pasteStart = `${escape}[200~`;
|
|
19338
|
+
if (candidate.startsWith(pasteStart)) {
|
|
19339
|
+
this.inBracketedPaste = true;
|
|
19340
|
+
const remainder = candidate.slice(pasteStart.length);
|
|
19341
|
+
return this.feed(remainder);
|
|
19342
|
+
}
|
|
19343
|
+
if (!candidate.startsWith(escape)) return { protocol: false, text: input, mouseWheel: null };
|
|
19344
|
+
const wheel = parseMouseWheel(candidate);
|
|
19345
|
+
if (wheel || isSgrMouseReport(candidate)) {
|
|
19346
|
+
return { protocol: true, text: "", mouseWheel: wheel };
|
|
19347
|
+
}
|
|
19348
|
+
const sgrPrefix = `${escape}[<`;
|
|
19349
|
+
const isPartialSgr = sgrPrefix.startsWith(candidate) || candidate.startsWith(sgrPrefix);
|
|
19350
|
+
if (isPartialSgr && candidate.length <= MAX_PROTOCOL_BUFFER) {
|
|
19351
|
+
this.pending = candidate;
|
|
19352
|
+
return { protocol: true, text: "", mouseWheel: null };
|
|
19353
|
+
}
|
|
19354
|
+
return { protocol: true, text: "", mouseWheel: null };
|
|
19355
|
+
}
|
|
19356
|
+
reset() {
|
|
19357
|
+
this.pending = "";
|
|
19358
|
+
this.inBracketedPaste = false;
|
|
19359
|
+
}
|
|
19360
|
+
};
|
|
19361
|
+
}
|
|
19362
|
+
});
|
|
19363
|
+
|
|
19166
19364
|
// src/runtime/errorPresentation.ts
|
|
19167
19365
|
function errorRecord(error) {
|
|
19168
19366
|
return error && typeof error === "object" ? error : {};
|
|
@@ -19286,19 +19484,20 @@ function renderCliError(error) {
|
|
|
19286
19484
|
tool: "Local tool guardrail",
|
|
19287
19485
|
cli: "Local CLI"
|
|
19288
19486
|
}[error.surface];
|
|
19289
|
-
return [
|
|
19487
|
+
return sanitizeTerminalText([
|
|
19290
19488
|
`[${error.code}] ${error.summary}`,
|
|
19291
19489
|
`Surface: ${surface}`,
|
|
19292
19490
|
`Why: ${error.explanation}`,
|
|
19293
19491
|
`Next: ${error.action}`,
|
|
19294
19492
|
...error.detail ? [`Detail: ${error.detail}`] : []
|
|
19295
|
-
].join("\n");
|
|
19493
|
+
].join("\n"));
|
|
19296
19494
|
}
|
|
19297
19495
|
var init_errorPresentation = __esm({
|
|
19298
19496
|
"src/runtime/errorPresentation.ts"() {
|
|
19299
19497
|
"use strict";
|
|
19300
19498
|
init_esm_shims();
|
|
19301
19499
|
init_src3();
|
|
19500
|
+
init_terminalScreen();
|
|
19302
19501
|
}
|
|
19303
19502
|
});
|
|
19304
19503
|
|
|
@@ -19752,7 +19951,6 @@ var init_toggles = __esm({
|
|
|
19752
19951
|
sessionToggles = /* @__PURE__ */ new Map([
|
|
19753
19952
|
["effort", "medium"],
|
|
19754
19953
|
// 'low' | 'medium' | 'high'
|
|
19755
|
-
["vimMode", false],
|
|
19756
19954
|
["fastMode", false],
|
|
19757
19955
|
["simpleMode", false],
|
|
19758
19956
|
["filterRegex", null]
|
|
@@ -19807,12 +20005,18 @@ var init_toggles = __esm({
|
|
|
19807
20005
|
context.addMessage("system", `effort set to: ${arg}`);
|
|
19808
20006
|
}
|
|
19809
20007
|
};
|
|
19810
|
-
vimCommand =
|
|
19811
|
-
"vim",
|
|
19812
|
-
"
|
|
19813
|
-
"
|
|
19814
|
-
|
|
19815
|
-
|
|
20008
|
+
vimCommand = {
|
|
20009
|
+
name: "vim",
|
|
20010
|
+
args: "[on|off]",
|
|
20011
|
+
description: "Show Vim editor-mode availability (not yet implemented)",
|
|
20012
|
+
category: "config",
|
|
20013
|
+
handler: (_args, context) => {
|
|
20014
|
+
context.addMessage(
|
|
20015
|
+
"system",
|
|
20016
|
+
"Vim input mode is not available yet. /vim does not change editor behavior; use the standard cursor and history keys shown by /shortcuts."
|
|
20017
|
+
);
|
|
20018
|
+
}
|
|
20019
|
+
};
|
|
19816
20020
|
fastCommand = makeToggle(
|
|
19817
20021
|
"fast",
|
|
19818
20022
|
"fastMode",
|
|
@@ -23566,7 +23770,7 @@ var init_version = __esm({
|
|
|
23566
23770
|
description: "Show version information for CLI and core packages",
|
|
23567
23771
|
category: "debug",
|
|
23568
23772
|
handler: async (_args, context) => {
|
|
23569
|
-
const cliVersion = true ? "2.3.6-beta.
|
|
23773
|
+
const cliVersion = true ? "2.3.6-beta.62" : "(dev)";
|
|
23570
23774
|
const coreVersion = true ? "2.3.6-beta.43" : "(dev)";
|
|
23571
23775
|
const runtime = process.version;
|
|
23572
23776
|
context.addMessage("system", "MSapling Version Info");
|
|
@@ -23840,7 +24044,7 @@ var init_shortcuts = __esm({
|
|
|
23840
24044
|
shortcutsCommand = {
|
|
23841
24045
|
name: "shortcuts",
|
|
23842
24046
|
aliases: ["sc"],
|
|
23843
|
-
description: "List
|
|
24047
|
+
description: "List keyboard controls and registered slash commands",
|
|
23844
24048
|
category: "debug",
|
|
23845
24049
|
handler: (args2, context) => {
|
|
23846
24050
|
const { commands: commands2 } = (init_commands(), __toCommonJS(commands_exports));
|
|
@@ -23876,7 +24080,19 @@ ${matching.length} command(s) found.`);
|
|
|
23876
24080
|
...CATEGORY_ORDER2.filter((c) => grouped[c]),
|
|
23877
24081
|
...Object.keys(grouped).filter((c) => !CATEGORY_ORDER2.includes(c)).sort()
|
|
23878
24082
|
];
|
|
23879
|
-
context.addMessage("system",
|
|
24083
|
+
context.addMessage("system", [
|
|
24084
|
+
"Keyboard Controls",
|
|
24085
|
+
" \u2191/\u2193 (empty prompt) Scroll transcript one row",
|
|
24086
|
+
" PageUp/PageDown Scroll transcript one page",
|
|
24087
|
+
" Ctrl+E Return to newest transcript row",
|
|
24088
|
+
" \u2190/\u2192 Move the prompt cursor",
|
|
24089
|
+
" Ctrl+A Move to start of prompt",
|
|
24090
|
+
" Ctrl+P/Ctrl+N Previous/next prompt history",
|
|
24091
|
+
" Shift+Enter Insert a newline",
|
|
24092
|
+
" Escape/Ctrl+C Cancel current operation",
|
|
24093
|
+
"",
|
|
24094
|
+
"Registered Slash Commands"
|
|
24095
|
+
].join("\n"));
|
|
23880
24096
|
context.addMessage("system", tableSep());
|
|
23881
24097
|
for (const cat of cats) {
|
|
23882
24098
|
const cmds = grouped[cat].sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -29593,7 +29809,7 @@ import { render } from "ink";
|
|
|
29593
29809
|
|
|
29594
29810
|
// src/App.tsx
|
|
29595
29811
|
init_esm_shims();
|
|
29596
|
-
import { useState as useState5, useEffect as
|
|
29812
|
+
import { useState as useState5, useEffect as useEffect3, useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
29597
29813
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
29598
29814
|
import { Box as Box7, Text as Text7, useApp, useInput as useInput4, useStdout } from "ink";
|
|
29599
29815
|
|
|
@@ -29603,11 +29819,11 @@ import { Box, Text } from "ink";
|
|
|
29603
29819
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
29604
29820
|
var Header = ({ compact: compact2 = false }) => compact2 ? /* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
29605
29821
|
"\u25CF MSapling v",
|
|
29606
|
-
"2.3.6-beta.
|
|
29607
|
-
] }) : /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
29822
|
+
"2.3.6-beta.62"
|
|
29823
|
+
] }) : /* @__PURE__ */ jsxs(Box, { width: "100%", borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
29608
29824
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
29609
29825
|
"\u25CF MSapling CLI v",
|
|
29610
|
-
"2.3.6-beta.
|
|
29826
|
+
"2.3.6-beta.62"
|
|
29611
29827
|
] }),
|
|
29612
29828
|
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
|
|
29613
29829
|
] });
|
|
@@ -29615,6 +29831,7 @@ var Header = ({ compact: compact2 = false }) => compact2 ? /* @__PURE__ */ jsxs(
|
|
|
29615
29831
|
// src/components/Footer.tsx
|
|
29616
29832
|
init_esm_shims();
|
|
29617
29833
|
init_src3();
|
|
29834
|
+
init_terminalScreen();
|
|
29618
29835
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
29619
29836
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
29620
29837
|
var PRO_TIERS2 = /* @__PURE__ */ new Set(["pro", "monthly", "lifetime", "enterprise", "admin", "superadmin"]);
|
|
@@ -29660,18 +29877,21 @@ var Footer = ({ user, options, model, project, chatId, cwd, mode, lastCost, sess
|
|
|
29660
29877
|
const showCapMeter = user ? shouldShowCapMeter(user) : false;
|
|
29661
29878
|
const dailyPct = user && showCapMeter ? Math.min(100, Math.round(user.daily_tokens_used / user.daily_tokens_limit * 100)) : 0;
|
|
29662
29879
|
const standaloneSearchCost = getSessionStats().snapshot().standaloneSearch.estimatedCostUsd;
|
|
29663
|
-
|
|
29880
|
+
const safeModel = sanitizeTerminalText(model, false);
|
|
29881
|
+
const safeProject = sanitizeTerminalText(project, false);
|
|
29882
|
+
const safeChatId = chatId ? sanitizeTerminalText(chatId, false) : null;
|
|
29883
|
+
return /* @__PURE__ */ jsxs2(Box2, { width: "100%", borderStyle: "round", borderColor: "gray", paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
29664
29884
|
/* @__PURE__ */ jsxs2(Box2, { justifyContent: "space-between", children: [
|
|
29665
29885
|
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "CLI telemetry" }),
|
|
29666
29886
|
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: formatAccountSummary(user, { billingProfile, isStale, usageError }) })
|
|
29667
29887
|
] }),
|
|
29668
29888
|
expanded && options.chat && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
29669
29889
|
"project: ",
|
|
29670
|
-
|
|
29890
|
+
safeProject,
|
|
29671
29891
|
" chat: ",
|
|
29672
|
-
|
|
29892
|
+
safeChatId ?? "none",
|
|
29673
29893
|
" model: ",
|
|
29674
|
-
|
|
29894
|
+
safeModel
|
|
29675
29895
|
] }),
|
|
29676
29896
|
options.location && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
29677
29897
|
"cwd: ",
|
|
@@ -29709,44 +29929,9 @@ function promptLabel(user) {
|
|
|
29709
29929
|
|
|
29710
29930
|
// src/components/ApprovalDialog.tsx
|
|
29711
29931
|
init_esm_shims();
|
|
29932
|
+
init_terminalScreen();
|
|
29712
29933
|
import { useState, useMemo } from "react";
|
|
29713
29934
|
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
29714
|
-
|
|
29715
|
-
// src/hooks/useTerminalMouseScroll.ts
|
|
29716
|
-
init_esm_shims();
|
|
29717
|
-
import { useEffect, useRef } from "react";
|
|
29718
|
-
var ESC = String.fromCharCode(27);
|
|
29719
|
-
function isMouseReport(input) {
|
|
29720
|
-
return input.includes(`${ESC}[<`) && /\d+;\d+;\d+[mM]/.test(input);
|
|
29721
|
-
}
|
|
29722
|
-
function parseMouseScroll(input) {
|
|
29723
|
-
const directions = [];
|
|
29724
|
-
const pattern = new RegExp(`${ESC}\\[<(64|65);\\d+;\\d+[mM]`, "g");
|
|
29725
|
-
for (const match of input.matchAll(pattern)) {
|
|
29726
|
-
directions.push(match[1] === "64" ? "up" : "down");
|
|
29727
|
-
}
|
|
29728
|
-
return directions;
|
|
29729
|
-
}
|
|
29730
|
-
function useTerminalMouseScroll(onScroll) {
|
|
29731
|
-
const callback = useRef(onScroll);
|
|
29732
|
-
callback.current = onScroll;
|
|
29733
|
-
useEffect(() => {
|
|
29734
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
29735
|
-
const handleData = (chunk) => {
|
|
29736
|
-
for (const direction of parseMouseScroll(String(chunk))) {
|
|
29737
|
-
callback.current(direction);
|
|
29738
|
-
}
|
|
29739
|
-
};
|
|
29740
|
-
process.stdout.write("\x1B[?1000h\x1B[?1006h");
|
|
29741
|
-
process.stdin.on("data", handleData);
|
|
29742
|
-
return () => {
|
|
29743
|
-
process.stdin.off("data", handleData);
|
|
29744
|
-
process.stdout.write("\x1B[?1006l\x1B[?1000l");
|
|
29745
|
-
};
|
|
29746
|
-
}, []);
|
|
29747
|
-
}
|
|
29748
|
-
|
|
29749
|
-
// src/components/ApprovalDialog.tsx
|
|
29750
29935
|
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
29751
29936
|
function parseDiffLines(diffText) {
|
|
29752
29937
|
if (!diffText) return [];
|
|
@@ -29810,10 +29995,13 @@ var ApprovalDialog = ({
|
|
|
29810
29995
|
onResolve
|
|
29811
29996
|
}) => {
|
|
29812
29997
|
const [showFullDiff, setShowFullDiff] = useState(false);
|
|
29813
|
-
const
|
|
29998
|
+
const safeCommand = sanitizeTerminalText(command, false);
|
|
29999
|
+
const safeReason = sanitizeTerminalText(reason);
|
|
30000
|
+
const safePath = targetPath ? sanitizeTerminalText(targetPath, false) : void 0;
|
|
30001
|
+
const safeDiff = diff ? sanitizeTerminalText(diff) : void 0;
|
|
30002
|
+
const { hasDiff, diffText, title } = useMemo(() => extractDiffFromCommand(safeCommand, safeDiff), [safeCommand, safeDiff]);
|
|
29814
30003
|
const diffLines = useMemo(() => parseDiffLines(diffText), [diffText]);
|
|
29815
30004
|
useInput((input, key) => {
|
|
29816
|
-
if (isMouseReport(input)) return;
|
|
29817
30005
|
if (key.escape) {
|
|
29818
30006
|
onResolve("no");
|
|
29819
30007
|
return;
|
|
@@ -29833,16 +30021,16 @@ var ApprovalDialog = ({
|
|
|
29833
30021
|
const isTruncated = !showFullDiff && diffLines.length > MAX_DIFF_COLLAPSED_LINES;
|
|
29834
30022
|
return /* @__PURE__ */ jsxs3(Box3, { borderStyle: "double", borderColor: "yellow", paddingX: 1, marginY: 1, flexDirection: "column", children: [
|
|
29835
30023
|
/* @__PURE__ */ jsx3(Text3, { bold: true, color: "yellow", children: "SECURITY APPROVAL REQUIRED" }),
|
|
29836
|
-
/* @__PURE__ */ jsx3(Text3, { italic: true, dimColor: true, children:
|
|
30024
|
+
/* @__PURE__ */ jsx3(Text3, { italic: true, dimColor: true, children: safeReason }),
|
|
29837
30025
|
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, paddingX: 1, borderStyle: "round", borderColor: "gray", children: /* @__PURE__ */ jsxs3(Text3, { color: "white", children: [
|
|
29838
30026
|
"$ ",
|
|
29839
|
-
|
|
30027
|
+
safeCommand
|
|
29840
30028
|
] }) }),
|
|
29841
30029
|
hasDiff && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", borderStyle: "single", borderColor: "cyan", paddingX: 1, children: [
|
|
29842
30030
|
/* @__PURE__ */ jsxs3(Box3, { justifyContent: "space-between", children: [
|
|
29843
30031
|
/* @__PURE__ */ jsxs3(Text3, { bold: true, color: "cyan", children: [
|
|
29844
30032
|
"DIFF REVIEW ",
|
|
29845
|
-
|
|
30033
|
+
safePath || title ? `(${safePath || sanitizeTerminalText(title, false)})` : "",
|
|
29846
30034
|
":"
|
|
29847
30035
|
] }),
|
|
29848
30036
|
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
@@ -29893,6 +30081,7 @@ var ApprovalDialog = ({
|
|
|
29893
30081
|
|
|
29894
30082
|
// src/components/AskUserQuestion.tsx
|
|
29895
30083
|
init_esm_shims();
|
|
30084
|
+
init_terminalScreen();
|
|
29896
30085
|
import { useState as useState2 } from "react";
|
|
29897
30086
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
29898
30087
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -29900,7 +30089,6 @@ var AskUserQuestion = ({ question, options, multiSelect, onResolve }) => {
|
|
|
29900
30089
|
const [selectedIndex, setSelectedIndex] = useState2(0);
|
|
29901
30090
|
const [selectedIndices, setSelectedIndices] = useState2(/* @__PURE__ */ new Set());
|
|
29902
30091
|
useInput2((input, key) => {
|
|
29903
|
-
if (isMouseReport(input)) return;
|
|
29904
30092
|
if (key.upArrow) {
|
|
29905
30093
|
setSelectedIndex((prev) => prev > 0 ? prev - 1 : options.length - 1);
|
|
29906
30094
|
} else if (key.downArrow) {
|
|
@@ -29928,7 +30116,7 @@ var AskUserQuestion = ({ question, options, multiSelect, onResolve }) => {
|
|
|
29928
30116
|
});
|
|
29929
30117
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1, children: [
|
|
29930
30118
|
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: "QUESTION FROM AGENT" }),
|
|
29931
|
-
/* @__PURE__ */ jsx4(Text4, { children: question }),
|
|
30119
|
+
/* @__PURE__ */ jsx4(Text4, { children: sanitizeTerminalText(question) }),
|
|
29932
30120
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: options.map((opt, i) => {
|
|
29933
30121
|
const isHighlighted = i === selectedIndex;
|
|
29934
30122
|
const isSelected = selectedIndices.has(i);
|
|
@@ -29939,9 +30127,9 @@ var AskUserQuestion = ({ question, options, multiSelect, onResolve }) => {
|
|
|
29939
30127
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
29940
30128
|
/* @__PURE__ */ jsxs4(Text4, { color: isHighlighted ? "blue" : "white", bold: isHighlighted, children: [
|
|
29941
30129
|
marker,
|
|
29942
|
-
opt.text
|
|
30130
|
+
sanitizeTerminalText(opt.text, false)
|
|
29943
30131
|
] }),
|
|
29944
|
-
isHighlighted && opt.preview && /* @__PURE__ */ jsx4(Box4, { marginLeft: 4, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: opt.preview }) })
|
|
30132
|
+
isHighlighted && opt.preview && /* @__PURE__ */ jsx4(Box4, { marginLeft: 4, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: sanitizeTerminalText(opt.preview) }) })
|
|
29945
30133
|
] }, i);
|
|
29946
30134
|
}) }),
|
|
29947
30135
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
@@ -29954,37 +30142,12 @@ var AskUserQuestion = ({ question, options, multiSelect, onResolve }) => {
|
|
|
29954
30142
|
|
|
29955
30143
|
// src/components/VirtualizedMessageList.tsx
|
|
29956
30144
|
init_esm_shims();
|
|
30145
|
+
init_terminalScreen();
|
|
29957
30146
|
import React3 from "react";
|
|
29958
30147
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
30148
|
+
import stringWidth from "string-width";
|
|
30149
|
+
import stripAnsi2 from "strip-ansi";
|
|
29959
30150
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
29960
|
-
function estimateLineCount(text, cols) {
|
|
29961
|
-
const effectiveCols = cols > 0 ? cols : 80;
|
|
29962
|
-
const physicalLines = text.split("\n");
|
|
29963
|
-
let total = 0;
|
|
29964
|
-
for (const line of physicalLines) {
|
|
29965
|
-
total += line.length === 0 ? 1 : Math.ceil(line.length / effectiveCols);
|
|
29966
|
-
}
|
|
29967
|
-
return total;
|
|
29968
|
-
}
|
|
29969
|
-
function computeViewport(messages, visibleLines, termColumns, offsetFromEnd = 0) {
|
|
29970
|
-
const cols = termColumns > 0 ? termColumns : 80;
|
|
29971
|
-
const budget = Math.max(visibleLines, 1);
|
|
29972
|
-
let linesUsed = 0;
|
|
29973
|
-
const endIdx = Math.max(0, messages.length - Math.max(0, Math.floor(offsetFromEnd)));
|
|
29974
|
-
let startIdx = endIdx;
|
|
29975
|
-
for (let i = endIdx - 1; i >= 0; i--) {
|
|
29976
|
-
const contentLines = estimateLineCount(messages[i].content, cols);
|
|
29977
|
-
const msgCost = contentLines + 2;
|
|
29978
|
-
if (linesUsed + msgCost > budget) break;
|
|
29979
|
-
linesUsed += msgCost;
|
|
29980
|
-
startIdx = i;
|
|
29981
|
-
}
|
|
29982
|
-
return {
|
|
29983
|
-
displayMessages: messages.slice(startIdx, endIdx),
|
|
29984
|
-
hiddenCount: startIdx,
|
|
29985
|
-
hiddenAfter: messages.length - endIdx
|
|
29986
|
-
};
|
|
29987
|
-
}
|
|
29988
30151
|
var ROLE_COLOR = {
|
|
29989
30152
|
user: "green",
|
|
29990
30153
|
assistant: "cyan",
|
|
@@ -29997,6 +30160,96 @@ var ROLE_LABEL = {
|
|
|
29997
30160
|
error: "Error: ",
|
|
29998
30161
|
system: ""
|
|
29999
30162
|
};
|
|
30163
|
+
function cleanTerminalText(value) {
|
|
30164
|
+
return sanitizeTerminalText(stripAnsi2(value)).replace(/\r\n?/g, "\n").replace(/\t/g, " ");
|
|
30165
|
+
}
|
|
30166
|
+
function graphemes(value) {
|
|
30167
|
+
if (typeof Intl.Segmenter === "function") {
|
|
30168
|
+
const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
30169
|
+
return Array.from(segmenter.segment(value), (segment) => segment.segment);
|
|
30170
|
+
}
|
|
30171
|
+
return Array.from(value);
|
|
30172
|
+
}
|
|
30173
|
+
function wrapTerminalLine(value, columns) {
|
|
30174
|
+
const width = Math.max(1, Math.floor(columns));
|
|
30175
|
+
if (value.length === 0) return [""];
|
|
30176
|
+
const rows = [];
|
|
30177
|
+
let row3 = "";
|
|
30178
|
+
let rowWidth = 0;
|
|
30179
|
+
for (const grapheme of graphemes(value)) {
|
|
30180
|
+
const cellWidth = Math.max(0, stringWidth(grapheme));
|
|
30181
|
+
if (row3.length > 0 && rowWidth + cellWidth > width) {
|
|
30182
|
+
rows.push(row3);
|
|
30183
|
+
row3 = "";
|
|
30184
|
+
rowWidth = 0;
|
|
30185
|
+
}
|
|
30186
|
+
row3 += grapheme;
|
|
30187
|
+
rowWidth += cellWidth;
|
|
30188
|
+
}
|
|
30189
|
+
rows.push(row3);
|
|
30190
|
+
return rows;
|
|
30191
|
+
}
|
|
30192
|
+
function buildTranscriptRows(messages, termColumns, compact2 = false) {
|
|
30193
|
+
const columns = termColumns > 0 ? Math.floor(termColumns) : 80;
|
|
30194
|
+
const separator = "\u2500".repeat(Math.max(1, Math.min(columns, 60)));
|
|
30195
|
+
const rows = [];
|
|
30196
|
+
messages.forEach((message2, messageIndex) => {
|
|
30197
|
+
if (compact2 && messageIndex > 0) {
|
|
30198
|
+
rows.push({ messageIndex, role: message2.role, prefix: "", content: separator, separator: true });
|
|
30199
|
+
}
|
|
30200
|
+
const label = ROLE_LABEL[message2.role];
|
|
30201
|
+
const labelWidth = stringWidth(label);
|
|
30202
|
+
const contentWidth = Math.max(1, columns - labelWidth);
|
|
30203
|
+
const continuationPrefix = " ".repeat(labelWidth);
|
|
30204
|
+
let firstVisualRow = true;
|
|
30205
|
+
for (const physicalLine of cleanTerminalText(message2.content).split("\n")) {
|
|
30206
|
+
const wrapped = wrapTerminalLine(physicalLine, contentWidth);
|
|
30207
|
+
for (const content of wrapped) {
|
|
30208
|
+
rows.push({
|
|
30209
|
+
messageIndex,
|
|
30210
|
+
role: message2.role,
|
|
30211
|
+
prefix: firstVisualRow ? label : continuationPrefix,
|
|
30212
|
+
content
|
|
30213
|
+
});
|
|
30214
|
+
firstVisualRow = false;
|
|
30215
|
+
}
|
|
30216
|
+
}
|
|
30217
|
+
if (!compact2 && message2.role === "assistant") {
|
|
30218
|
+
rows.push({ messageIndex, role: message2.role, prefix: "", content: "", margin: true });
|
|
30219
|
+
}
|
|
30220
|
+
});
|
|
30221
|
+
return rows;
|
|
30222
|
+
}
|
|
30223
|
+
function uniqueMessageCount(rows) {
|
|
30224
|
+
return new Set(rows.map((row3) => row3.messageIndex)).size;
|
|
30225
|
+
}
|
|
30226
|
+
function computeViewport(messages, visibleLines, termColumns, offsetFromEnd = 0, compact2 = false) {
|
|
30227
|
+
const allRows = buildTranscriptRows(messages, termColumns, compact2);
|
|
30228
|
+
const totalRows = allRows.length;
|
|
30229
|
+
const budget = Math.max(1, Math.floor(visibleLines));
|
|
30230
|
+
const hiddenRowsAfter = Math.min(totalRows, Math.max(0, Math.floor(offsetFromEnd)));
|
|
30231
|
+
const end = totalRows - hiddenRowsAfter;
|
|
30232
|
+
let contentBudget = budget;
|
|
30233
|
+
let start = Math.max(0, end - contentBudget);
|
|
30234
|
+
if (start > 0 || hiddenRowsAfter > 0) {
|
|
30235
|
+
contentBudget = Math.max(0, budget - 1);
|
|
30236
|
+
start = Math.max(0, end - contentBudget);
|
|
30237
|
+
}
|
|
30238
|
+
const displayRows = allRows.slice(start, end);
|
|
30239
|
+
const visibleIndices = [...new Set(displayRows.map((row3) => row3.messageIndex))];
|
|
30240
|
+
const displayMessages = visibleIndices.map((index) => messages[index]);
|
|
30241
|
+
const beforeRows = allRows.slice(0, start);
|
|
30242
|
+
const afterRows = allRows.slice(end);
|
|
30243
|
+
return {
|
|
30244
|
+
displayMessages,
|
|
30245
|
+
displayRows,
|
|
30246
|
+
hiddenCount: uniqueMessageCount(beforeRows),
|
|
30247
|
+
hiddenAfter: uniqueMessageCount(afterRows),
|
|
30248
|
+
hiddenRowsBefore: start,
|
|
30249
|
+
hiddenRowsAfter,
|
|
30250
|
+
totalRows
|
|
30251
|
+
};
|
|
30252
|
+
}
|
|
30000
30253
|
var VirtualizedMessageList = ({
|
|
30001
30254
|
messages,
|
|
30002
30255
|
visibleLines,
|
|
@@ -30004,45 +30257,27 @@ var VirtualizedMessageList = ({
|
|
|
30004
30257
|
compact: compact2 = false,
|
|
30005
30258
|
offsetFromEnd = 0
|
|
30006
30259
|
}) => {
|
|
30007
|
-
const {
|
|
30008
|
-
() => computeViewport(messages, visibleLines, termColumns, offsetFromEnd),
|
|
30009
|
-
[messages, visibleLines, termColumns, offsetFromEnd]
|
|
30260
|
+
const { displayRows, hiddenRowsBefore, hiddenRowsAfter } = React3.useMemo(
|
|
30261
|
+
() => computeViewport(messages, visibleLines, termColumns, offsetFromEnd, compact2),
|
|
30262
|
+
[messages, visibleLines, termColumns, offsetFromEnd, compact2]
|
|
30010
30263
|
);
|
|
30011
|
-
|
|
30012
|
-
|
|
30013
|
-
(
|
|
30014
|
-
|
|
30015
|
-
|
|
30016
|
-
|
|
30017
|
-
flexDirection: "column",
|
|
30018
|
-
marginBottom: compact2 ? 0 : msg.role === "assistant" ? 1 : 0,
|
|
30019
|
-
children: [
|
|
30020
|
-
compact2 && i > 0 && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2500".repeat(separatorWidth) }),
|
|
30021
|
-
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
30022
|
-
/* @__PURE__ */ jsx5(
|
|
30023
|
-
Text5,
|
|
30024
|
-
{
|
|
30025
|
-
color: ROLE_COLOR[msg.role],
|
|
30026
|
-
bold: msg.role !== "assistant",
|
|
30027
|
-
children: ROLE_LABEL[msg.role]
|
|
30028
|
-
}
|
|
30029
|
-
),
|
|
30030
|
-
/* @__PURE__ */ jsx5(Text5, { wrap: "wrap", children: msg.content })
|
|
30031
|
-
] })
|
|
30032
|
-
]
|
|
30033
|
-
},
|
|
30034
|
-
i
|
|
30035
|
-
))
|
|
30264
|
+
return /* @__PURE__ */ jsxs5(Box5, { width: "100%", flexDirection: "column", flexGrow: 1, children: [
|
|
30265
|
+
(hiddenRowsBefore > 0 || hiddenRowsAfter > 0) && /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: `[\u2191 ${hiddenRowsBefore} rows \xB7 \u2193 ${hiddenRowsAfter} \xB7 PgUp/PgDn \xB7 Ctrl+E latest]` }),
|
|
30266
|
+
displayRows.map((row3, index) => row3.separator ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: row3.content }, `${row3.messageIndex}-${index}`) : row3.margin ? /* @__PURE__ */ jsx5(Text5, { children: " " }, `${row3.messageIndex}-${index}`) : /* @__PURE__ */ jsxs5(Text5, { wrap: "truncate-end", children: [
|
|
30267
|
+
/* @__PURE__ */ jsx5(Text5, { color: ROLE_COLOR[row3.role], bold: row3.role !== "assistant", children: row3.prefix }),
|
|
30268
|
+
row3.content
|
|
30269
|
+
] }, `${row3.messageIndex}-${index}`))
|
|
30036
30270
|
] });
|
|
30037
30271
|
};
|
|
30038
30272
|
|
|
30039
30273
|
// src/App.tsx
|
|
30274
|
+
init_terminalScreen();
|
|
30040
30275
|
init_src();
|
|
30041
30276
|
init_src3();
|
|
30042
30277
|
|
|
30043
30278
|
// src/ui/TextInput.tsx
|
|
30044
30279
|
init_esm_shims();
|
|
30045
|
-
import { useState as useState3, useEffect
|
|
30280
|
+
import React4, { useState as useState3, useEffect } from "react";
|
|
30046
30281
|
import { Box as Box6, Text as Text6, useInput as useInput3 } from "ink";
|
|
30047
30282
|
|
|
30048
30283
|
// src/state/commandHandler.ts
|
|
@@ -30629,7 +30864,42 @@ ${finalCmd}`;
|
|
|
30629
30864
|
}
|
|
30630
30865
|
|
|
30631
30866
|
// src/ui/TextInput.tsx
|
|
30867
|
+
init_terminalScreen();
|
|
30632
30868
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
30869
|
+
function sanitizePromptInput(value) {
|
|
30870
|
+
return sanitizeTerminalText(value);
|
|
30871
|
+
}
|
|
30872
|
+
function cursorBoundaries(value) {
|
|
30873
|
+
if (typeof Intl.Segmenter !== "function") {
|
|
30874
|
+
return Array.from({ length: value.length + 1 }, (_, index) => index);
|
|
30875
|
+
}
|
|
30876
|
+
const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
30877
|
+
return [0, ...Array.from(segmenter.segment(value), (segment) => segment.index + segment.segment.length)];
|
|
30878
|
+
}
|
|
30879
|
+
function moveCursorLeft(value, cursor) {
|
|
30880
|
+
const boundaries = cursorBoundaries(value);
|
|
30881
|
+
return boundaries[Math.max(0, boundaries.findIndex((boundary) => boundary >= cursor) - 1)] ?? 0;
|
|
30882
|
+
}
|
|
30883
|
+
function moveCursorRight(value, cursor) {
|
|
30884
|
+
const boundaries = cursorBoundaries(value);
|
|
30885
|
+
return boundaries.find((boundary) => boundary > cursor) ?? value.length;
|
|
30886
|
+
}
|
|
30887
|
+
function moveCursorWordLeft(value, cursor) {
|
|
30888
|
+
const boundaries = cursorBoundaries(value);
|
|
30889
|
+
let index = boundaries.findIndex((boundary) => boundary >= cursor);
|
|
30890
|
+
if (index < 0) index = boundaries.length - 1;
|
|
30891
|
+
while (index > 0 && /\s/.test(value.slice(boundaries[index - 1], boundaries[index]))) index--;
|
|
30892
|
+
while (index > 0 && !/\s/.test(value.slice(boundaries[index - 1], boundaries[index]))) index--;
|
|
30893
|
+
return boundaries[index] ?? 0;
|
|
30894
|
+
}
|
|
30895
|
+
function moveCursorWordRight(value, cursor) {
|
|
30896
|
+
const boundaries = cursorBoundaries(value);
|
|
30897
|
+
let index = boundaries.findIndex((boundary) => boundary > cursor);
|
|
30898
|
+
if (index < 0) return value.length;
|
|
30899
|
+
while (index < boundaries.length - 1 && !/\s/.test(value.slice(boundaries[index], boundaries[index + 1]))) index++;
|
|
30900
|
+
while (index < boundaries.length - 1 && /\s/.test(value.slice(boundaries[index], boundaries[index + 1]))) index++;
|
|
30901
|
+
return boundaries[index] ?? value.length;
|
|
30902
|
+
}
|
|
30633
30903
|
var TextInput = ({
|
|
30634
30904
|
value,
|
|
30635
30905
|
onChange,
|
|
@@ -30641,12 +30911,24 @@ var TextInput = ({
|
|
|
30641
30911
|
transcriptNavigationActive = false
|
|
30642
30912
|
}) => {
|
|
30643
30913
|
const [history, setHistory] = useState3([]);
|
|
30914
|
+
const terminalInputDecoder = React4.useRef(new TerminalInputDecoder());
|
|
30644
30915
|
const [historyIndex, setHistoryIndex] = useState3(-1);
|
|
30645
|
-
|
|
30916
|
+
const [cursor, setCursor] = useState3(value.length);
|
|
30917
|
+
useEffect(() => {
|
|
30646
30918
|
storage.loadHistory().then((entries) => setHistory(filterSafeHistory(entries)));
|
|
30647
30919
|
}, [storage]);
|
|
30920
|
+
useEffect(() => {
|
|
30921
|
+
setCursor((current) => Math.min(current, value.length));
|
|
30922
|
+
}, [value]);
|
|
30648
30923
|
useInput3((input, key) => {
|
|
30649
|
-
|
|
30924
|
+
const decoded = terminalInputDecoder.current.feed(input);
|
|
30925
|
+
if (decoded.protocol && key.escape) {
|
|
30926
|
+
terminalInputDecoder.current.reset();
|
|
30927
|
+
} else if (decoded.protocol) {
|
|
30928
|
+
if (!decoded.text) return;
|
|
30929
|
+
input = decoded.text;
|
|
30930
|
+
}
|
|
30931
|
+
const extendedKey = key;
|
|
30650
30932
|
if (key.ctrl && input === "c" || key.escape) {
|
|
30651
30933
|
onCancel?.();
|
|
30652
30934
|
return;
|
|
@@ -30654,39 +30936,70 @@ var TextInput = ({
|
|
|
30654
30936
|
if (disabled) return;
|
|
30655
30937
|
if (key.return) {
|
|
30656
30938
|
if (key.shift) {
|
|
30657
|
-
onChange(value + "\n");
|
|
30939
|
+
onChange(value.slice(0, cursor) + "\n" + value.slice(cursor));
|
|
30940
|
+
setCursor(cursor + 1);
|
|
30658
30941
|
} else {
|
|
30659
30942
|
onSubmit(value);
|
|
30660
30943
|
onChange("");
|
|
30944
|
+
setCursor(0);
|
|
30661
30945
|
setHistoryIndex(-1);
|
|
30662
30946
|
}
|
|
30663
|
-
} else if (key.backspace
|
|
30664
|
-
|
|
30947
|
+
} else if (key.backspace) {
|
|
30948
|
+
if (cursor > 0) {
|
|
30949
|
+
onChange(value.slice(0, cursor - 1) + value.slice(cursor));
|
|
30950
|
+
setCursor(cursor - 1);
|
|
30951
|
+
}
|
|
30952
|
+
} else if (key.delete) {
|
|
30953
|
+
if (cursor < value.length) onChange(value.slice(0, cursor) + value.slice(cursor + 1));
|
|
30954
|
+
} else if (extendedKey.home || key.ctrl && input === "a") {
|
|
30955
|
+
setCursor(0);
|
|
30956
|
+
} else if (extendedKey.end) {
|
|
30957
|
+
setCursor(value.length);
|
|
30958
|
+
} else if (key.leftArrow && key.ctrl) {
|
|
30959
|
+
setCursor((current) => moveCursorWordLeft(value, current));
|
|
30960
|
+
} else if (key.rightArrow && key.ctrl) {
|
|
30961
|
+
setCursor((current) => moveCursorWordRight(value, current));
|
|
30962
|
+
} else if (key.leftArrow) {
|
|
30963
|
+
setCursor((current) => moveCursorLeft(value, current));
|
|
30964
|
+
} else if (key.rightArrow) {
|
|
30965
|
+
setCursor((current) => moveCursorRight(value, current));
|
|
30665
30966
|
} else if (key.ctrl && input === "p" || key.upArrow && !transcriptNavigationActive) {
|
|
30666
30967
|
const nextIndex = historyIndex + 1;
|
|
30667
30968
|
if (nextIndex < history.length) {
|
|
30668
30969
|
setHistoryIndex(nextIndex);
|
|
30669
|
-
|
|
30970
|
+
const entry = history[history.length - 1 - nextIndex];
|
|
30971
|
+
const safeEntry = sanitizePromptInput(entry);
|
|
30972
|
+
onChange(safeEntry);
|
|
30973
|
+
setCursor(safeEntry.length);
|
|
30670
30974
|
}
|
|
30671
30975
|
} else if (key.ctrl && input === "n" || key.downArrow && !transcriptNavigationActive) {
|
|
30672
30976
|
const nextIndex = historyIndex - 1;
|
|
30673
30977
|
if (nextIndex >= 0) {
|
|
30674
30978
|
setHistoryIndex(nextIndex);
|
|
30675
|
-
|
|
30979
|
+
const entry = history[history.length - 1 - nextIndex];
|
|
30980
|
+
const safeEntry = sanitizePromptInput(entry);
|
|
30981
|
+
onChange(safeEntry);
|
|
30982
|
+
setCursor(safeEntry.length);
|
|
30676
30983
|
} else {
|
|
30677
30984
|
setHistoryIndex(-1);
|
|
30678
30985
|
onChange("");
|
|
30986
|
+
setCursor(0);
|
|
30679
30987
|
}
|
|
30680
30988
|
} else if ((key.upArrow || key.downArrow) && transcriptNavigationActive) {
|
|
30681
30989
|
return;
|
|
30682
30990
|
} else if (input && !key.ctrl && !key.meta) {
|
|
30683
|
-
|
|
30991
|
+
const safeInput = sanitizePromptInput(input);
|
|
30992
|
+
if (safeInput.length > 0) {
|
|
30993
|
+
onChange(value.slice(0, cursor) + safeInput + value.slice(cursor));
|
|
30994
|
+
setCursor(cursor + safeInput.length);
|
|
30995
|
+
}
|
|
30684
30996
|
}
|
|
30685
30997
|
});
|
|
30686
|
-
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
30998
|
+
return /* @__PURE__ */ jsxs6(Box6, { width: "100%", children: [
|
|
30687
30999
|
/* @__PURE__ */ jsx6(Text6, { bold: true, color: promptColor, children: "\u276F " }),
|
|
30688
|
-
/* @__PURE__ */ jsx6(Text6, { children: value }),
|
|
30689
|
-
!disabled && /* @__PURE__ */ jsx6(Text6, { backgroundColor: "white", color: "black", children: " " })
|
|
31000
|
+
/* @__PURE__ */ jsx6(Text6, { children: value.slice(0, cursor) }),
|
|
31001
|
+
!disabled && /* @__PURE__ */ jsx6(Text6, { backgroundColor: "white", color: "black", children: value[cursor] ?? " " }),
|
|
31002
|
+
/* @__PURE__ */ jsx6(Text6, { children: disabled ? value.slice(cursor) : value.slice(cursor + 1) })
|
|
30690
31003
|
] });
|
|
30691
31004
|
};
|
|
30692
31005
|
var PROMPT_COLOR_BY_MODE = {
|
|
@@ -30869,26 +31182,38 @@ init_errorPresentation();
|
|
|
30869
31182
|
|
|
30870
31183
|
// src/hooks/useTerminalResize.ts
|
|
30871
31184
|
init_esm_shims();
|
|
30872
|
-
import { useState as useState4, useEffect as
|
|
30873
|
-
function
|
|
31185
|
+
import { useState as useState4, useEffect as useEffect2, useCallback, useRef } from "react";
|
|
31186
|
+
function normalizeTerminalDimensions(columns, rows) {
|
|
30874
31187
|
return {
|
|
30875
|
-
columns:
|
|
30876
|
-
rows:
|
|
31188
|
+
columns: Number.isFinite(columns) && columns > 0 ? Math.floor(columns) : 80,
|
|
31189
|
+
rows: Number.isFinite(rows) && rows > 0 ? Math.floor(rows) : 24
|
|
30877
31190
|
};
|
|
30878
31191
|
}
|
|
31192
|
+
function getCurrentDimensions() {
|
|
31193
|
+
return normalizeTerminalDimensions(process.stdout.columns ?? 80, process.stdout.rows ?? 24);
|
|
31194
|
+
}
|
|
30879
31195
|
function useTerminalResize() {
|
|
30880
31196
|
const [dimensions, setDimensions] = useState4(
|
|
30881
31197
|
getCurrentDimensions
|
|
30882
31198
|
);
|
|
31199
|
+
const resizeTimer = useRef(null);
|
|
31200
|
+
const resizeEpoch = useRef(0);
|
|
30883
31201
|
const handleResize = useCallback(() => {
|
|
30884
|
-
|
|
31202
|
+
const epoch = ++resizeEpoch.current;
|
|
31203
|
+
if (resizeTimer.current !== null) clearTimeout(resizeTimer.current);
|
|
31204
|
+
resizeTimer.current = setTimeout(() => {
|
|
31205
|
+
resizeTimer.current = null;
|
|
31206
|
+
if (epoch === resizeEpoch.current) setDimensions(getCurrentDimensions());
|
|
31207
|
+
}, 16);
|
|
30885
31208
|
}, []);
|
|
30886
|
-
|
|
31209
|
+
useEffect2(() => {
|
|
30887
31210
|
process.stdout.on("resize", handleResize);
|
|
30888
31211
|
const onSigwinch = () => handleResize();
|
|
30889
31212
|
process.on("SIGWINCH", onSigwinch);
|
|
30890
31213
|
handleResize();
|
|
30891
31214
|
return () => {
|
|
31215
|
+
if (resizeTimer.current !== null) clearTimeout(resizeTimer.current);
|
|
31216
|
+
resizeTimer.current = null;
|
|
30892
31217
|
process.stdout.off("resize", handleResize);
|
|
30893
31218
|
process.off("SIGWINCH", onSigwinch);
|
|
30894
31219
|
};
|
|
@@ -30961,6 +31286,7 @@ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
|
30961
31286
|
var App = ({ compact: compact2 = false, continueSession: continueSession2 = false, executionMode: executionMode2 = "remote" }) => {
|
|
30962
31287
|
const [user, setUser] = useState5(null);
|
|
30963
31288
|
const [input, setInput] = useState5("");
|
|
31289
|
+
const terminalInputDecoder = useRef2(new TerminalInputDecoder());
|
|
30964
31290
|
const [history, setHistory] = useState5([]);
|
|
30965
31291
|
const [historyView, setHistoryView] = useState5(null);
|
|
30966
31292
|
const [historyOffset, setHistoryOffset] = useState5(0);
|
|
@@ -31034,15 +31360,15 @@ var App = ({ compact: compact2 = false, continueSession: continueSession2 = fals
|
|
|
31034
31360
|
const trustStore = useRef2(new TrustStore()).current;
|
|
31035
31361
|
const lastActivityRef = useRef2(Date.now());
|
|
31036
31362
|
const pollingIntervalRef = useRef2(null);
|
|
31037
|
-
|
|
31363
|
+
useEffect3(() => {
|
|
31038
31364
|
agent.setApprovalCallback(requestApproval);
|
|
31039
31365
|
}, [agent, requestApproval]);
|
|
31040
|
-
|
|
31366
|
+
useEffect3(() => {
|
|
31041
31367
|
if (bypassExpiry === null) return;
|
|
31042
31368
|
const timer = setInterval(() => setPermissionNow(Date.now()), 1e3);
|
|
31043
31369
|
return () => clearInterval(timer);
|
|
31044
31370
|
}, [bypassExpiry]);
|
|
31045
|
-
|
|
31371
|
+
useEffect3(() => {
|
|
31046
31372
|
agent.setOnModeChange((m) => {
|
|
31047
31373
|
setModeState(m);
|
|
31048
31374
|
addMessage("system", `Mode changed to: ${m} (via plan-mode tool)`);
|
|
@@ -31071,7 +31397,7 @@ var App = ({ compact: compact2 = false, continueSession: continueSession2 = fals
|
|
|
31071
31397
|
setModeState(m);
|
|
31072
31398
|
agent.setMode(m, source);
|
|
31073
31399
|
}, [agent]);
|
|
31074
|
-
|
|
31400
|
+
useEffect3(() => {
|
|
31075
31401
|
if (mode !== "bypassPermissions" || !isBypassExpired(bypassExpiry, permissionNow)) return;
|
|
31076
31402
|
setMode("default");
|
|
31077
31403
|
setBypassExpiry(null);
|
|
@@ -31173,7 +31499,7 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31173
31499
|
client.setToken("");
|
|
31174
31500
|
setStatus("Session expired - run /login");
|
|
31175
31501
|
}, [client, storage]);
|
|
31176
|
-
|
|
31502
|
+
useEffect3(() => {
|
|
31177
31503
|
agent.setAuthFailureHandler(handle401);
|
|
31178
31504
|
return () => agent.setAuthFailureHandler(null);
|
|
31179
31505
|
}, [agent, handle401]);
|
|
@@ -31194,7 +31520,7 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31194
31520
|
setStatus(classifyCliError(error, { executionMode: executionMode2 }).summary);
|
|
31195
31521
|
}
|
|
31196
31522
|
}, [client, activeChatId, setProjectId, handle401]);
|
|
31197
|
-
|
|
31523
|
+
useEffect3(() => {
|
|
31198
31524
|
(async () => {
|
|
31199
31525
|
try {
|
|
31200
31526
|
if (executionMode2 === "local") {
|
|
@@ -31306,14 +31632,14 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31306
31632
|
}
|
|
31307
31633
|
})();
|
|
31308
31634
|
}, []);
|
|
31309
|
-
|
|
31635
|
+
useEffect3(() => {
|
|
31310
31636
|
return () => {
|
|
31311
31637
|
void agent.flushPendingToolTelemetry();
|
|
31312
31638
|
void agent.flushPendingUsageTelemetry();
|
|
31313
31639
|
agent.fireLifecycleHook("session-end", { cwd: process.cwd() });
|
|
31314
31640
|
};
|
|
31315
31641
|
}, []);
|
|
31316
|
-
|
|
31642
|
+
useEffect3(() => {
|
|
31317
31643
|
if (!user) return;
|
|
31318
31644
|
createIdleAwarePoll(pollingIntervalRef, lastActivityRef, client, setUser, setUsageError);
|
|
31319
31645
|
return () => {
|
|
@@ -31414,7 +31740,7 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31414
31740
|
});
|
|
31415
31741
|
const relayCommandRef = useRef2(handleCommand);
|
|
31416
31742
|
relayCommandRef.current = handleCommand;
|
|
31417
|
-
|
|
31743
|
+
useEffect3(() => {
|
|
31418
31744
|
if (executionMode2 !== "remote" || process.env.MSAPLING_RELAY_ENABLED !== "1" || !activeProjectId) return;
|
|
31419
31745
|
let listener = null;
|
|
31420
31746
|
let cancelled = false;
|
|
@@ -31451,24 +31777,45 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31451
31777
|
const activityRows = pendingApproval ? 6 : pendingAskUser ? 10 : isRunning ? 2 : 0;
|
|
31452
31778
|
const visibleLines = Math.max(termHeight - (terminalLayout.fixedRows + footerRows + modeRows + activityRows), 1);
|
|
31453
31779
|
const displayedHistory = historyView ?? history;
|
|
31454
|
-
const historyPageStep = Math.max(1,
|
|
31455
|
-
const viewport = computeViewport(displayedHistory, visibleLines, termColumns, historyOffset);
|
|
31456
|
-
const
|
|
31780
|
+
const historyPageStep = Math.max(1, visibleLines - 1);
|
|
31781
|
+
const viewport = computeViewport(displayedHistory, visibleLines, termColumns, historyOffset, compactPresentation);
|
|
31782
|
+
const safeStatus = sanitizeTerminalText(status2, false);
|
|
31783
|
+
const safeProjectId = sanitizeTerminalText(activeProjectId || "none", false);
|
|
31784
|
+
const safeModel = sanitizeTerminalText(activeModel, false);
|
|
31785
|
+
const safeEnvironment = sanitizeTerminalText(remoteEnvironment.label, false);
|
|
31786
|
+
const canScrollOlder = viewport.hiddenRowsBefore > 0;
|
|
31457
31787
|
const canScrollNewer = historyOffset > 0;
|
|
31788
|
+
const previousTranscriptRowsRef = useRef2(viewport.totalRows);
|
|
31789
|
+
useEffect3(() => {
|
|
31790
|
+
const previousRows = previousTranscriptRowsRef.current;
|
|
31791
|
+
previousTranscriptRowsRef.current = viewport.totalRows;
|
|
31792
|
+
const rowDelta = viewport.totalRows - previousRows;
|
|
31793
|
+
if (historyOffset > 0 && rowDelta !== 0) {
|
|
31794
|
+
setHistoryOffset((current) => Math.min(
|
|
31795
|
+
Math.max(0, viewport.totalRows - 1),
|
|
31796
|
+
Math.max(0, current + rowDelta)
|
|
31797
|
+
));
|
|
31798
|
+
}
|
|
31799
|
+
}, [historyOffset, viewport.totalRows]);
|
|
31458
31800
|
const scrollTranscript = useCallback2((direction, page = false) => {
|
|
31459
31801
|
const amount = page ? historyPageStep : 1;
|
|
31460
31802
|
if (direction === "up") {
|
|
31461
|
-
setHistoryOffset((current) => Math.min(Math.max(0,
|
|
31803
|
+
setHistoryOffset((current) => Math.min(Math.max(0, viewport.totalRows - 1), current + amount));
|
|
31462
31804
|
} else {
|
|
31463
31805
|
setHistoryOffset((current) => Math.max(0, current - amount));
|
|
31464
31806
|
}
|
|
31465
|
-
}, [
|
|
31466
|
-
useTerminalMouseScroll((direction) => {
|
|
31467
|
-
if (!pendingApproval && !pendingAskUser) scrollTranscript(direction);
|
|
31468
|
-
});
|
|
31807
|
+
}, [historyPageStep, viewport.totalRows]);
|
|
31469
31808
|
useInput4((input2, key) => {
|
|
31470
31809
|
if (pendingApproval || pendingAskUser) return;
|
|
31471
|
-
|
|
31810
|
+
const decoded = terminalInputDecoder.current.feed(input2);
|
|
31811
|
+
if (decoded.protocol && !decoded.mouseWheel) return;
|
|
31812
|
+
if (isSgrMouseReport(input2) && !parseMouseWheel(input2)) return;
|
|
31813
|
+
const mouseWheel = decoded.mouseWheel ?? parseMouseWheel(input2);
|
|
31814
|
+
if (mouseWheel === "up") {
|
|
31815
|
+
scrollTranscript("up");
|
|
31816
|
+
} else if (mouseWheel === "down") {
|
|
31817
|
+
scrollTranscript("down");
|
|
31818
|
+
} else if (key.pageUp) {
|
|
31472
31819
|
scrollTranscript("up", true);
|
|
31473
31820
|
} else if (key.pageDown) {
|
|
31474
31821
|
scrollTranscript("down", true);
|
|
@@ -31481,9 +31828,9 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31481
31828
|
setHistoryView(null);
|
|
31482
31829
|
}
|
|
31483
31830
|
});
|
|
31484
|
-
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", padding: terminalLayout.outerPadding, children: [
|
|
31831
|
+
return /* @__PURE__ */ jsxs7(Box7, { width: termColumns, height: termHeight, flexDirection: "column", padding: terminalLayout.outerPadding, overflow: "hidden", children: [
|
|
31485
31832
|
/* @__PURE__ */ jsx7(Header, { compact: !terminalLayout.showFramedHeader }),
|
|
31486
|
-
/* @__PURE__ */ jsx7(Box7, {
|
|
31833
|
+
/* @__PURE__ */ jsx7(Box7, { width: "100%", flexGrow: 1, overflow: "hidden", children: /* @__PURE__ */ jsx7(
|
|
31487
31834
|
VirtualizedMessageList,
|
|
31488
31835
|
{
|
|
31489
31836
|
messages: displayedHistory,
|
|
@@ -31558,7 +31905,7 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31558
31905
|
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
31559
31906
|
/* @__PURE__ */ jsxs7(Text7, { color: executionMode2 === "local" ? "yellow" : "cyan", children: [
|
|
31560
31907
|
"Execution: ",
|
|
31561
|
-
executionMode2 === "local" ? "STANDALONE LOCAL" :
|
|
31908
|
+
executionMode2 === "local" ? "STANDALONE LOCAL" : safeEnvironment
|
|
31562
31909
|
] }),
|
|
31563
31910
|
/* @__PURE__ */ jsxs7(Text7, { color: billingProfile === "account-metered" ? "cyan" : "yellow", children: [
|
|
31564
31911
|
"Billing: ",
|
|
@@ -31571,15 +31918,15 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31571
31918
|
] }),
|
|
31572
31919
|
/* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
|
|
31573
31920
|
"Status: ",
|
|
31574
|
-
|
|
31921
|
+
safeStatus
|
|
31575
31922
|
] }),
|
|
31576
31923
|
/* @__PURE__ */ jsxs7(Text7, { color: "gray", children: [
|
|
31577
31924
|
"Project: ",
|
|
31578
|
-
|
|
31925
|
+
safeProjectId
|
|
31579
31926
|
] }),
|
|
31580
31927
|
/* @__PURE__ */ jsxs7(Text7, { color: "gray", children: [
|
|
31581
31928
|
"Model: ",
|
|
31582
|
-
|
|
31929
|
+
safeModel
|
|
31583
31930
|
] })
|
|
31584
31931
|
] }),
|
|
31585
31932
|
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", alignItems: "flex-end", children: [
|
|
@@ -31594,9 +31941,9 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31594
31941
|
contextBudgetSnap !== null && /* @__PURE__ */ jsx7(Text7, { color: contextBudgetColor(contextBudgetSnap.usedPct), children: formatContextBudgetLabel(contextBudgetSnap) })
|
|
31595
31942
|
] })
|
|
31596
31943
|
] }),
|
|
31597
|
-
terminalLayout.density === "condensed" && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
31944
|
+
terminalLayout.density === "condensed" && /* @__PURE__ */ jsxs7(Box7, { width: "100%", flexDirection: "column", children: [
|
|
31598
31945
|
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate-end", color: executionMode2 === "local" ? "yellow" : "cyan", children: [
|
|
31599
|
-
executionMode2 === "local" ? "LOCAL" :
|
|
31946
|
+
executionMode2 === "local" ? "LOCAL" : safeEnvironment.replace("CONNECTED ", ""),
|
|
31600
31947
|
" \xB7 ",
|
|
31601
31948
|
mode,
|
|
31602
31949
|
" \xB7 ",
|
|
@@ -31605,17 +31952,17 @@ ${renderCliError(classifyCliError(error, { executionMode: executionMode2 }))}`);
|
|
|
31605
31952
|
continuityProfile
|
|
31606
31953
|
] }),
|
|
31607
31954
|
/* @__PURE__ */ jsxs7(Text7, { wrap: "truncate-end", dimColor: true, children: [
|
|
31608
|
-
|
|
31955
|
+
safeModel,
|
|
31609
31956
|
contextBudgetSnap ? ` \xB7 ${formatContextBudgetLabel(contextBudgetSnap)}` : "",
|
|
31610
31957
|
lastCost > 0 ? ` \xB7 last $${lastCost.toFixed(4)}` : ""
|
|
31611
31958
|
] })
|
|
31612
31959
|
] }),
|
|
31613
31960
|
terminalLayout.density === "minimal" && /* @__PURE__ */ jsxs7(Text7, { wrap: "truncate-end", dimColor: true, children: [
|
|
31614
|
-
executionMode2 === "local" ? "LOCAL" :
|
|
31961
|
+
executionMode2 === "local" ? "LOCAL" : safeEnvironment.replace("CONNECTED ", ""),
|
|
31615
31962
|
" \xB7 ",
|
|
31616
31963
|
mode,
|
|
31617
31964
|
" \xB7 ",
|
|
31618
|
-
|
|
31965
|
+
safeModel,
|
|
31619
31966
|
lastCost > 0 ? ` \xB7 $${lastCost.toFixed(4)}` : "",
|
|
31620
31967
|
contextBudgetSnap ? ` \xB7 ctx ${contextBudgetSnap.usedPct}%` : ""
|
|
31621
31968
|
] }),
|
|
@@ -31834,26 +32181,7 @@ function handleCliArgs(args2) {
|
|
|
31834
32181
|
// src/index.tsx
|
|
31835
32182
|
init_src3();
|
|
31836
32183
|
init_errorPresentation();
|
|
31837
|
-
|
|
31838
|
-
// src/runtime/terminalScreen.ts
|
|
31839
|
-
init_esm_shims();
|
|
31840
|
-
var ENTER_ALTERNATE_SCREEN = "\x1B[?1049h\x1B[H";
|
|
31841
|
-
var LEAVE_ALTERNATE_SCREEN = "\x1B[?1049l\x1B[?25h";
|
|
31842
|
-
var alternateScreenActive = false;
|
|
31843
|
-
function enterAlternateScreen(output = process.stdout, env = process.env) {
|
|
31844
|
-
if (alternateScreenActive || !output.isTTY || env.MSAPLING_NO_ALT_SCREEN === "1" || env.TERM === "dumb") return false;
|
|
31845
|
-
output.write(ENTER_ALTERNATE_SCREEN);
|
|
31846
|
-
alternateScreenActive = true;
|
|
31847
|
-
return true;
|
|
31848
|
-
}
|
|
31849
|
-
function leaveAlternateScreen(output = process.stdout) {
|
|
31850
|
-
if (!alternateScreenActive) return false;
|
|
31851
|
-
output.write(LEAVE_ALTERNATE_SCREEN);
|
|
31852
|
-
alternateScreenActive = false;
|
|
31853
|
-
return true;
|
|
31854
|
-
}
|
|
31855
|
-
|
|
31856
|
-
// src/index.tsx
|
|
32184
|
+
init_terminalScreen();
|
|
31857
32185
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
31858
32186
|
var index_default = App;
|
|
31859
32187
|
function restoreTerminalMode() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msapling",
|
|
3
|
-
"version": "2.3.6-beta.
|
|
3
|
+
"version": "2.3.6-beta.62",
|
|
4
4
|
"description": "Short-name distribution of the MSapling CLI.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "MSapling Team",
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
"proper-lockfile": "^4.1.2",
|
|
49
49
|
"react": "^18.3.1",
|
|
50
50
|
"shell-quote": "^1.8.1",
|
|
51
|
+
"string-width": "^5.1.2",
|
|
52
|
+
"strip-ansi": "^7.1.0",
|
|
51
53
|
"yaml": "^2.8.3"
|
|
52
54
|
},
|
|
53
55
|
"optionalDependencies": {
|