negotium 0.22.7 → 0.23.0
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/agent-helpers.js +31 -14
- package/dist/agent-helpers.js.map +4 -4
- package/dist/{chunk-1gznvrth.js → chunk-qmpbb92y.js} +2 -2
- package/dist/{chunk-1gznvrth.js.map → chunk-qmpbb92y.js.map} +2 -2
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +664 -107
- package/dist/main.js.map +10 -10
- package/dist/mcp-factories.js +31 -14
- package/dist/mcp-factories.js.map +4 -4
- package/dist/registry.js +1 -1
- package/dist/runtime/src/mcp-runtime-host.ts +1 -0
- package/dist/runtime/src/runtime/visuals.ts +47 -11
- package/dist/runtime/src/version.ts +1 -1
- package/dist/types/packages/core/src/runtime/visuals.d.ts +9 -2
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -6559,7 +6559,7 @@ var exports_version = {};
|
|
|
6559
6559
|
__export(exports_version, {
|
|
6560
6560
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
6561
6561
|
});
|
|
6562
|
-
var NEGOTIUM_VERSION = "0.
|
|
6562
|
+
var NEGOTIUM_VERSION = "0.23.0";
|
|
6563
6563
|
|
|
6564
6564
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
6565
6565
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -21485,7 +21485,7 @@ function buildVideoHtml(mimeType) {
|
|
|
21485
21485
|
<body><video controls playsinline preload="metadata" src="${VISUAL_MEDIA_URL_PLACEHOLDER}" data-mime="${escapeHtml2(mimeType)}"></video></body>
|
|
21486
21486
|
</html>`;
|
|
21487
21487
|
}
|
|
21488
|
-
function
|
|
21488
|
+
function locateVisualMediaInput(topicId, input) {
|
|
21489
21489
|
if (typeof input.file_id === "string" && input.file_id.trim()) {
|
|
21490
21490
|
const fileId = input.file_id.trim().toLowerCase();
|
|
21491
21491
|
if (!isUploadFileId(fileId))
|
|
@@ -21493,15 +21493,11 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
21493
21493
|
if (!topicAllowsVisualFileId(topicId, fileId)) {
|
|
21494
21494
|
return { error: "file_id is not attached to this topic" };
|
|
21495
21495
|
}
|
|
21496
|
-
const
|
|
21497
|
-
const
|
|
21498
|
-
if (!
|
|
21496
|
+
const attachment = resolveAttachmentByFileId(fileId);
|
|
21497
|
+
const filePath = resolveUploadedFilePathByFileId(fileId);
|
|
21498
|
+
if (!attachment || !filePath)
|
|
21499
21499
|
return { error: `uploaded file not found: ${fileId}` };
|
|
21500
|
-
return {
|
|
21501
|
-
fileId: attachment2.id,
|
|
21502
|
-
mimeType: attachment2.mimeType,
|
|
21503
|
-
source: `file_id:${attachment2.id}`
|
|
21504
|
-
};
|
|
21500
|
+
return { kind: "upload", fileId: attachment.id, mimeType: attachment.mimeType };
|
|
21505
21501
|
}
|
|
21506
21502
|
if (typeof input.file_path !== "string" || !input.file_path.trim()) {
|
|
21507
21503
|
return { error: "file_path or file_id is required" };
|
|
@@ -21509,18 +21505,38 @@ function resolveVisualMediaInput(topicId, input) {
|
|
|
21509
21505
|
const rawPath = input.file_path.trim();
|
|
21510
21506
|
const cwd = workspaceCwdFor(topicId);
|
|
21511
21507
|
const candidate = isAbsolute5(rawPath) ? rawPath : resolve16(cwd, rawPath);
|
|
21512
|
-
if (!isPathInside(cwd, candidate)) {
|
|
21513
|
-
return { error: "file_path must be inside the topic workspace" };
|
|
21514
|
-
}
|
|
21515
21508
|
let realCandidate;
|
|
21516
21509
|
try {
|
|
21517
21510
|
realCandidate = realpathSync5(candidate);
|
|
21518
21511
|
} catch {
|
|
21519
21512
|
return { error: `file not found: ${rawPath}` };
|
|
21520
21513
|
}
|
|
21514
|
+
if (!isPathInside(cwd, realCandidate)) {
|
|
21515
|
+
return {
|
|
21516
|
+
error: `file_path must be inside the topic workspace (${cwd}); copy the file into it and pass the copy`
|
|
21517
|
+
};
|
|
21518
|
+
}
|
|
21521
21519
|
if (isSensitivePath(realCandidate)) {
|
|
21522
21520
|
return { error: "file_path matches the sensitive-file blacklist" };
|
|
21523
21521
|
}
|
|
21522
|
+
return { kind: "file", path: realCandidate, rawPath };
|
|
21523
|
+
}
|
|
21524
|
+
function visualMediaInputError(topicId, input) {
|
|
21525
|
+
const located = locateVisualMediaInput(topicId, input);
|
|
21526
|
+
return "error" in located ? located.error : null;
|
|
21527
|
+
}
|
|
21528
|
+
function resolveVisualMediaInput(topicId, input) {
|
|
21529
|
+
const located = locateVisualMediaInput(topicId, input);
|
|
21530
|
+
if ("error" in located)
|
|
21531
|
+
return located;
|
|
21532
|
+
if (located.kind === "upload") {
|
|
21533
|
+
return {
|
|
21534
|
+
fileId: located.fileId,
|
|
21535
|
+
mimeType: located.mimeType,
|
|
21536
|
+
source: `file_id:${located.fileId}`
|
|
21537
|
+
};
|
|
21538
|
+
}
|
|
21539
|
+
const { path: realCandidate, rawPath } = located;
|
|
21524
21540
|
const attachment = storeLocalFileAsUpload(realCandidate, { topicId });
|
|
21525
21541
|
if (!attachment)
|
|
21526
21542
|
return { error: `failed to store media file: ${rawPath}` };
|
|
@@ -22791,6 +22807,7 @@ __export(exports_turn_runner, {
|
|
|
22791
22807
|
workspaceCwdFor: () => workspaceCwdFor,
|
|
22792
22808
|
withDefaultPlaywright: () => withDefaultPlaywright,
|
|
22793
22809
|
wasLocallyRequeuedAfterUserPreemption: () => wasLocallyRequeuedAfterUserPreemption,
|
|
22810
|
+
visualMediaInputError: () => visualMediaInputError,
|
|
22794
22811
|
userConversationPromptsToRecord: () => userConversationPromptsToRecord,
|
|
22795
22812
|
upsertTaskPanelMessage: () => upsertTaskPanelMessage,
|
|
22796
22813
|
tryReconstructTopicRollout: () => tryReconstructTopicRollout,
|
|
@@ -30444,6 +30461,7 @@ var init_thread_read = __esm(async () => {
|
|
|
30444
30461
|
var exports_mcp_runtime_host = {};
|
|
30445
30462
|
__export(exports_mcp_runtime_host, {
|
|
30446
30463
|
visualToolDefinitions: () => visualToolDefinitions,
|
|
30464
|
+
visualMediaInputError: () => visualMediaInputError,
|
|
30447
30465
|
textResult: () => textResult,
|
|
30448
30466
|
storeLocalFileAsUpload: () => storeLocalFileAsUpload,
|
|
30449
30467
|
showPngTool: () => showPngTool,
|
|
@@ -30457,6 +30475,7 @@ __export(exports_mcp_runtime_host, {
|
|
|
30457
30475
|
prepareDeliveryAck: () => prepareDeliveryAck,
|
|
30458
30476
|
logger: () => logger,
|
|
30459
30477
|
listTopicThreadRoots: () => listTopicThreadRoots,
|
|
30478
|
+
isVisualsShowImageTool: () => isVisualsShowImageTool,
|
|
30460
30479
|
isSensitivePath: () => isSensitivePath,
|
|
30461
30480
|
isParticipant: () => isParticipant,
|
|
30462
30481
|
isInsideDir: () => isInsideDir,
|
|
@@ -30533,6 +30552,7 @@ var init_mcp_runtime_host = __esm(async () => {
|
|
|
30533
30552
|
init_actor_topic_reach(),
|
|
30534
30553
|
init_delivery_ack(),
|
|
30535
30554
|
init_thread_read(),
|
|
30555
|
+
init_visuals(),
|
|
30536
30556
|
init_api_messages(),
|
|
30537
30557
|
init_api_topic_config(),
|
|
30538
30558
|
init_api_topics(),
|
|
@@ -35524,7 +35544,12 @@ function buildNegotiumMcpServer(ctx) {
|
|
|
35524
35544
|
const server = new McpServer8({ name: RUNTIME_MCP_KEY, version: "1.0.0" });
|
|
35525
35545
|
if (ctx.visualTools === true) {
|
|
35526
35546
|
for (const def of [...visualToolDefinitions, showPngTool]) {
|
|
35527
|
-
const handler = ctx.peerBridge && (def.name === "show_html" || def.name === "show_mermaid") ? async () => textResult("Visual queued for ordered display on the canonical hub.") : def.
|
|
35547
|
+
const handler = ctx.peerBridge && (def.name === "show_html" || def.name === "show_mermaid") ? async () => textResult("Visual queued for ordered display on the canonical hub.") : isVisualsShowImageTool(def.name) ? async (input) => {
|
|
35548
|
+
const problem = visualMediaInputError(ctx.topicId, input ?? {});
|
|
35549
|
+
if (problem)
|
|
35550
|
+
return errorResult(`Error: ${problem}`);
|
|
35551
|
+
return def.handler(input);
|
|
35552
|
+
} : def.handler;
|
|
35528
35553
|
server.tool(def.name, def.description, def.schema, handler);
|
|
35529
35554
|
}
|
|
35530
35555
|
const publishTools = createPublishHtmlToolDefinitions({ cwd: ctx.cwd });
|
|
@@ -41904,7 +41929,10 @@ function createInitialState(userId) {
|
|
|
41904
41929
|
decisionGraphOffset: { x: 0, y: 0 },
|
|
41905
41930
|
decisionGraphSpacing: DEFAULT_DECISION_GRAPH_SPACING,
|
|
41906
41931
|
askChoiceIndex: 0,
|
|
41907
|
-
|
|
41932
|
+
taskPanelScrollOffset: 0,
|
|
41933
|
+
topicsPanelEnabled: true,
|
|
41934
|
+
topicsPanelScrollOffset: 0,
|
|
41935
|
+
topicsPanelSort: "activity",
|
|
41908
41936
|
overlay: null,
|
|
41909
41937
|
topicPickerRoot: false,
|
|
41910
41938
|
vaultEntries: [],
|
|
@@ -41916,8 +41944,27 @@ function createInitialState(userId) {
|
|
|
41916
41944
|
vaultRequestSubmitting: false
|
|
41917
41945
|
};
|
|
41918
41946
|
}
|
|
41919
|
-
function
|
|
41920
|
-
return { ...state,
|
|
41947
|
+
function toggleTopicsPanel(state) {
|
|
41948
|
+
return { ...state, topicsPanelEnabled: !state.topicsPanelEnabled };
|
|
41949
|
+
}
|
|
41950
|
+
function cycleTopicsPanelSort(state) {
|
|
41951
|
+
return { ...state, topicsPanelSort: state.topicsPanelSort === "activity" ? "name" : "activity" };
|
|
41952
|
+
}
|
|
41953
|
+
function scrollTopicsPanel(state, delta, maxOffset) {
|
|
41954
|
+
const next = Math.min(maxOffset, Math.max(0, state.topicsPanelScrollOffset + delta));
|
|
41955
|
+
return next === state.topicsPanelScrollOffset ? state : { ...state, topicsPanelScrollOffset: next };
|
|
41956
|
+
}
|
|
41957
|
+
function scrollTaskPanel(state, delta, maxOffset) {
|
|
41958
|
+
const next = Math.min(maxOffset, Math.max(0, state.taskPanelScrollOffset + delta));
|
|
41959
|
+
return next === state.taskPanelScrollOffset ? state : { ...state, taskPanelScrollOffset: next };
|
|
41960
|
+
}
|
|
41961
|
+
function setTopicsPanelScrollOffset(state, offset, maxOffset) {
|
|
41962
|
+
const next = Math.min(maxOffset, Math.max(0, offset));
|
|
41963
|
+
return next === state.topicsPanelScrollOffset ? state : { ...state, topicsPanelScrollOffset: next };
|
|
41964
|
+
}
|
|
41965
|
+
function setTaskPanelScrollOffset(state, offset, maxOffset) {
|
|
41966
|
+
const next = Math.min(maxOffset, Math.max(0, offset));
|
|
41967
|
+
return next === state.taskPanelScrollOffset ? state : { ...state, taskPanelScrollOffset: next };
|
|
41921
41968
|
}
|
|
41922
41969
|
function activeTopic(state) {
|
|
41923
41970
|
return state.topics.find((topic) => topic.id === state.activeTopicId) ?? null;
|
|
@@ -41934,6 +41981,16 @@ function setTopicUsage(state, usage) {
|
|
|
41934
41981
|
function activeQuestion(state) {
|
|
41935
41982
|
return activeMessages(state).slice().reverse().find((message2) => message2.kind === "ask_user_question" && message2.askUserQuestion && !message2.askUserQuestion.expired && !message2.askUserQuestion.selectedLabel) ?? null;
|
|
41936
41983
|
}
|
|
41984
|
+
function blockedQuestionText(state, topicId) {
|
|
41985
|
+
const messages = state.messages[topicId] ?? [];
|
|
41986
|
+
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
41987
|
+
const message2 = messages[index];
|
|
41988
|
+
if (message2.kind === "ask_user_question" && message2.askUserQuestion && !message2.askUserQuestion.expired && !message2.askUserQuestion.selectedLabel) {
|
|
41989
|
+
return message2.askUserQuestion.question;
|
|
41990
|
+
}
|
|
41991
|
+
}
|
|
41992
|
+
return;
|
|
41993
|
+
}
|
|
41937
41994
|
function activeVaultRequest(state) {
|
|
41938
41995
|
return activeMessages(state).find((message2) => message2.kind === "vault_secret_request" && message2.vaultSecretRequest?.status === "pending") ?? null;
|
|
41939
41996
|
}
|
|
@@ -42037,12 +42094,43 @@ function visibleTopicPickerIds(state) {
|
|
|
42037
42094
|
function visibleBackgroundSessions(state) {
|
|
42038
42095
|
return state.backgroundSessions.filter((session) => topicPickerQueryMatches(session.title, state.topicFilter));
|
|
42039
42096
|
}
|
|
42097
|
+
function topicRank(state, topic) {
|
|
42098
|
+
if (blockedQuestionText(state, topic.id) !== undefined)
|
|
42099
|
+
return 0;
|
|
42100
|
+
if (state.activity[topic.id]?.running)
|
|
42101
|
+
return 1;
|
|
42102
|
+
return 2;
|
|
42103
|
+
}
|
|
42104
|
+
function groupTopicsIntoUnits(entries) {
|
|
42105
|
+
const units = [];
|
|
42106
|
+
for (const entry of entries) {
|
|
42107
|
+
const last = units.at(-1);
|
|
42108
|
+
if (entry.topic.isSubagent && last)
|
|
42109
|
+
last.push(entry);
|
|
42110
|
+
else
|
|
42111
|
+
units.push([entry]);
|
|
42112
|
+
}
|
|
42113
|
+
return units;
|
|
42114
|
+
}
|
|
42115
|
+
function sortedTopicEntries(state, entries) {
|
|
42116
|
+
const units = groupTopicsIntoUnits(entries);
|
|
42117
|
+
if (state.topicsPanelSort === "name") {
|
|
42118
|
+
return units.slice().sort((a, b) => (a[0]?.topic.title ?? "").localeCompare(b[0]?.topic.title ?? "")).flat();
|
|
42119
|
+
}
|
|
42120
|
+
return units.map((unit, order) => ({
|
|
42121
|
+
unit,
|
|
42122
|
+
order,
|
|
42123
|
+
rank: Math.min(...unit.map(({ topic }) => topicRank(state, topic)))
|
|
42124
|
+
})).sort((a, b) => a.rank - b.rank || a.order - b.order).flatMap(({ unit }) => unit);
|
|
42125
|
+
}
|
|
42040
42126
|
function topicPickerItems(state) {
|
|
42041
42127
|
const visible = visibleTopicPickerIds(state);
|
|
42042
42128
|
const indexedTopics = state.topics.map((topic, index) => ({ topic, index })).filter(({ topic }) => visible.has(topic.id));
|
|
42129
|
+
const managerEntries = sortedTopicEntries(state, indexedTopics.filter(({ topic }) => topic.kind === "manager"));
|
|
42130
|
+
const regularEntries = sortedTopicEntries(state, indexedTopics.filter(({ topic }) => topic.kind !== "manager"));
|
|
42043
42131
|
return [
|
|
42044
|
-
...
|
|
42045
|
-
...
|
|
42132
|
+
...managerEntries.map(({ topic, index }) => ({ kind: "topic", id: topic.id, index })),
|
|
42133
|
+
...regularEntries.map(({ topic, index }) => ({ kind: "topic", id: topic.id, index })),
|
|
42046
42134
|
...visibleBackgroundSessions(state).map((session) => ({
|
|
42047
42135
|
kind: "background",
|
|
42048
42136
|
id: session.id
|
|
@@ -42334,6 +42422,22 @@ function failedToolText(text3) {
|
|
|
42334
42422
|
return [title, ...mapped].join(`
|
|
42335
42423
|
`);
|
|
42336
42424
|
}
|
|
42425
|
+
function appendToolOutput(text3, content) {
|
|
42426
|
+
if (!content.trim())
|
|
42427
|
+
return text3;
|
|
42428
|
+
const [title = "Tool"] = text3.split(`
|
|
42429
|
+
`);
|
|
42430
|
+
if (TOOL_OUTPUT_EXCLUDED_PREFIXES.some((prefix) => title.startsWith(prefix)))
|
|
42431
|
+
return text3;
|
|
42432
|
+
if (text3.includes(`
|
|
42433
|
+
`))
|
|
42434
|
+
return text3;
|
|
42435
|
+
const lines = content.replace(/\r\n?/g, `
|
|
42436
|
+
`).replace(/\n+$/, "").split(`
|
|
42437
|
+
`);
|
|
42438
|
+
return [title, ...lines].join(`
|
|
42439
|
+
`);
|
|
42440
|
+
}
|
|
42337
42441
|
function toolMessageId(status, toolUseId) {
|
|
42338
42442
|
return `terminal-tool:${String(status.queryId ?? "query")}:${toolUseId}`;
|
|
42339
42443
|
}
|
|
@@ -42433,14 +42537,17 @@ function applyAiStatus(state, topicId, raw, createdAt) {
|
|
|
42433
42537
|
return state;
|
|
42434
42538
|
const id = String(status.toolUseId ?? "");
|
|
42435
42539
|
const failed = status.isError === true;
|
|
42436
|
-
const
|
|
42540
|
+
const content = String(status.content ?? "");
|
|
42541
|
+
const tools = current3.tools.map((tool) => tool.id === id ? { ...tool, output: content, status: failed ? "error" : "done" } : tool);
|
|
42437
42542
|
const withActivity = setActivity(state, topicId, { ...liveCurrent, tools });
|
|
42438
42543
|
const messageId = toolMessageId(status, id);
|
|
42439
42544
|
const existing = (withActivity.messages[topicId] ?? []).find((message2) => message2.id === messageId);
|
|
42545
|
+
const withOutput = existing ? appendToolOutput(existing.text, content) : undefined;
|
|
42546
|
+
const nextText = failed && (!existing || withOutput === existing.text) ? failedToolText(existing?.text ?? "") : withOutput;
|
|
42440
42547
|
return patchMessage(withActivity, topicId, messageId, {
|
|
42441
42548
|
editedAt: createdAt ?? new Date().toISOString(),
|
|
42442
42549
|
toolResult: failed ? "error" : "ok",
|
|
42443
|
-
...
|
|
42550
|
+
...nextText !== undefined ? { text: nextText } : {}
|
|
42444
42551
|
});
|
|
42445
42552
|
}
|
|
42446
42553
|
if (kind === "tool_status") {
|
|
@@ -42473,11 +42580,18 @@ function applyRuntimeEvent(state, event) {
|
|
|
42473
42580
|
}
|
|
42474
42581
|
return state;
|
|
42475
42582
|
}
|
|
42476
|
-
var NO_TOPIC_PICKER_SELECTION = -1;
|
|
42583
|
+
var NO_TOPIC_PICKER_SELECTION = -1, TOOL_OUTPUT_EXCLUDED_PREFIXES;
|
|
42477
42584
|
var init_state2 = __esm(async () => {
|
|
42478
42585
|
init_decision_graph();
|
|
42479
42586
|
init_subagent_graph();
|
|
42480
42587
|
await init_src();
|
|
42588
|
+
TOOL_OUTPUT_EXCLUDED_PREFIXES = [
|
|
42589
|
+
"Edit \xB7 ",
|
|
42590
|
+
"Write \xB7 ",
|
|
42591
|
+
"Delete \xB7 ",
|
|
42592
|
+
"Ask session \xB7 ",
|
|
42593
|
+
"Tell session \xB7 "
|
|
42594
|
+
];
|
|
42481
42595
|
});
|
|
42482
42596
|
|
|
42483
42597
|
// ../../adapters/terminal/src/context-usage.ts
|
|
@@ -43590,7 +43704,6 @@ function toolMessageLines(message2, width) {
|
|
|
43590
43704
|
`);
|
|
43591
43705
|
const failed = message2.toolResult === "error";
|
|
43592
43706
|
const done = failed || Boolean(message2.editedAt);
|
|
43593
|
-
const fileMutation = /^(?:Edit|Write|Delete) \u00B7 /.test(title);
|
|
43594
43707
|
const wrapWidth = Math.max(4, width - 6);
|
|
43595
43708
|
const marker = failed ? "!" : done ? "\u2713" : "\u25CF";
|
|
43596
43709
|
const headerText = ` ${marker} ${title}`;
|
|
@@ -43606,14 +43719,8 @@ function toolMessageLines(message2, width) {
|
|
|
43606
43719
|
{ text: ")" }
|
|
43607
43720
|
] : [{ text: headerText, fg: headerColor }]
|
|
43608
43721
|
});
|
|
43609
|
-
if (!fileMutation) {
|
|
43610
|
-
return [
|
|
43611
|
-
header,
|
|
43612
|
-
...details.slice(0, 2).flatMap((detail) => wrapText(detail, wrapWidth).slice(0, 1).map((text3) => line(` ${text3}`, { fg: toolDetailColor(detail), dim: !failed })))
|
|
43613
|
-
];
|
|
43614
|
-
}
|
|
43615
43722
|
const wrapped = details.flatMap((detail) => wrapText(detail, wrapWidth).map((text3) => ({ detail, text: text3 })));
|
|
43616
|
-
const visible = wrapped.slice(0,
|
|
43723
|
+
const visible = wrapped.slice(0, TOOL_PREVIEW_MAX_LINES);
|
|
43617
43724
|
const hidden = wrapped.length - visible.length;
|
|
43618
43725
|
return [
|
|
43619
43726
|
header,
|
|
@@ -43718,50 +43825,255 @@ function taskLines(state, width) {
|
|
|
43718
43825
|
const visibleTasks = tasks3.slice(0, INLINE_TASK_LIMIT);
|
|
43719
43826
|
const hidden = tasks3.length - visibleTasks.length;
|
|
43720
43827
|
return [
|
|
43721
|
-
line(" \u25EB Tasks \xB7 Ctrl-
|
|
43828
|
+
line(" \u25EB Tasks \xB7 Ctrl-P sidebar", { fg: theme.amber, bold: true }),
|
|
43722
43829
|
...visibleTasks.flatMap((task) => wrapText(task.trimStart(), Math.max(4, width - 6)).map((text3) => line(` ${text3}`, { fg: theme.muted }))),
|
|
43723
43830
|
...hidden > 0 ? [line(` +${hidden} more`, { fg: theme.muted, dim: true })] : [],
|
|
43724
43831
|
line("")
|
|
43725
43832
|
];
|
|
43726
43833
|
}
|
|
43727
43834
|
function terminalBodyLayout(state, width) {
|
|
43728
|
-
const
|
|
43835
|
+
const wideEnough = width >= SIDE_PANEL_MIN_WIDTH && state.topicsPanelEnabled && (!state.overlay || state.overlay === "background-session") && !state.creatingTopic;
|
|
43836
|
+
const showTaskPanel = wideEnough && taskItems(state).length > 0;
|
|
43837
|
+
const showTopicsPanel = wideEnough && (state.topics.length > 1 || visibleBackgroundSessions(state).length > 0);
|
|
43838
|
+
const showSide = showTaskPanel || showTopicsPanel;
|
|
43729
43839
|
return {
|
|
43730
|
-
conversationWidth:
|
|
43731
|
-
|
|
43732
|
-
|
|
43733
|
-
|
|
43840
|
+
conversationWidth: showSide ? width - SIDE_PANEL_WIDTH - SIDE_PANEL_GAP : width,
|
|
43841
|
+
sideWidth: showSide ? SIDE_PANEL_WIDTH : 0,
|
|
43842
|
+
showTaskPanel,
|
|
43843
|
+
showTopicsPanel
|
|
43844
|
+
};
|
|
43845
|
+
}
|
|
43846
|
+
function topicStatusIndicator(state, topic, animationFrame) {
|
|
43847
|
+
const blockedText = blockedQuestionText(state, topic.id);
|
|
43848
|
+
if (blockedText !== undefined)
|
|
43849
|
+
return { icon: "?", fg: theme.amber, blockedText };
|
|
43850
|
+
if (state.activity[topic.id]?.running) {
|
|
43851
|
+
return { icon: workingFrame(animationFrame), fg: theme.green };
|
|
43852
|
+
}
|
|
43853
|
+
return { icon: "\u25CB", fg: theme.muted };
|
|
43854
|
+
}
|
|
43855
|
+
function topicPanelRowLines(state, topic, topicIndex, animationFrame) {
|
|
43856
|
+
const selected = topic.id === state.activeTopicId;
|
|
43857
|
+
const hovered = !selected && topic.id === state.sidePanelHoverTopicId;
|
|
43858
|
+
const status = topicStatusIndicator(state, topic, animationFrame);
|
|
43859
|
+
const childPrefix = subagentTreePrefix(topic, state.topics);
|
|
43860
|
+
const bg2 = selected || hovered ? theme.selected : theme.canvas;
|
|
43861
|
+
const header = line(` ${selected ? "\u203A" : " "} ${childPrefix}${status.icon} ${topic.title}`, {
|
|
43862
|
+
fg: selected ? theme.text : status.fg,
|
|
43863
|
+
bg: bg2,
|
|
43864
|
+
bold: selected,
|
|
43865
|
+
pickerTarget: { topicIndex }
|
|
43866
|
+
});
|
|
43867
|
+
if (status.blockedText === undefined)
|
|
43868
|
+
return [header];
|
|
43869
|
+
return [
|
|
43870
|
+
header,
|
|
43871
|
+
line(` ${status.blockedText}`, {
|
|
43872
|
+
fg: theme.amber,
|
|
43873
|
+
bg: bg2,
|
|
43874
|
+
pickerTarget: { topicIndex }
|
|
43875
|
+
})
|
|
43876
|
+
];
|
|
43877
|
+
}
|
|
43878
|
+
function topicPanelGroupLines(state, label, entries, animationFrame) {
|
|
43879
|
+
if (entries.length === 0)
|
|
43880
|
+
return [];
|
|
43881
|
+
return [
|
|
43882
|
+
line(` ${label}`, { fg: theme.cyan, dim: true, bold: true, bg: theme.canvas }),
|
|
43883
|
+
...sortedTopicEntries(state, entries).flatMap(({ topic, topicIndex }) => topicPanelRowLines(state, topic, topicIndex, animationFrame))
|
|
43884
|
+
];
|
|
43885
|
+
}
|
|
43886
|
+
function topicsPanelRows(state, animationFrame) {
|
|
43887
|
+
const indexed = state.topics.map((topic, topicIndex) => ({ topic, topicIndex }));
|
|
43888
|
+
const managerEntries = indexed.filter(({ topic }) => topic.kind === "manager");
|
|
43889
|
+
const regularEntries = indexed.filter(({ topic }) => topic.kind !== "manager");
|
|
43890
|
+
const topicRows = [
|
|
43891
|
+
...topicPanelGroupLines(state, "manager", managerEntries, animationFrame),
|
|
43892
|
+
...topicPanelGroupLines(state, "topics", regularEntries, animationFrame)
|
|
43893
|
+
];
|
|
43894
|
+
const sessionRows = ["cron", "memory", "compact"].flatMap((kind) => {
|
|
43895
|
+
const matching = visibleBackgroundSessions(state).filter((session) => session.kind === kind);
|
|
43896
|
+
if (matching.length === 0)
|
|
43897
|
+
return [];
|
|
43898
|
+
return [
|
|
43899
|
+
line(` ${kind}`, { fg: theme.cyan, dim: true, bold: true, bg: theme.canvas }),
|
|
43900
|
+
...matching.map((session) => {
|
|
43901
|
+
const hovered = session.id === state.sidePanelHoverBackgroundSessionId;
|
|
43902
|
+
return line(` ${session.active ? workingFrame(animationFrame) : "\u25CB"} ${session.title}`, {
|
|
43903
|
+
fg: hovered ? theme.text : session.active ? theme.green : theme.muted,
|
|
43904
|
+
bg: hovered ? theme.selected : theme.canvas,
|
|
43905
|
+
pickerTarget: { backgroundSessionId: session.id }
|
|
43906
|
+
});
|
|
43907
|
+
})
|
|
43908
|
+
];
|
|
43909
|
+
});
|
|
43910
|
+
return [...topicRows, ...sessionRows];
|
|
43734
43911
|
}
|
|
43735
|
-
function
|
|
43912
|
+
function taskPanelRows(state, width) {
|
|
43736
43913
|
const items = taskItems(state);
|
|
43737
|
-
|
|
43914
|
+
return items.flatMap((task) => {
|
|
43738
43915
|
const completed = /^\s*(?:\[x\]|\u2612|\u2713|\u2705)/i.test(task);
|
|
43739
|
-
return wrapText(task.trimStart(), Math.max(4, width -
|
|
43916
|
+
return wrapText(task.trimStart(), Math.max(4, width - 2)).map((text3) => line(` ${text3}`, {
|
|
43740
43917
|
fg: completed ? theme.muted : theme.text,
|
|
43741
|
-
dim: completed
|
|
43918
|
+
dim: completed,
|
|
43919
|
+
bg: theme.canvas
|
|
43742
43920
|
}));
|
|
43743
43921
|
});
|
|
43744
|
-
|
|
43745
|
-
|
|
43746
|
-
|
|
43747
|
-
|
|
43748
|
-
|
|
43749
|
-
|
|
43750
|
-
|
|
43751
|
-
|
|
43752
|
-
|
|
43753
|
-
|
|
43754
|
-
|
|
43755
|
-
|
|
43756
|
-
|
|
43757
|
-
|
|
43758
|
-
|
|
43922
|
+
}
|
|
43923
|
+
function panelHeaderHeight(sectionHeight) {
|
|
43924
|
+
return Math.min(2, sectionHeight);
|
|
43925
|
+
}
|
|
43926
|
+
function panelContentHeight(sectionHeight) {
|
|
43927
|
+
return Math.max(0, sectionHeight - panelHeaderHeight(sectionHeight));
|
|
43928
|
+
}
|
|
43929
|
+
function scrollbarThumb(totalRows, viewportRows, offset) {
|
|
43930
|
+
if (viewportRows <= 0 || totalRows <= 0)
|
|
43931
|
+
return { top: 0, len: 0 };
|
|
43932
|
+
const len = Math.max(1, Math.min(viewportRows, Math.round(viewportRows * viewportRows / totalRows)));
|
|
43933
|
+
const maxThumbTop = Math.max(0, viewportRows - len);
|
|
43934
|
+
const maxOffset = Math.max(1, totalRows - viewportRows);
|
|
43935
|
+
const top = maxThumbTop === 0 ? 0 : Math.round(Math.min(offset, maxOffset) * maxThumbTop / maxOffset);
|
|
43936
|
+
return { top, len };
|
|
43937
|
+
}
|
|
43938
|
+
function scrollOffsetFromDragRow(totalRows, viewportRows, trackRow, grabRowOffset) {
|
|
43939
|
+
if (viewportRows <= 0 || totalRows <= 0)
|
|
43940
|
+
return 0;
|
|
43941
|
+
const { len } = scrollbarThumb(totalRows, viewportRows, 0);
|
|
43942
|
+
const maxThumbTop = Math.max(0, viewportRows - len);
|
|
43943
|
+
if (maxThumbTop === 0)
|
|
43944
|
+
return 0;
|
|
43945
|
+
const clampedRow = Math.max(0, Math.min(trackRow, viewportRows - 1));
|
|
43946
|
+
const desiredTop = Math.min(maxThumbTop, Math.max(0, clampedRow - grabRowOffset));
|
|
43947
|
+
const maxOffset = Math.max(0, totalRows - viewportRows);
|
|
43948
|
+
return Math.round(desiredTop * maxOffset / maxThumbTop);
|
|
43949
|
+
}
|
|
43950
|
+
function scrollbarCell(totalRows, viewportRows, offset, rowIndex, accent) {
|
|
43951
|
+
const thumb = scrollbarThumb(totalRows, viewportRows, offset);
|
|
43952
|
+
const isThumb = rowIndex >= thumb.top && rowIndex < thumb.top + thumb.len;
|
|
43953
|
+
return paint(isThumb ? "\u2590" : "\u2595", { fg: isThumb ? accent : theme.muted, bg: theme.canvas });
|
|
43954
|
+
}
|
|
43955
|
+
function renderPanelSection(label, rows, width, height, scrollOffset, accent) {
|
|
43956
|
+
if (height <= 0 || width <= 0)
|
|
43957
|
+
return { lines: [], rowTargets: [] };
|
|
43958
|
+
const headerHeight = panelHeaderHeight(height);
|
|
43959
|
+
const contentHeight = panelContentHeight(height);
|
|
43960
|
+
const overflow = rows.length > contentHeight;
|
|
43961
|
+
const textWidth = overflow ? Math.max(1, width - 1) : width;
|
|
43962
|
+
const clampedOffset = Math.max(0, Math.min(scrollOffset, Math.max(0, rows.length - contentHeight)));
|
|
43963
|
+
const visible = rows.slice(clampedOffset, clampedOffset + contentHeight);
|
|
43964
|
+
const lines = [];
|
|
43965
|
+
if (headerHeight >= 1)
|
|
43966
|
+
lines.push(paint("\u2500".repeat(width), { fg: theme.border, bg: theme.canvas }));
|
|
43967
|
+
if (headerHeight >= 2) {
|
|
43968
|
+
lines.push(paint(fit(` ${label}`, width), { fg: accent, bg: theme.canvas, bold: true }));
|
|
43969
|
+
}
|
|
43970
|
+
const rowTargets = [];
|
|
43971
|
+
for (let index = 0;index < contentHeight; index += 1) {
|
|
43972
|
+
const item = visible[index];
|
|
43973
|
+
const text3 = paint(fit(item?.text ?? "", textWidth), {
|
|
43974
|
+
fg: item?.fg ?? theme.text,
|
|
43975
|
+
bg: item?.bg ?? theme.canvas,
|
|
43976
|
+
bold: item?.bold,
|
|
43977
|
+
dim: item?.dim
|
|
43978
|
+
});
|
|
43979
|
+
const scrollCell = overflow ? scrollbarCell(rows.length, contentHeight, clampedOffset, index, accent) : "";
|
|
43980
|
+
lines.push(`${text3}${scrollCell}`);
|
|
43981
|
+
if (item?.pickerTarget)
|
|
43982
|
+
rowTargets.push({ y: headerHeight + index, pickerTarget: item.pickerTarget });
|
|
43983
|
+
}
|
|
43984
|
+
return {
|
|
43985
|
+
lines,
|
|
43986
|
+
rowTargets,
|
|
43987
|
+
track: overflow ? { x: width - 1, viewportRows: contentHeight, rowCount: rows.length } : undefined
|
|
43988
|
+
};
|
|
43989
|
+
}
|
|
43990
|
+
function sidePanelSectionHeights(layout, bodyHeight) {
|
|
43991
|
+
if (layout.showTopicsPanel && layout.showTaskPanel) {
|
|
43992
|
+
const topicsHeight = Math.max(3, Math.floor(bodyHeight / 2));
|
|
43993
|
+
return { topicsHeight, taskHeight: Math.max(0, bodyHeight - topicsHeight) };
|
|
43994
|
+
}
|
|
43995
|
+
if (layout.showTopicsPanel)
|
|
43996
|
+
return { topicsHeight: bodyHeight, taskHeight: 0 };
|
|
43997
|
+
if (layout.showTaskPanel)
|
|
43998
|
+
return { topicsHeight: 0, taskHeight: bodyHeight };
|
|
43999
|
+
return { topicsHeight: 0, taskHeight: 0 };
|
|
44000
|
+
}
|
|
44001
|
+
function renderSideColumn(state, layout, bodyHeight, animationFrame) {
|
|
44002
|
+
const { showTaskPanel, showTopicsPanel, sideWidth } = layout;
|
|
44003
|
+
if (!showTaskPanel && !showTopicsPanel)
|
|
44004
|
+
return { lines: [], targets: [], tracks: [] };
|
|
44005
|
+
const { topicsHeight, taskHeight } = sidePanelSectionHeights(layout, bodyHeight);
|
|
44006
|
+
const sections = [];
|
|
44007
|
+
if (showTopicsPanel) {
|
|
44008
|
+
sections.push({
|
|
44009
|
+
panel: "topics",
|
|
44010
|
+
label: state.topicsPanelSort === "activity" ? "ACTIVITY \xB7 name" : "activity \xB7 NAME",
|
|
44011
|
+
rows: topicsPanelRows(state, animationFrame),
|
|
44012
|
+
accent: theme.accent,
|
|
44013
|
+
height: topicsHeight,
|
|
44014
|
+
offset: 0,
|
|
44015
|
+
scrollOffset: state.topicsPanelScrollOffset
|
|
44016
|
+
});
|
|
44017
|
+
}
|
|
44018
|
+
if (showTaskPanel) {
|
|
44019
|
+
sections.push({
|
|
44020
|
+
panel: "tasks",
|
|
44021
|
+
label: "tasks",
|
|
44022
|
+
rows: taskPanelRows(state, sideWidth),
|
|
44023
|
+
accent: theme.taskBorder,
|
|
44024
|
+
height: taskHeight,
|
|
44025
|
+
offset: showTopicsPanel ? topicsHeight : 0,
|
|
44026
|
+
scrollOffset: state.taskPanelScrollOffset
|
|
44027
|
+
});
|
|
44028
|
+
}
|
|
44029
|
+
const lines = [];
|
|
44030
|
+
const targets = [];
|
|
44031
|
+
const tracks = [];
|
|
44032
|
+
for (const section of sections) {
|
|
44033
|
+
const result = renderPanelSection(section.label, section.rows, sideWidth, section.height, section.scrollOffset, section.accent);
|
|
44034
|
+
lines.push(...result.lines);
|
|
44035
|
+
for (const target of result.rowTargets) {
|
|
44036
|
+
targets.push({ y: section.offset + target.y, pickerTarget: target.pickerTarget });
|
|
44037
|
+
}
|
|
44038
|
+
if (result.track) {
|
|
44039
|
+
tracks.push({
|
|
44040
|
+
panel: section.panel,
|
|
44041
|
+
x: result.track.x,
|
|
44042
|
+
yStart: section.offset + panelHeaderHeight(section.height),
|
|
44043
|
+
viewportRows: result.track.viewportRows,
|
|
44044
|
+
rowCount: result.track.rowCount
|
|
44045
|
+
});
|
|
43759
44046
|
}
|
|
43760
|
-
rows.push(...group);
|
|
43761
|
-
shown += 1;
|
|
43762
44047
|
}
|
|
43763
|
-
|
|
43764
|
-
|
|
44048
|
+
while (lines.length < bodyHeight)
|
|
44049
|
+
lines.push(paint(" ".repeat(sideWidth), { bg: theme.canvas }));
|
|
44050
|
+
return { lines: lines.slice(0, bodyHeight), targets, tracks };
|
|
44051
|
+
}
|
|
44052
|
+
function maxTopicsPanelScrollOffset(state, columns, rows) {
|
|
44053
|
+
const width = Math.max(1, columns);
|
|
44054
|
+
const height = Math.max(14, rows);
|
|
44055
|
+
if (state.overlay)
|
|
44056
|
+
return 0;
|
|
44057
|
+
const layout = terminalBodyLayout(state, width);
|
|
44058
|
+
if (!layout.showTopicsPanel)
|
|
44059
|
+
return 0;
|
|
44060
|
+
const bodyHeight = Math.max(3, height - footerLines(state, width).length - decisionPane(state, width).length - vaultRequestPane(state, width).length - composerPane(state, layout.conversationWidth).lines.length);
|
|
44061
|
+
const { topicsHeight } = sidePanelSectionHeights(layout, bodyHeight);
|
|
44062
|
+
const viewport = panelContentHeight(topicsHeight);
|
|
44063
|
+
return Math.max(0, topicsPanelRows(state, 0).length - viewport);
|
|
44064
|
+
}
|
|
44065
|
+
function maxTaskPanelScrollOffset(state, columns, rows) {
|
|
44066
|
+
const width = Math.max(1, columns);
|
|
44067
|
+
const height = Math.max(14, rows);
|
|
44068
|
+
if (state.overlay)
|
|
44069
|
+
return 0;
|
|
44070
|
+
const layout = terminalBodyLayout(state, width);
|
|
44071
|
+
if (!layout.showTaskPanel)
|
|
44072
|
+
return 0;
|
|
44073
|
+
const bodyHeight = Math.max(3, height - footerLines(state, width).length - decisionPane(state, width).length - vaultRequestPane(state, width).length - composerPane(state, layout.conversationWidth).lines.length);
|
|
44074
|
+
const { taskHeight } = sidePanelSectionHeights(layout, bodyHeight);
|
|
44075
|
+
const viewport = panelContentHeight(taskHeight);
|
|
44076
|
+
return Math.max(0, taskPanelRows(state, layout.sideWidth).length - viewport);
|
|
43765
44077
|
}
|
|
43766
44078
|
function helpLines() {
|
|
43767
44079
|
return [
|
|
@@ -43771,7 +44083,9 @@ function helpLines() {
|
|
|
43771
44083
|
line(" \u2190 \u2192 move \xB7 Ctrl/Alt-\u2190 \u2192 move by word \xB7 \u2191 \u2193 history"),
|
|
43772
44084
|
line(" Alt-Backspace delete word \xB7 Ctrl-U clear before cursor"),
|
|
43773
44085
|
line(" Cmd-Backspace works when forwarded \xB7 Ctrl-W/K aliases"),
|
|
43774
|
-
line(" Mouse wheel / PgUp/PgDn scroll \xB7 Ctrl-E load older
|
|
44086
|
+
line(" Mouse wheel / PgUp/PgDn scroll \xB7 Ctrl-E load older"),
|
|
44087
|
+
line(" Ctrl-P topics + tasks panel \xB7 click/hover a row to switch \xB7 drag scrollbar"),
|
|
44088
|
+
line(" Ctrl-R sort topics panel (activity / name)"),
|
|
43775
44089
|
line(" Ctrl-O topics \xB7 Ctrl-G subagents \xB7 Ctrl-D decisions \xB7 Ctrl-X abort"),
|
|
43776
44090
|
line(" In topics: type to filter \xB7 Ctrl-N new \xB7 Ctrl-D delete"),
|
|
43777
44091
|
line(" Esc/Ctrl-C stop active turn \xB7 Ctrl-C twice when idle to quit"),
|
|
@@ -43923,8 +44237,8 @@ function topicOverlayCursor(state, width, bodyHeight) {
|
|
|
43923
44237
|
function topicOverlayLines(state, width, height, animationFrame = 0) {
|
|
43924
44238
|
const visibleIds = visibleTopicPickerIds(state);
|
|
43925
44239
|
const indexedTopics = state.topics.map((topic, topicIndex) => ({ topic, topicIndex })).filter(({ topic }) => visibleIds.has(topic.id));
|
|
43926
|
-
const managerTopics = indexedTopics.filter(({ topic }) => topic.kind === "manager");
|
|
43927
|
-
const regularTopics = indexedTopics.filter(({ topic }) => topic.kind !== "manager");
|
|
44240
|
+
const managerTopics = sortedTopicEntries(state, indexedTopics.filter(({ topic }) => topic.kind === "manager"));
|
|
44241
|
+
const regularTopics = sortedTopicEntries(state, indexedTopics.filter(({ topic }) => topic.kind !== "manager"));
|
|
43928
44242
|
const entries = [];
|
|
43929
44243
|
for (const [label, topics] of [
|
|
43930
44244
|
["Manager", managerTopics],
|
|
@@ -43972,30 +44286,48 @@ function topicOverlayLines(state, width, height, animationFrame = 0) {
|
|
|
43972
44286
|
query2.length > 0 ? line(`${TOPIC_FILTER_LABEL}${safeText(query2)}`, { fg: theme.cyan, bold: true }) : line(""),
|
|
43973
44287
|
...entries.length === 0 ? [
|
|
43974
44288
|
line(query2.length > 0 ? ` No topics match \u201C${safeText(query2)}\u201D \xB7 Esc clears the filter` : " No topics yet \xB7 Press Ctrl-N to create one", { fg: theme.muted })
|
|
43975
|
-
] : entries.slice(start, start + visibleCount).
|
|
44289
|
+
] : entries.slice(start, start + visibleCount).flatMap((entry) => {
|
|
43976
44290
|
if (entry.kind === "heading") {
|
|
43977
|
-
return line(` ${entry.label}`, { fg: theme.cyan, bold: true });
|
|
44291
|
+
return [line(` ${entry.label}`, { fg: theme.cyan, bold: true })];
|
|
43978
44292
|
}
|
|
43979
44293
|
if (entry.kind === "separator") {
|
|
43980
|
-
return line(` ${"\u2500".repeat(Math.max(1, width - 4))}`, { fg: theme.border });
|
|
44294
|
+
return [line(` ${"\u2500".repeat(Math.max(1, width - 4))}`, { fg: theme.border })];
|
|
43981
44295
|
}
|
|
43982
44296
|
if (entry.kind === "background") {
|
|
43983
44297
|
const selected2 = entry.sessionId === state.topicPickerBackgroundId;
|
|
43984
|
-
return
|
|
43985
|
-
|
|
43986
|
-
|
|
43987
|
-
|
|
43988
|
-
|
|
44298
|
+
return [
|
|
44299
|
+
line(` ${selected2 ? "\u203A" : " "} ${entry.active ? workingFrame(animationFrame) : "\u25CB"} ${entry.label} \xB7 ${entry.status}`, {
|
|
44300
|
+
fg: selected2 ? theme.text : entry.active ? theme.green : theme.muted,
|
|
44301
|
+
bg: selected2 ? theme.selected : theme.canvas,
|
|
44302
|
+
bold: selected2,
|
|
44303
|
+
pickerTarget: { backgroundSessionId: entry.sessionId }
|
|
44304
|
+
})
|
|
44305
|
+
];
|
|
43989
44306
|
}
|
|
43990
44307
|
const { topic, topicIndex } = entry;
|
|
43991
44308
|
const selected = topicIndex === state.topicPickerIndex;
|
|
43992
|
-
const
|
|
44309
|
+
const status = topicStatusIndicator(state, topic, animationFrame);
|
|
43993
44310
|
const childPrefix = subagentTreePrefix(topic, state.topics);
|
|
43994
|
-
|
|
43995
|
-
|
|
43996
|
-
|
|
43997
|
-
|
|
44311
|
+
const bg2 = selected ? theme.selected : theme.canvas;
|
|
44312
|
+
const header = line(` ${selected ? "\u203A" : " "} ${childPrefix}${status.icon} ${topic.title} \xB7 ${topic.agent ?? "no agent"} \xB7 ${effectiveTopicModel(topic)} \xB7 ${effectiveTopicEffort(topic)}`, {
|
|
44313
|
+
fg: selected ? theme.text : status.fg,
|
|
44314
|
+
bg: bg2,
|
|
44315
|
+
bold: selected,
|
|
44316
|
+
pickerTarget: { topicIndex }
|
|
43998
44317
|
});
|
|
44318
|
+
const running = state.activity[topic.id]?.running;
|
|
44319
|
+
const subtitle = status.blockedText ?? (running ? activityDetail(state.activity[topic.id]?.status) : undefined);
|
|
44320
|
+
if (!subtitle)
|
|
44321
|
+
return [header];
|
|
44322
|
+
return [
|
|
44323
|
+
header,
|
|
44324
|
+
line(` ${subtitle}`, {
|
|
44325
|
+
fg: status.blockedText !== undefined ? theme.amber : theme.muted,
|
|
44326
|
+
dim: status.blockedText === undefined,
|
|
44327
|
+
bg: bg2,
|
|
44328
|
+
pickerTarget: { topicIndex }
|
|
44329
|
+
})
|
|
44330
|
+
];
|
|
43999
44331
|
})
|
|
44000
44332
|
];
|
|
44001
44333
|
}
|
|
@@ -44341,6 +44673,16 @@ function conversationViewport(lineCount, height, requestedOffset) {
|
|
|
44341
44673
|
offset: Math.min(maxOffset, Math.max(0, requestedOffset))
|
|
44342
44674
|
};
|
|
44343
44675
|
}
|
|
44676
|
+
function popupPaneWidth(width) {
|
|
44677
|
+
return Math.max(0, Math.min(POPUP_PANE_MAX_WIDTH, width - 4));
|
|
44678
|
+
}
|
|
44679
|
+
function centerPaneRows(rows, boxWidth, totalWidth) {
|
|
44680
|
+
const left = Math.max(0, Math.floor((totalWidth - boxWidth) / 2));
|
|
44681
|
+
const right = Math.max(0, totalWidth - boxWidth - left);
|
|
44682
|
+
const leftPad = left > 0 ? paint(" ".repeat(left), { bg: theme.canvas }) : "";
|
|
44683
|
+
const rightPad = right > 0 ? paint(" ".repeat(right), { bg: theme.canvas }) : "";
|
|
44684
|
+
return rows.map((row) => `${leftPad}${row}${rightPad}`);
|
|
44685
|
+
}
|
|
44344
44686
|
function decisionPane(state, width) {
|
|
44345
44687
|
if (state.overlay)
|
|
44346
44688
|
return [];
|
|
@@ -44351,6 +44693,7 @@ function decisionPane(state, width) {
|
|
|
44351
44693
|
if (!ask || !question?.choices.length)
|
|
44352
44694
|
return [];
|
|
44353
44695
|
const selected = Math.min(state.askChoiceIndex, question.choices.length - 1);
|
|
44696
|
+
const boxWidth = popupPaneWidth(width);
|
|
44354
44697
|
const content = [
|
|
44355
44698
|
line(` ${question.question}`, { bold: true }),
|
|
44356
44699
|
...question.choices.map((choice, index) => line(` ${index === selected ? "\u25CF" : "\u25CB"} ${choice.label}${choice.description ? ` \u2014 ${choice.description}` : ""}`, {
|
|
@@ -44359,7 +44702,8 @@ function decisionPane(state, width) {
|
|
|
44359
44702
|
bold: index === selected
|
|
44360
44703
|
}))
|
|
44361
44704
|
];
|
|
44362
|
-
|
|
44705
|
+
const rows = framePane("decision required \xB7 \u2191\u2193 select \xB7 Enter confirm", content, boxWidth, Math.min(8, Math.max(4, content.length + 2)), { active: true, accent: theme.amber });
|
|
44706
|
+
return centerPaneRows(rows, boxWidth, width);
|
|
44363
44707
|
}
|
|
44364
44708
|
function vaultRequestPane(state, width) {
|
|
44365
44709
|
if (state.overlay)
|
|
@@ -44368,15 +44712,17 @@ function vaultRequestPane(state, width) {
|
|
|
44368
44712
|
if (!request)
|
|
44369
44713
|
return [];
|
|
44370
44714
|
const declining = state.vaultRequestMode === "confirm-decline";
|
|
44715
|
+
const boxWidth = popupPaneWidth(width);
|
|
44371
44716
|
const content = [
|
|
44372
44717
|
line(` ${request.key}`, { bold: true }),
|
|
44373
|
-
...request.description ? wrapText(request.description, Math.max(4,
|
|
44718
|
+
...request.description ? wrapText(request.description, Math.max(4, boxWidth - 6)).map((text3) => line(` ${text3}`, { fg: theme.muted })) : [],
|
|
44374
44719
|
declining ? line(" Decline this request? y / n", { fg: theme.red, bold: true }) : line(" Enter save to Vault \xB7 Esc clear / decline \xB7 Alt-Enter newline", {
|
|
44375
44720
|
fg: theme.subtle
|
|
44376
44721
|
}),
|
|
44377
44722
|
...state.vaultRequestNotice ? [line(` ! ${state.vaultRequestNotice}`, { fg: theme.amber })] : []
|
|
44378
44723
|
];
|
|
44379
|
-
|
|
44724
|
+
const rows = framePane(`secret requested by ${state.aiName} \xB7 never shown to the agent${state.vaultRequestSubmitting ? ` \xB7 ${workingFrame(0)} saving` : ""}`, content, boxWidth, Math.min(8, Math.max(4, content.length + 2)), { active: true, accent: theme.accent });
|
|
44725
|
+
return centerPaneRows(rows, boxWidth, width);
|
|
44380
44726
|
}
|
|
44381
44727
|
function wrapLineWithCursor(value, codePointColumn, width) {
|
|
44382
44728
|
const chars = Array.from(safeText(value));
|
|
@@ -44450,6 +44796,20 @@ function inputVisualLines(state, width) {
|
|
|
44450
44796
|
}
|
|
44451
44797
|
return { lines: result, cursorLine, cursorColumn };
|
|
44452
44798
|
}
|
|
44799
|
+
function shiftLines(lines, marginWidth) {
|
|
44800
|
+
if (marginWidth <= 0)
|
|
44801
|
+
return lines;
|
|
44802
|
+
const margin = paint(" ".repeat(marginWidth), { bg: theme.canvas });
|
|
44803
|
+
return lines.map((row) => `${margin}${row}`);
|
|
44804
|
+
}
|
|
44805
|
+
function shiftComposerPane(pane, marginWidth) {
|
|
44806
|
+
if (marginWidth <= 0)
|
|
44807
|
+
return pane;
|
|
44808
|
+
return {
|
|
44809
|
+
lines: shiftLines(pane.lines, marginWidth),
|
|
44810
|
+
cursor: { x: pane.cursor.x + marginWidth, y: pane.cursor.y }
|
|
44811
|
+
};
|
|
44812
|
+
}
|
|
44453
44813
|
function composerPane(state, width) {
|
|
44454
44814
|
const title = state.creatingTopic ? "new topic \xB7 type a name \xB7 Enter create" : state.overlay === "vault" ? state.vaultMode === "list" ? "Vault command \xB7 Enter run \xB7 Esc close" : `${state.vaultMode === "key" ? "key" : state.vaultMode === "value" ? "secret value" : "description"} \xB7 Enter continue \xB7 Esc cancel` : "Ctrl-O topics \xB7 Ctrl-G subagents \xB7 Ctrl-D decisions";
|
|
44455
44815
|
const visual = inputVisualLines(state, width);
|
|
@@ -44693,30 +45053,62 @@ function renderApp(state, columns, rows, animationFrame = 0, nowMs = terminalNow
|
|
|
44693
45053
|
function renderAppFrame(state, columns, rows, animationFrame = 0, nowMs = terminalNowMs()) {
|
|
44694
45054
|
const width = Math.max(1, columns);
|
|
44695
45055
|
const height = Math.max(14, rows);
|
|
44696
|
-
const
|
|
44697
|
-
const
|
|
45056
|
+
const layout = terminalBodyLayout(state, width);
|
|
45057
|
+
const conversationXStart = layout.sideWidth > 0 ? layout.sideWidth + SIDE_PANEL_GAP + 1 : 1;
|
|
45058
|
+
const footer = shiftLines(footerLines(state, layout.conversationWidth), conversationXStart - 1);
|
|
45059
|
+
const decision = shiftLines([
|
|
45060
|
+
...decisionPane(state, layout.conversationWidth),
|
|
45061
|
+
...vaultRequestPane(state, layout.conversationWidth)
|
|
45062
|
+
], conversationXStart - 1);
|
|
44698
45063
|
const hideComposer = state.overlay === "background-session" || state.overlay === "topics" || state.overlay === "subagents" || state.overlay === "decisions" || state.overlay === "vault" && state.vaultMode === "confirm-delete";
|
|
44699
|
-
const composer = hideComposer ? { lines: [], cursor: null } : composerPane(state,
|
|
45064
|
+
const composer = hideComposer ? { lines: [], cursor: null } : shiftComposerPane(composerPane(state, layout.conversationWidth), conversationXStart - 1);
|
|
44700
45065
|
const bodyHeight = Math.max(3, height - footer.length - decision.length - composer.lines.length);
|
|
44701
|
-
const
|
|
44702
|
-
const conversation = conversationLines(state, layout.conversationWidth, bodyHeight, animationFrame, nowMs, !layout.showTaskSidebar);
|
|
45066
|
+
const conversation = conversationLines(state, layout.conversationWidth, bodyHeight, animationFrame, nowMs, !layout.showTaskPanel);
|
|
44703
45067
|
const conversationBody = renderBody(conversation, layout.conversationWidth, bodyHeight);
|
|
44704
|
-
const
|
|
44705
|
-
|
|
44706
|
-
|
|
44707
|
-
|
|
44708
|
-
const gap = paint(" ".repeat(TASK_SIDEBAR_GAP), { bg: theme.canvas });
|
|
44709
|
-
return conversationBody.map((row, index) => `${row}${gap}${taskPane[index] ?? ""}`);
|
|
45068
|
+
const sideColumn = layout.showTaskPanel || layout.showTopicsPanel ? renderSideColumn(state, layout, bodyHeight, animationFrame) : null;
|
|
45069
|
+
const body = sideColumn?.lines.length ? (() => {
|
|
45070
|
+
const gap = paint(" ".repeat(SIDE_PANEL_GAP), { bg: theme.canvas });
|
|
45071
|
+
return sideColumn.lines.map((row, index) => `${row}${gap}${conversationBody[index] ?? ""}`);
|
|
44710
45072
|
})() : conversationBody;
|
|
44711
45073
|
const codeCopyTargets = conversation.flatMap((item, index) => {
|
|
44712
45074
|
if (item.codeCopy === undefined || index >= bodyHeight)
|
|
44713
45075
|
return [];
|
|
44714
45076
|
const trimmed = item.text.trimEnd();
|
|
44715
45077
|
const leading = trimmed.length - trimmed.trimStart().length;
|
|
44716
|
-
const xStart = displayWidth(trimmed.slice(0, leading))
|
|
44717
|
-
const xEnd = Math.min(displayWidth(trimmed),
|
|
45078
|
+
const xStart = conversationXStart + displayWidth(trimmed.slice(0, leading));
|
|
45079
|
+
const xEnd = Math.min(conversationXStart - 1 + displayWidth(trimmed), width);
|
|
44718
45080
|
return xEnd >= xStart ? [{ xStart, xEnd, y: index + 1, text: item.codeCopy }] : [];
|
|
44719
45081
|
});
|
|
45082
|
+
const overlayTargets = conversation.flatMap((item, index) => {
|
|
45083
|
+
if (!item.pickerTarget || index >= bodyHeight)
|
|
45084
|
+
return [];
|
|
45085
|
+
return [{ xStart: 1, xEnd: layout.conversationWidth, y: index + 1, ...item.pickerTarget }];
|
|
45086
|
+
});
|
|
45087
|
+
const sidePanelTargets = (sideColumn?.targets ?? []).map((target) => ({
|
|
45088
|
+
xStart: 1,
|
|
45089
|
+
xEnd: layout.sideWidth,
|
|
45090
|
+
y: target.y + 1,
|
|
45091
|
+
...target.pickerTarget
|
|
45092
|
+
}));
|
|
45093
|
+
const topicPickerTargets = [...overlayTargets, ...sidePanelTargets];
|
|
45094
|
+
const sidePanelTracks = (sideColumn?.tracks ?? []).map((track) => ({
|
|
45095
|
+
...track,
|
|
45096
|
+
x: 1 + track.x,
|
|
45097
|
+
yStart: track.yStart + 1
|
|
45098
|
+
}));
|
|
45099
|
+
const sideColumnBounds = sideColumn ? (() => {
|
|
45100
|
+
const { topicsHeight, taskHeight } = sidePanelSectionHeights(layout, bodyHeight);
|
|
45101
|
+
const sections = [];
|
|
45102
|
+
let offset = 0;
|
|
45103
|
+
if (layout.showTopicsPanel) {
|
|
45104
|
+
sections.push({ panel: "topics", yStart: offset + 1, yEnd: offset + topicsHeight });
|
|
45105
|
+
offset += topicsHeight;
|
|
45106
|
+
}
|
|
45107
|
+
if (layout.showTaskPanel) {
|
|
45108
|
+
sections.push({ panel: "tasks", yStart: offset + 1, yEnd: offset + taskHeight });
|
|
45109
|
+
}
|
|
45110
|
+
return { xStart: 1, xEnd: layout.sideWidth, sections };
|
|
45111
|
+
})() : null;
|
|
44720
45112
|
const cursorY = composer.cursor ? body.length + decision.length + composer.cursor.y : Number.POSITIVE_INFINITY;
|
|
44721
45113
|
const overlayCursor = topicOverlayCursor(state, layout.conversationWidth, body.length);
|
|
44722
45114
|
const cursor = composer.cursor && cursorY <= height ? { x: Math.min(composer.cursor.x, width), y: cursorY } : overlayCursor && overlayCursor.y <= height ? overlayCursor : null;
|
|
@@ -44724,7 +45116,10 @@ function renderAppFrame(state, columns, rows, animationFrame = 0, nowMs = termin
|
|
|
44724
45116
|
frame: linkifyUrls([...body, ...decision, ...composer.lines, ...footer].slice(0, height).join(`
|
|
44725
45117
|
`)),
|
|
44726
45118
|
cursor,
|
|
44727
|
-
codeCopyTargets
|
|
45119
|
+
codeCopyTargets,
|
|
45120
|
+
topicPickerTargets,
|
|
45121
|
+
sidePanelTracks,
|
|
45122
|
+
sideColumnBounds
|
|
44728
45123
|
};
|
|
44729
45124
|
}
|
|
44730
45125
|
function maxConversationScrollOffset(state, columns, rows) {
|
|
@@ -44736,9 +45131,9 @@ function maxConversationScrollOffset(state, columns, rows) {
|
|
|
44736
45131
|
}
|
|
44737
45132
|
if (state.overlay)
|
|
44738
45133
|
return 0;
|
|
44739
|
-
const bodyHeight = Math.max(3, height - footerLines(state, width).length - decisionPane(state, width).length - vaultRequestPane(state, width).length - composerPane(state, width).lines.length);
|
|
44740
45134
|
const layout = terminalBodyLayout(state, width);
|
|
44741
|
-
const
|
|
45135
|
+
const bodyHeight = Math.max(3, height - footerLines(state, width).length - decisionPane(state, width).length - vaultRequestPane(state, width).length - composerPane(state, layout.conversationWidth).lines.length);
|
|
45136
|
+
const lineCount = conversationContentLines(state, layout.conversationWidth, 0, terminalNowMs(), !layout.showTaskPanel).length;
|
|
44742
45137
|
return conversationViewport(lineCount, bodyHeight, state.scrollOffset).maxOffset;
|
|
44743
45138
|
}
|
|
44744
45139
|
function preserveConversationScrollAnchor(previous, next, columns, rows) {
|
|
@@ -44776,7 +45171,7 @@ var theme, WORKING_FRAMES, CODE_COPY_MARKER = "\u29C9", WORKING_FRAME_INTERVAL_M
|
|
|
44776
45171
|
default:
|
|
44777
45172
|
return `${ESC}48;2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
|
44778
45173
|
}
|
|
44779
|
-
}, BARE_URL_PATTERN, URL_TRAILING_PUNCTUATION, RENDERED_TAB_WIDTH = 4, CIRCLED_DIGIT_START = 9312, CIRCLED_DIGIT_END = 9331, CIRCLED_ZERO = 9450, isWrapSpace = (character) => character === " " || character === "\t", isWideBreak = (character) => runeWidth(character) === 2, NO_ROW_START, NO_ROW_END, WRAP_MIN_WIDTH = 2, FRAME_MIN_INNER_WIDTH = 4, FRAME_TITLE_MIN_INNER_WIDTH = 8, TABLE_MAX_WIDTH_FRACTION = 0.92, TABLE_MIN_COL_WIDTH = 4,
|
|
45174
|
+
}, BARE_URL_PATTERN, URL_TRAILING_PUNCTUATION, RENDERED_TAB_WIDTH = 4, CIRCLED_DIGIT_START = 9312, CIRCLED_DIGIT_END = 9331, CIRCLED_ZERO = 9450, isWrapSpace = (character) => character === " " || character === "\t", isWideBreak = (character) => runeWidth(character) === 2, NO_ROW_START, NO_ROW_END, WRAP_MIN_WIDTH = 2, FRAME_MIN_INNER_WIDTH = 4, FRAME_TITLE_MIN_INNER_WIDTH = 8, TABLE_MAX_WIDTH_FRACTION = 0.92, TABLE_MIN_COL_WIDTH = 4, TOOL_PREVIEW_MAX_LINES = 12, messageLayoutCache, INLINE_TASK_LIMIT = 5, SIDE_PANEL_MIN_WIDTH = 110, SIDE_PANEL_WIDTH = 36, SIDE_PANEL_GAP = 1, TOPIC_FILTER_ROW_INDEX = 2, TOPIC_FILTER_LABEL = " Filter: ", POPUP_PANE_MAX_WIDTH = 72, COMPOSER_GUTTER = 4, COMPOSER_RIGHT_MARGIN = 1, COMPOSER_MIN_CONTENT_WIDTH = 4, NOTICE_STYLE;
|
|
44780
45175
|
var init_render = __esm(async () => {
|
|
44781
45176
|
init_color_depth();
|
|
44782
45177
|
init_commands();
|
|
@@ -45034,6 +45429,7 @@ function consumeMouseInput(raw) {
|
|
|
45034
45429
|
let scrollDelta = 0;
|
|
45035
45430
|
let horizontalScrollDelta = 0;
|
|
45036
45431
|
const events = [];
|
|
45432
|
+
const wheelEvents = [];
|
|
45037
45433
|
const input = raw.replace(SGR_MOUSE_PATTERN, (_sequence, rawButton, rawX, rawY, suffix) => {
|
|
45038
45434
|
const button = Number.parseInt(rawButton, 10);
|
|
45039
45435
|
if (Number.isFinite(button) && (button & 64) !== 0) {
|
|
@@ -45043,6 +45439,10 @@ function consumeMouseInput(raw) {
|
|
|
45043
45439
|
horizontalScrollDelta += delta;
|
|
45044
45440
|
else
|
|
45045
45441
|
scrollDelta += delta;
|
|
45442
|
+
const x = Number.parseInt(rawX, 10);
|
|
45443
|
+
const y = Number.parseInt(rawY, 10);
|
|
45444
|
+
if (Number.isFinite(x) && Number.isFinite(y))
|
|
45445
|
+
wheelEvents.push({ x, y, delta, horizontal });
|
|
45046
45446
|
} else {
|
|
45047
45447
|
const x = Number.parseInt(rawX, 10);
|
|
45048
45448
|
const y = Number.parseInt(rawY, 10);
|
|
@@ -45057,11 +45457,14 @@ function consumeMouseInput(raw) {
|
|
|
45057
45457
|
}
|
|
45058
45458
|
return "";
|
|
45059
45459
|
});
|
|
45060
|
-
return { input, scrollDelta, horizontalScrollDelta, events };
|
|
45460
|
+
return { input, scrollDelta, horizontalScrollDelta, events, wheelEvents };
|
|
45061
45461
|
}
|
|
45062
45462
|
function codeCopyTargetAt(targets, point) {
|
|
45063
45463
|
return targets.find((target) => target.y === point.y && point.x >= target.xStart && point.x <= target.xEnd);
|
|
45064
45464
|
}
|
|
45465
|
+
function topicPickerTargetAt(targets, point) {
|
|
45466
|
+
return targets.find((target) => target.y === point.y && point.x >= target.xStart && point.x <= target.xEnd);
|
|
45467
|
+
}
|
|
45065
45468
|
function escapeStopsActiveTurn(state) {
|
|
45066
45469
|
if (state.overlay || state.creatingTopic)
|
|
45067
45470
|
return false;
|
|
@@ -46791,9 +47194,9 @@ function altScreenSequences(env = process.env, savedDepth) {
|
|
|
46791
47194
|
const setBackground = colored ? "\x1B]11;#0a0b0f\x07" : "";
|
|
46792
47195
|
const fillCanvas = canvasFill(depth2);
|
|
46793
47196
|
const resetBackground = colored ? "\x1B]111\x07" : "";
|
|
46794
|
-
const modeResets = "\x1B[0m\x1B[?7h\x1B[?1l\x1B[?1006l\x1B[?
|
|
47197
|
+
const modeResets = "\x1B[0m\x1B[?7h\x1B[?1l\x1B[?1006l\x1B[?1003l\x1B[?2004l\x1B[?25h\x1B[?1049l";
|
|
46795
47198
|
return {
|
|
46796
|
-
enter: `${setBackground}\x1B[?1049h${fillCanvas}\x1B[2J\x1B[H\x1B[?25l\x1B[?2004h\x1B[?
|
|
47199
|
+
enter: `${setBackground}\x1B[?1049h${fillCanvas}\x1B[2J\x1B[H\x1B[?25l\x1B[?2004h\x1B[?1003h\x1B[?1006h\x1B[?1l${push}`,
|
|
46797
47200
|
exit: `${END_SYNCHRONIZED_UPDATE}${pop}${modeResets}${resetBackground}`,
|
|
46798
47201
|
abortEnter: `${END_SYNCHRONIZED_UPDATE}${modeResets}`
|
|
46799
47202
|
};
|
|
@@ -46836,6 +47239,10 @@ class TerminalApp {
|
|
|
46836
47239
|
#subagentGraphDragPoint = null;
|
|
46837
47240
|
#plainFrameLines = [];
|
|
46838
47241
|
#codeCopyTargets = [];
|
|
47242
|
+
#topicPickerTargets = [];
|
|
47243
|
+
#sidePanelTracks = [];
|
|
47244
|
+
#sideColumnBounds = null;
|
|
47245
|
+
#sidePanelDrag = null;
|
|
46839
47246
|
#lastInterruptAt = 0;
|
|
46840
47247
|
#subagentGraphGeneration = 0;
|
|
46841
47248
|
#subagentGraphAbortController = null;
|
|
@@ -47211,6 +47618,9 @@ class TerminalApp {
|
|
|
47211
47618
|
const rows = process.stdout.rows ?? 30;
|
|
47212
47619
|
const rendered = renderAppFrame(this.#state, columns, rows, this.#animationFrame);
|
|
47213
47620
|
this.#codeCopyTargets = rendered.codeCopyTargets;
|
|
47621
|
+
this.#topicPickerTargets = rendered.topicPickerTargets;
|
|
47622
|
+
this.#sidePanelTracks = rendered.sidePanelTracks;
|
|
47623
|
+
this.#sideColumnBounds = rendered.sideColumnBounds;
|
|
47214
47624
|
const baseFrame = rendered.frame;
|
|
47215
47625
|
this.#plainFrameLines = stripAnsi(baseFrame).split(`
|
|
47216
47626
|
`);
|
|
@@ -47598,19 +48008,25 @@ class TerminalApp {
|
|
|
47598
48008
|
}
|
|
47599
48009
|
#handleKeySegment(segment) {
|
|
47600
48010
|
const mouse = consumeMouseInput(segment);
|
|
47601
|
-
|
|
48011
|
+
const { scrollDelta, horizontalScrollDelta } = this.#routeWheelEvents(mouse.wheelEvents);
|
|
48012
|
+
if (horizontalScrollDelta !== 0 && (this.#state.overlay === "subagents" || this.#state.overlay === "decisions")) {
|
|
47602
48013
|
this.#selection = null;
|
|
47603
|
-
this.#panActiveGraph(-
|
|
48014
|
+
this.#panActiveGraph(-horizontalScrollDelta, 0);
|
|
47604
48015
|
}
|
|
47605
|
-
if (
|
|
48016
|
+
if (scrollDelta !== 0) {
|
|
47606
48017
|
this.#selection = null;
|
|
47607
|
-
this.#scroll(
|
|
48018
|
+
this.#scroll(scrollDelta);
|
|
47608
48019
|
}
|
|
47609
48020
|
for (const event of mouse.events) {
|
|
47610
48021
|
if (this.#state.overlay === "subagents" || this.#state.overlay === "decisions") {
|
|
47611
48022
|
this.#handleGraphMouse(event);
|
|
47612
|
-
|
|
47613
|
-
|
|
48023
|
+
continue;
|
|
48024
|
+
}
|
|
48025
|
+
if (this.#handleSidePanelScrollbarDrag(event))
|
|
48026
|
+
continue;
|
|
48027
|
+
if (this.#handlePickableRowMouse(event))
|
|
48028
|
+
continue;
|
|
48029
|
+
this.#handleMouseSelection(event);
|
|
47614
48030
|
}
|
|
47615
48031
|
const chunk = normalizeKeySequences(mouse.input);
|
|
47616
48032
|
if (!chunk)
|
|
@@ -47649,10 +48065,17 @@ class TerminalApp {
|
|
|
47649
48065
|
this.#toggleDecisionGraph();
|
|
47650
48066
|
return;
|
|
47651
48067
|
}
|
|
47652
|
-
if (chunk === "\
|
|
48068
|
+
if (chunk === "\x10") {
|
|
47653
48069
|
if (editingVaultSecret)
|
|
47654
48070
|
return;
|
|
47655
|
-
this.#state =
|
|
48071
|
+
this.#state = toggleTopicsPanel(this.#state);
|
|
48072
|
+
this.#queueRender();
|
|
48073
|
+
return;
|
|
48074
|
+
}
|
|
48075
|
+
if (chunk === "\x12") {
|
|
48076
|
+
if (editingVaultSecret)
|
|
48077
|
+
return;
|
|
48078
|
+
this.#state = cycleTopicsPanelSort(this.#state);
|
|
47656
48079
|
this.#queueRender();
|
|
47657
48080
|
return;
|
|
47658
48081
|
}
|
|
@@ -48790,6 +49213,140 @@ class TerminalApp {
|
|
|
48790
49213
|
}
|
|
48791
49214
|
this.#queueRender();
|
|
48792
49215
|
}
|
|
49216
|
+
#routeWheelEvents(events) {
|
|
49217
|
+
let scrollDelta = 0;
|
|
49218
|
+
let horizontalScrollDelta = 0;
|
|
49219
|
+
if (events.length === 0)
|
|
49220
|
+
return { scrollDelta, horizontalScrollDelta };
|
|
49221
|
+
const bounds = this.#sideColumnBounds;
|
|
49222
|
+
let touchedPanel = false;
|
|
49223
|
+
for (const event of events) {
|
|
49224
|
+
const section = bounds && event.x >= bounds.xStart && event.x <= bounds.xEnd ? bounds.sections.find((s) => event.y >= s.yStart && event.y <= s.yEnd) : undefined;
|
|
49225
|
+
if (!section) {
|
|
49226
|
+
if (event.horizontal)
|
|
49227
|
+
horizontalScrollDelta += event.delta;
|
|
49228
|
+
else
|
|
49229
|
+
scrollDelta += event.delta;
|
|
49230
|
+
continue;
|
|
49231
|
+
}
|
|
49232
|
+
touchedPanel = true;
|
|
49233
|
+
const columns = process.stdout.columns ?? 100;
|
|
49234
|
+
const rows = process.stdout.rows ?? 30;
|
|
49235
|
+
this.#state = section.panel === "topics" ? scrollTopicsPanel(this.#state, -event.delta, maxTopicsPanelScrollOffset(this.#state, columns, rows)) : scrollTaskPanel(this.#state, -event.delta, maxTaskPanelScrollOffset(this.#state, columns, rows));
|
|
49236
|
+
}
|
|
49237
|
+
if (touchedPanel)
|
|
49238
|
+
this.#queueRender();
|
|
49239
|
+
return { scrollDelta, horizontalScrollDelta };
|
|
49240
|
+
}
|
|
49241
|
+
#handleSidePanelScrollbarDrag(event) {
|
|
49242
|
+
if (event.kind === "press" && (event.button & 3) === 0) {
|
|
49243
|
+
const track2 = this.#sidePanelTracks.find((t) => event.x === t.x && event.y >= t.yStart && event.y < t.yStart + t.viewportRows);
|
|
49244
|
+
if (!track2)
|
|
49245
|
+
return false;
|
|
49246
|
+
const current3 = track2.panel === "topics" ? this.#state.topicsPanelScrollOffset : this.#state.taskPanelScrollOffset;
|
|
49247
|
+
const thumb = scrollbarThumb(track2.rowCount, track2.viewportRows, current3);
|
|
49248
|
+
this.#sidePanelDrag = {
|
|
49249
|
+
panel: track2.panel,
|
|
49250
|
+
track: track2,
|
|
49251
|
+
grabRowOffset: event.y - (track2.yStart + thumb.top)
|
|
49252
|
+
};
|
|
49253
|
+
return true;
|
|
49254
|
+
}
|
|
49255
|
+
const drag = this.#sidePanelDrag;
|
|
49256
|
+
if (!drag)
|
|
49257
|
+
return false;
|
|
49258
|
+
if (event.kind === "release") {
|
|
49259
|
+
this.#sidePanelDrag = null;
|
|
49260
|
+
return true;
|
|
49261
|
+
}
|
|
49262
|
+
const { track, grabRowOffset, panel } = drag;
|
|
49263
|
+
const offset = scrollOffsetFromDragRow(track.rowCount, track.viewportRows, event.y - track.yStart, grabRowOffset);
|
|
49264
|
+
const columns = process.stdout.columns ?? 100;
|
|
49265
|
+
const rows = process.stdout.rows ?? 30;
|
|
49266
|
+
this.#state = panel === "topics" ? setTopicsPanelScrollOffset(this.#state, offset, maxTopicsPanelScrollOffset(this.#state, columns, rows)) : setTaskPanelScrollOffset(this.#state, offset, maxTaskPanelScrollOffset(this.#state, columns, rows));
|
|
49267
|
+
this.#queueRender();
|
|
49268
|
+
return true;
|
|
49269
|
+
}
|
|
49270
|
+
#handlePickableRowMouse(event) {
|
|
49271
|
+
const inOverlay = this.#state.overlay === "topics";
|
|
49272
|
+
const hovering = event.kind === "drag" && (event.button & 3) === 3;
|
|
49273
|
+
const isClick = event.kind === "press" && (event.button & 3) === 0;
|
|
49274
|
+
if (!inOverlay && !hovering && !isClick)
|
|
49275
|
+
return false;
|
|
49276
|
+
const target = topicPickerTargetAt(this.#topicPickerTargets, { x: event.x, y: event.y });
|
|
49277
|
+
if (inOverlay) {
|
|
49278
|
+
if (!target)
|
|
49279
|
+
return true;
|
|
49280
|
+
const highlighted = this.#highlightPickedTarget(target);
|
|
49281
|
+
if (!hovering && highlighted)
|
|
49282
|
+
this.#selectPickedTopic();
|
|
49283
|
+
return true;
|
|
49284
|
+
}
|
|
49285
|
+
if (target?.backgroundSessionId !== undefined) {
|
|
49286
|
+
const sessionId = target.backgroundSessionId;
|
|
49287
|
+
if (hovering) {
|
|
49288
|
+
this.#setSidePanelHover(undefined, sessionId);
|
|
49289
|
+
return true;
|
|
49290
|
+
}
|
|
49291
|
+
this.#setSidePanelHover(undefined, undefined);
|
|
49292
|
+
this.#state = {
|
|
49293
|
+
...this.#state,
|
|
49294
|
+
overlay: "background-session",
|
|
49295
|
+
topicPickerBackgroundId: sessionId,
|
|
49296
|
+
backgroundScrollOffset: 0,
|
|
49297
|
+
notice: undefined,
|
|
49298
|
+
noticeLevel: undefined
|
|
49299
|
+
};
|
|
49300
|
+
this.#queueRender();
|
|
49301
|
+
return true;
|
|
49302
|
+
}
|
|
49303
|
+
if (target?.topicIndex === undefined) {
|
|
49304
|
+
this.#setSidePanelHover(undefined, undefined);
|
|
49305
|
+
return false;
|
|
49306
|
+
}
|
|
49307
|
+
const topic = this.#state.topics[target.topicIndex];
|
|
49308
|
+
if (!topic)
|
|
49309
|
+
return false;
|
|
49310
|
+
if (hovering) {
|
|
49311
|
+
this.#setSidePanelHover(topic.id, undefined);
|
|
49312
|
+
return true;
|
|
49313
|
+
}
|
|
49314
|
+
this.#setSidePanelHover(undefined, undefined);
|
|
49315
|
+
if (topic.id !== this.#state.activeTopicId)
|
|
49316
|
+
this.#activateTopic(topic.id);
|
|
49317
|
+
return true;
|
|
49318
|
+
}
|
|
49319
|
+
#setSidePanelHover(topicId, backgroundSessionId) {
|
|
49320
|
+
if (this.#state.sidePanelHoverTopicId === topicId && this.#state.sidePanelHoverBackgroundSessionId === backgroundSessionId) {
|
|
49321
|
+
return;
|
|
49322
|
+
}
|
|
49323
|
+
this.#state = {
|
|
49324
|
+
...this.#state,
|
|
49325
|
+
sidePanelHoverTopicId: topicId,
|
|
49326
|
+
sidePanelHoverBackgroundSessionId: backgroundSessionId
|
|
49327
|
+
};
|
|
49328
|
+
this.#queueRender();
|
|
49329
|
+
}
|
|
49330
|
+
#highlightPickedTarget(target) {
|
|
49331
|
+
if (target.backgroundSessionId !== undefined) {
|
|
49332
|
+
if (this.#state.topicPickerBackgroundId === target.backgroundSessionId)
|
|
49333
|
+
return true;
|
|
49334
|
+
this.#state = { ...this.#state, topicPickerBackgroundId: target.backgroundSessionId };
|
|
49335
|
+
} else if (target.topicIndex !== undefined) {
|
|
49336
|
+
if (!this.#state.topicPickerBackgroundId && this.#state.topicPickerIndex === target.topicIndex) {
|
|
49337
|
+
return true;
|
|
49338
|
+
}
|
|
49339
|
+
this.#state = {
|
|
49340
|
+
...this.#state,
|
|
49341
|
+
topicPickerIndex: target.topicIndex,
|
|
49342
|
+
topicPickerBackgroundId: undefined
|
|
49343
|
+
};
|
|
49344
|
+
} else {
|
|
49345
|
+
return false;
|
|
49346
|
+
}
|
|
49347
|
+
this.#queueRender();
|
|
49348
|
+
return true;
|
|
49349
|
+
}
|
|
48793
49350
|
#handleMouseSelection(event) {
|
|
48794
49351
|
if ((event.button & 3) !== 0 && event.kind !== "release")
|
|
48795
49352
|
return;
|
|
@@ -59153,4 +59710,4 @@ switch (command) {
|
|
|
59153
59710
|
}
|
|
59154
59711
|
}
|
|
59155
59712
|
|
|
59156
|
-
//# debugId=
|
|
59713
|
+
//# debugId=A04216FF3BF92ED864756E2164756E21
|