@codex-infinity/pi-infinity 0.52.4 → 0.60.2
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/CHANGELOG.md +387 -0
- package/README.md +97 -66
- package/dist/bun/cli.d.ts +3 -0
- package/dist/bun/cli.d.ts.map +1 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/cli.js.map +1 -0
- package/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/bun/register-bedrock.d.ts.map +1 -0
- package/dist/bun/register-bedrock.js +4 -0
- package/dist/bun/register-bedrock.js.map +1 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +17 -6
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/initial-message.d.ts +18 -0
- package/dist/cli/initial-message.d.ts.map +1 -0
- package/dist/cli/initial-message.js +22 -0
- package/dist/cli/initial-message.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session.d.ts +42 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +346 -72
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +27 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts +6 -7
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +8 -107
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +6 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +3 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +16 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +5 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +4 -3
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +11 -14
- package/dist/core/export-html/tool-renderer.d.ts +5 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +17 -4
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +37 -11
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +8 -4
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +77 -8
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +56 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +4 -11
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +4 -78
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +6 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +83 -37
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +3 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +22 -12
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +11 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +56 -16
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +6 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +122 -39
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +19 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +290 -57
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +43 -8
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +4 -7
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +21 -15
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +59 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +3 -2
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +29 -8
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +4 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +43 -29
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +8 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +77 -69
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -0
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +6 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +116 -36
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +5 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +9 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -23
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +1 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +1 -1
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +15 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +5 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +5 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +5 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +7 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +158 -7
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +21 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +127 -10
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +12 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +215 -71
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +5 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +49 -0
- package/dist/modes/rpc/jsonl.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +9 -11
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +94 -11
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +27 -16
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -0
- package/dist/utils/exif-orientation.js +158 -0
- package/dist/utils/exif-orientation.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +5 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +6 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +66 -21
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/compaction.md +2 -0
- package/docs/custom-provider.md +57 -9
- package/docs/extensions.md +125 -12
- package/docs/keybindings.md +11 -1
- package/docs/models.md +44 -2
- package/docs/packages.md +9 -0
- package/docs/providers.md +10 -1
- package/docs/rpc.md +44 -7
- package/docs/sdk.md +2 -2
- package/docs/settings.md +11 -0
- package/docs/terminal-setup.md +39 -3
- package/docs/tmux.md +61 -0
- package/docs/tree.md +9 -0
- package/examples/extensions/README.md +2 -0
- package/examples/extensions/antigravity-image-gen.ts +8 -5
- package/examples/extensions/built-in-tool-renderer.ts +246 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/dynamic-tools.ts +74 -0
- package/examples/extensions/overlay-qa-tests.ts +468 -1
- package/examples/extensions/preset.ts +2 -3
- package/examples/extensions/provider-payload.ts +14 -0
- package/examples/extensions/sandbox/index.ts +2 -3
- package/examples/extensions/subagent/agents.ts +2 -3
- package/examples/extensions/tool-override.ts +2 -3
- package/examples/extensions/with-deps/index.ts +1 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +10 -7
|
@@ -13,13 +13,17 @@ class TreeList {
|
|
|
13
13
|
toolCallMap = new Map();
|
|
14
14
|
multipleRoots = false;
|
|
15
15
|
activePathIds = new Set();
|
|
16
|
+
visibleParentMap = new Map();
|
|
17
|
+
visibleChildrenMap = new Map();
|
|
16
18
|
lastSelectedId = null;
|
|
19
|
+
foldedNodes = new Set();
|
|
17
20
|
onSelect;
|
|
18
21
|
onCancel;
|
|
19
22
|
onLabelEdit;
|
|
20
|
-
constructor(tree, currentLeafId, maxVisibleLines, initialSelectedId) {
|
|
23
|
+
constructor(tree, currentLeafId, maxVisibleLines, initialSelectedId, initialFilterMode) {
|
|
21
24
|
this.currentLeafId = currentLeafId;
|
|
22
25
|
this.maxVisibleLines = maxVisibleLines;
|
|
26
|
+
this.filterMode = initialFilterMode ?? "default";
|
|
23
27
|
this.multipleRoots = tree.length > 1;
|
|
24
28
|
this.flatNodes = this.flattenTree(tree);
|
|
25
29
|
this.buildActivePath();
|
|
@@ -217,7 +221,8 @@ class TreeList {
|
|
|
217
221
|
const isSettingsEntry = entry.type === "label" ||
|
|
218
222
|
entry.type === "custom" ||
|
|
219
223
|
entry.type === "model_change" ||
|
|
220
|
-
entry.type === "thinking_level_change"
|
|
224
|
+
entry.type === "thinking_level_change" ||
|
|
225
|
+
entry.type === "session_info";
|
|
221
226
|
switch (this.filterMode) {
|
|
222
227
|
case "user-only":
|
|
223
228
|
// Just user messages
|
|
@@ -249,6 +254,17 @@ class TreeList {
|
|
|
249
254
|
}
|
|
250
255
|
return true;
|
|
251
256
|
});
|
|
257
|
+
// Filter out descendants of folded nodes.
|
|
258
|
+
if (this.foldedNodes.size > 0) {
|
|
259
|
+
const skipSet = new Set();
|
|
260
|
+
for (const flatNode of this.flatNodes) {
|
|
261
|
+
const { id, parentId } = flatNode.node.entry;
|
|
262
|
+
if (parentId != null && (this.foldedNodes.has(parentId) || skipSet.has(parentId))) {
|
|
263
|
+
skipSet.add(id);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
this.filteredNodes = this.filteredNodes.filter((flatNode) => !skipSet.has(flatNode.node.entry.id));
|
|
267
|
+
}
|
|
252
268
|
// Recalculate visual structure (indent, connectors, gutters) based on visible tree
|
|
253
269
|
this.recalculateVisualStructure();
|
|
254
270
|
// Try to preserve cursor on the same node, or find nearest visible ancestor
|
|
@@ -373,6 +389,9 @@ class TreeList {
|
|
|
373
389
|
]);
|
|
374
390
|
}
|
|
375
391
|
}
|
|
392
|
+
// Store visible tree maps for ancestor/descendant lookups in navigation
|
|
393
|
+
this.visibleParentMap = visibleParent;
|
|
394
|
+
this.visibleChildrenMap = visibleChildren;
|
|
376
395
|
}
|
|
377
396
|
/** Get searchable text content from a node */
|
|
378
397
|
getSearchableText(node) {
|
|
@@ -411,6 +430,11 @@ class TreeList {
|
|
|
411
430
|
case "branch_summary":
|
|
412
431
|
parts.push("branch summary", entry.summary);
|
|
413
432
|
break;
|
|
433
|
+
case "session_info":
|
|
434
|
+
parts.push("title");
|
|
435
|
+
if (entry.name)
|
|
436
|
+
parts.push(entry.name);
|
|
437
|
+
break;
|
|
414
438
|
case "model_change":
|
|
415
439
|
parts.push("model", entry.modelId);
|
|
416
440
|
break;
|
|
@@ -479,6 +503,7 @@ class TreeList {
|
|
|
479
503
|
// Build prefix char by char, placing gutters and connector at their positions
|
|
480
504
|
const totalChars = displayIndent * 3;
|
|
481
505
|
const prefixChars = [];
|
|
506
|
+
const isFolded = this.foldedNodes.has(entry.id);
|
|
482
507
|
for (let i = 0; i < totalChars; i++) {
|
|
483
508
|
const level = Math.floor(i / 3);
|
|
484
509
|
const posInLevel = i % 3;
|
|
@@ -493,12 +518,13 @@ class TreeList {
|
|
|
493
518
|
}
|
|
494
519
|
}
|
|
495
520
|
else if (connector && level === connectorPosition) {
|
|
496
|
-
// Connector at this level
|
|
521
|
+
// Connector at this level, with fold indicator
|
|
497
522
|
if (posInLevel === 0) {
|
|
498
523
|
prefixChars.push(flatNode.isLast ? "└" : "├");
|
|
499
524
|
}
|
|
500
525
|
else if (posInLevel === 1) {
|
|
501
|
-
|
|
526
|
+
const foldable = this.isFoldable(entry.id);
|
|
527
|
+
prefixChars.push(isFolded ? "⊞" : foldable ? "⊟" : "─");
|
|
502
528
|
}
|
|
503
529
|
else {
|
|
504
530
|
prefixChars.push(" ");
|
|
@@ -509,12 +535,15 @@ class TreeList {
|
|
|
509
535
|
}
|
|
510
536
|
}
|
|
511
537
|
const prefix = prefixChars.join("");
|
|
538
|
+
// Fold marker for nodes without connectors (roots)
|
|
539
|
+
const showsFoldInConnector = flatNode.showConnector && !flatNode.isVirtualRootChild;
|
|
540
|
+
const foldMarker = isFolded && !showsFoldInConnector ? theme.fg("accent", "⊞ ") : "";
|
|
512
541
|
// Active path marker - shown right before the entry text
|
|
513
542
|
const isOnActivePath = this.activePathIds.has(entry.id);
|
|
514
543
|
const pathMarker = isOnActivePath ? theme.fg("accent", "• ") : "";
|
|
515
544
|
const label = flatNode.node.label ? theme.fg("warning", `[${flatNode.node.label}] `) : "";
|
|
516
545
|
const content = this.getEntryDisplayText(flatNode.node, isSelected);
|
|
517
|
-
let line = cursor + theme.fg("dim", prefix) + pathMarker + label + content;
|
|
546
|
+
let line = cursor + theme.fg("dim", prefix) + foldMarker + pathMarker + label + content;
|
|
518
547
|
if (isSelected) {
|
|
519
548
|
line = theme.bg("selectedBg", line);
|
|
520
549
|
}
|
|
@@ -602,6 +631,11 @@ class TreeList {
|
|
|
602
631
|
case "label":
|
|
603
632
|
result = theme.fg("dim", `[label: ${entry.label ?? "(cleared)"}]`);
|
|
604
633
|
break;
|
|
634
|
+
case "session_info":
|
|
635
|
+
result = entry.name
|
|
636
|
+
? [theme.fg("dim", "[title: "), theme.fg("dim", entry.name), theme.fg("dim", "]")].join("")
|
|
637
|
+
: [theme.fg("dim", "[title: "), theme.italic(theme.fg("dim", "empty")), theme.fg("dim", "]")].join("");
|
|
638
|
+
break;
|
|
605
639
|
default:
|
|
606
640
|
result = "";
|
|
607
641
|
}
|
|
@@ -703,11 +737,31 @@ class TreeList {
|
|
|
703
737
|
else if (kb.matches(keyData, "selectDown")) {
|
|
704
738
|
this.selectedIndex = this.selectedIndex === this.filteredNodes.length - 1 ? 0 : this.selectedIndex + 1;
|
|
705
739
|
}
|
|
706
|
-
else if (kb.matches(keyData, "
|
|
740
|
+
else if (kb.matches(keyData, "treeFoldOrUp")) {
|
|
741
|
+
const currentId = this.filteredNodes[this.selectedIndex]?.node.entry.id;
|
|
742
|
+
if (currentId && this.isFoldable(currentId) && !this.foldedNodes.has(currentId)) {
|
|
743
|
+
this.foldedNodes.add(currentId);
|
|
744
|
+
this.applyFilter();
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
this.selectedIndex = this.findBranchSegmentStart("up");
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
else if (kb.matches(keyData, "treeUnfoldOrDown")) {
|
|
751
|
+
const currentId = this.filteredNodes[this.selectedIndex]?.node.entry.id;
|
|
752
|
+
if (currentId && this.foldedNodes.has(currentId)) {
|
|
753
|
+
this.foldedNodes.delete(currentId);
|
|
754
|
+
this.applyFilter();
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
this.selectedIndex = this.findBranchSegmentStart("down");
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
else if (kb.matches(keyData, "cursorLeft") || kb.matches(keyData, "selectPageUp")) {
|
|
707
761
|
// Page up
|
|
708
762
|
this.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisibleLines);
|
|
709
763
|
}
|
|
710
|
-
else if (kb.matches(keyData, "cursorRight")) {
|
|
764
|
+
else if (kb.matches(keyData, "cursorRight") || kb.matches(keyData, "selectPageDown")) {
|
|
711
765
|
// Page down
|
|
712
766
|
this.selectedIndex = Math.min(this.filteredNodes.length - 1, this.selectedIndex + this.maxVisibleLines);
|
|
713
767
|
}
|
|
@@ -720,6 +774,7 @@ class TreeList {
|
|
|
720
774
|
else if (kb.matches(keyData, "selectCancel")) {
|
|
721
775
|
if (this.searchQuery) {
|
|
722
776
|
this.searchQuery = "";
|
|
777
|
+
this.foldedNodes.clear();
|
|
723
778
|
this.applyFilter();
|
|
724
779
|
}
|
|
725
780
|
else {
|
|
@@ -729,26 +784,31 @@ class TreeList {
|
|
|
729
784
|
else if (matchesKey(keyData, "ctrl+d")) {
|
|
730
785
|
// Direct filter: default
|
|
731
786
|
this.filterMode = "default";
|
|
787
|
+
this.foldedNodes.clear();
|
|
732
788
|
this.applyFilter();
|
|
733
789
|
}
|
|
734
790
|
else if (matchesKey(keyData, "ctrl+t")) {
|
|
735
791
|
// Toggle filter: no-tools ↔ default
|
|
736
792
|
this.filterMode = this.filterMode === "no-tools" ? "default" : "no-tools";
|
|
793
|
+
this.foldedNodes.clear();
|
|
737
794
|
this.applyFilter();
|
|
738
795
|
}
|
|
739
796
|
else if (matchesKey(keyData, "ctrl+u")) {
|
|
740
797
|
// Toggle filter: user-only ↔ default
|
|
741
798
|
this.filterMode = this.filterMode === "user-only" ? "default" : "user-only";
|
|
799
|
+
this.foldedNodes.clear();
|
|
742
800
|
this.applyFilter();
|
|
743
801
|
}
|
|
744
802
|
else if (matchesKey(keyData, "ctrl+l")) {
|
|
745
803
|
// Toggle filter: labeled-only ↔ default
|
|
746
804
|
this.filterMode = this.filterMode === "labeled-only" ? "default" : "labeled-only";
|
|
805
|
+
this.foldedNodes.clear();
|
|
747
806
|
this.applyFilter();
|
|
748
807
|
}
|
|
749
808
|
else if (matchesKey(keyData, "ctrl+a")) {
|
|
750
809
|
// Toggle filter: all ↔ default
|
|
751
810
|
this.filterMode = this.filterMode === "all" ? "default" : "all";
|
|
811
|
+
this.foldedNodes.clear();
|
|
752
812
|
this.applyFilter();
|
|
753
813
|
}
|
|
754
814
|
else if (matchesKey(keyData, "shift+ctrl+o")) {
|
|
@@ -756,6 +816,7 @@ class TreeList {
|
|
|
756
816
|
const modes = ["default", "no-tools", "user-only", "labeled-only", "all"];
|
|
757
817
|
const currentIndex = modes.indexOf(this.filterMode);
|
|
758
818
|
this.filterMode = modes[(currentIndex - 1 + modes.length) % modes.length];
|
|
819
|
+
this.foldedNodes.clear();
|
|
759
820
|
this.applyFilter();
|
|
760
821
|
}
|
|
761
822
|
else if (matchesKey(keyData, "ctrl+o")) {
|
|
@@ -763,11 +824,13 @@ class TreeList {
|
|
|
763
824
|
const modes = ["default", "no-tools", "user-only", "labeled-only", "all"];
|
|
764
825
|
const currentIndex = modes.indexOf(this.filterMode);
|
|
765
826
|
this.filterMode = modes[(currentIndex + 1) % modes.length];
|
|
827
|
+
this.foldedNodes.clear();
|
|
766
828
|
this.applyFilter();
|
|
767
829
|
}
|
|
768
830
|
else if (kb.matches(keyData, "deleteCharBackward")) {
|
|
769
831
|
if (this.searchQuery.length > 0) {
|
|
770
832
|
this.searchQuery = this.searchQuery.slice(0, -1);
|
|
833
|
+
this.foldedNodes.clear();
|
|
771
834
|
this.applyFilter();
|
|
772
835
|
}
|
|
773
836
|
}
|
|
@@ -784,10 +847,64 @@ class TreeList {
|
|
|
784
847
|
});
|
|
785
848
|
if (!hasControlChars && keyData.length > 0) {
|
|
786
849
|
this.searchQuery += keyData;
|
|
850
|
+
this.foldedNodes.clear();
|
|
787
851
|
this.applyFilter();
|
|
788
852
|
}
|
|
789
853
|
}
|
|
790
854
|
}
|
|
855
|
+
/**
|
|
856
|
+
* Whether a node can be folded. A node is foldable if it has visible children
|
|
857
|
+
* and is either a root (no visible parent) or a segment start (visible parent
|
|
858
|
+
* has multiple visible children).
|
|
859
|
+
*/
|
|
860
|
+
isFoldable(entryId) {
|
|
861
|
+
const children = this.visibleChildrenMap.get(entryId);
|
|
862
|
+
if (!children || children.length === 0)
|
|
863
|
+
return false;
|
|
864
|
+
const parentId = this.visibleParentMap.get(entryId);
|
|
865
|
+
if (parentId === null || parentId === undefined)
|
|
866
|
+
return true;
|
|
867
|
+
const siblings = this.visibleChildrenMap.get(parentId);
|
|
868
|
+
return siblings !== undefined && siblings.length > 1;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Find the index of the next branch segment start in the given direction.
|
|
872
|
+
* A segment start is the first child of a branch point.
|
|
873
|
+
*
|
|
874
|
+
* "up" walks the visible parent chain; "down" walks visible children
|
|
875
|
+
* (always following the first child).
|
|
876
|
+
*/
|
|
877
|
+
findBranchSegmentStart(direction) {
|
|
878
|
+
const selectedId = this.filteredNodes[this.selectedIndex]?.node.entry.id;
|
|
879
|
+
if (!selectedId)
|
|
880
|
+
return this.selectedIndex;
|
|
881
|
+
const indexByEntryId = new Map(this.filteredNodes.map((node, i) => [node.node.entry.id, i]));
|
|
882
|
+
let currentId = selectedId;
|
|
883
|
+
if (direction === "down") {
|
|
884
|
+
while (true) {
|
|
885
|
+
const children = this.visibleChildrenMap.get(currentId) ?? [];
|
|
886
|
+
if (children.length === 0)
|
|
887
|
+
return indexByEntryId.get(currentId);
|
|
888
|
+
if (children.length > 1)
|
|
889
|
+
return indexByEntryId.get(children[0]);
|
|
890
|
+
currentId = children[0];
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
// direction === "up"
|
|
894
|
+
while (true) {
|
|
895
|
+
const parentId = this.visibleParentMap.get(currentId) ?? null;
|
|
896
|
+
if (parentId === null)
|
|
897
|
+
return indexByEntryId.get(currentId);
|
|
898
|
+
const children = this.visibleChildrenMap.get(parentId) ?? [];
|
|
899
|
+
if (children.length > 1) {
|
|
900
|
+
const segmentStart = indexByEntryId.get(currentId);
|
|
901
|
+
if (segmentStart < this.selectedIndex) {
|
|
902
|
+
return segmentStart;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
currentId = parentId;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
791
908
|
}
|
|
792
909
|
/** Component that displays the current search query */
|
|
793
910
|
class SearchLine {
|
|
@@ -872,11 +989,11 @@ export class TreeSelectorComponent extends Container {
|
|
|
872
989
|
this.labelInput.focused = value;
|
|
873
990
|
}
|
|
874
991
|
}
|
|
875
|
-
constructor(tree, currentLeafId, terminalHeight, onSelect, onCancel, onLabelChange, initialSelectedId) {
|
|
992
|
+
constructor(tree, currentLeafId, terminalHeight, onSelect, onCancel, onLabelChange, initialSelectedId, initialFilterMode) {
|
|
876
993
|
super();
|
|
877
994
|
this.onLabelChangeCallback = onLabelChange;
|
|
878
995
|
const maxVisibleLines = Math.max(5, Math.floor(terminalHeight / 2));
|
|
879
|
-
this.treeList = new TreeList(tree, currentLeafId, maxVisibleLines, initialSelectedId);
|
|
996
|
+
this.treeList = new TreeList(tree, currentLeafId, maxVisibleLines, initialSelectedId, initialFilterMode);
|
|
880
997
|
this.treeList.onSelect = onSelect;
|
|
881
998
|
this.treeList.onCancel = onCancel;
|
|
882
999
|
this.treeList.onLabelEdit = (entryId, currentLabel) => this.showLabelInput(entryId, currentLabel);
|
|
@@ -886,7 +1003,7 @@ export class TreeSelectorComponent extends Container {
|
|
|
886
1003
|
this.addChild(new Spacer(1));
|
|
887
1004
|
this.addChild(new DynamicBorder());
|
|
888
1005
|
this.addChild(new Text(theme.bold(" Session Tree"), 1, 0));
|
|
889
|
-
this.addChild(new TruncatedText(theme.fg("muted", " ↑/↓: move. ←/→: page. Shift+L: label. ") +
|
|
1006
|
+
this.addChild(new TruncatedText(theme.fg("muted", " ↑/↓: move. ←/→: page. ^←/^→ or Alt+←/Alt+→: fold/branch. Shift+L: label. ") +
|
|
890
1007
|
theme.fg("muted", "^D/^T/^U/^L/^A: filters (^O/⇧^O cycle)"), 0, 0));
|
|
891
1008
|
this.addChild(new SearchLine(this.treeList));
|
|
892
1009
|
this.addChild(new DynamicBorder());
|