@oh-my-pi/pi-tui 18.10.0 → 18.10.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +42 -154
  2. package/THIRD-PARTY-NOTICES.txt +3 -3
  3. package/dist/types/app-keybindings.d.ts +8 -8
  4. package/dist/types/apps/git/diff-pane.d.ts +5 -0
  5. package/dist/types/apps/git/state.d.ts +11 -0
  6. package/dist/types/chat/assistant-message.d.ts +9 -4
  7. package/dist/types/chat/tool-execution.d.ts +32 -20
  8. package/dist/types/chat/user-message.d.ts +3 -2
  9. package/dist/types/chrome/countdown-timer.d.ts +3 -2
  10. package/dist/types/native/backend.d.ts +5 -4
  11. package/dist/types/native/blobs.d.ts +13 -1
  12. package/dist/types/overlays/annotation-overlay.d.ts +19 -0
  13. package/dist/types/overlays/ask-dialog.d.ts +9 -4
  14. package/dist/types/overlays/btw-history-panel.d.ts +2 -6
  15. package/dist/types/overlays/hook-editor.d.ts +7 -2
  16. package/dist/types/overlays/hook-input.d.ts +12 -4
  17. package/dist/types/overlays/jobs-panel.d.ts +8 -7
  18. package/dist/types/overlays/login-dialog.d.ts +8 -3
  19. package/dist/types/overlays/mcp-add-wizard.d.ts +9 -1
  20. package/dist/types/overlays/model-browser.d.ts +6 -1
  21. package/dist/types/overlays/pause-screen.d.ts +5 -0
  22. package/dist/types/overlays/report-panel.d.ts +5 -1
  23. package/dist/types/overlays/reset-usage-selector.d.ts +7 -5
  24. package/dist/types/overlays/session-account-selector.d.ts +4 -0
  25. package/dist/types/overlays/session-info-overlay.d.ts +7 -3
  26. package/dist/types/overlays/usage-dashboard.d.ts +6 -6
  27. package/dist/types/status-line/context-usage.d.ts +1 -1
  28. package/dist/types/tools/bash.d.ts +2 -1
  29. package/dist/types/tools/eval.d.ts +2 -2
  30. package/dist/types/tools/grouped-file-output.d.ts +4 -1
  31. package/dist/types/tools/native-view.d.ts +1 -1
  32. package/dist/types/tools/read.d.ts +7 -1
  33. package/dist/types/tools/renderer.d.ts +2 -0
  34. package/package.json +9 -9
  35. package/src/app-keybindings.ts +8 -8
  36. package/src/apps/autoresearch-dashboard.ts +440 -27
  37. package/src/apps/git/diff-pane.ts +39 -35
  38. package/src/apps/git/git-tui.ts +53 -4
  39. package/src/apps/git/state.ts +12 -0
  40. package/src/chat/assistant-message.ts +68 -19
  41. package/src/chat/tool-execution.ts +73 -30
  42. package/src/chat/user-message.ts +32 -19
  43. package/src/chrome/countdown-timer.ts +3 -3
  44. package/src/native/backend.ts +13 -5
  45. package/src/native/blobs.ts +34 -1
  46. package/src/native/reconcile.ts +24 -6
  47. package/src/overlays/advisor-config.ts +259 -8
  48. package/src/overlays/annotation-overlay.ts +420 -168
  49. package/src/overlays/ask-dialog.ts +154 -90
  50. package/src/overlays/btw-history-panel.ts +178 -124
  51. package/src/overlays/hook-editor.ts +90 -32
  52. package/src/overlays/hook-input.ts +105 -19
  53. package/src/overlays/jobs-panel.ts +154 -132
  54. package/src/overlays/login-dialog.ts +201 -91
  55. package/src/overlays/mcp-add-wizard.ts +559 -279
  56. package/src/overlays/model-browser.ts +23 -1
  57. package/src/overlays/model-hub.ts +2 -9
  58. package/src/overlays/pause-screen.ts +81 -23
  59. package/src/overlays/plugin-selector.ts +17 -1
  60. package/src/overlays/queue-mode-selector.ts +10 -0
  61. package/src/overlays/report-panel.ts +6 -2
  62. package/src/overlays/reset-usage-selector.ts +130 -21
  63. package/src/overlays/session-account-selector.ts +36 -0
  64. package/src/overlays/session-info-overlay.ts +197 -76
  65. package/src/overlays/show-images-selector.ts +1 -0
  66. package/src/overlays/theme-selector.ts +6 -1
  67. package/src/overlays/thinking-selector.ts +8 -4
  68. package/src/overlays/tree-selector.ts +117 -2
  69. package/src/overlays/usage-dashboard.ts +495 -143
  70. package/src/status-line/context-usage.ts +154 -57
  71. package/src/tools/bash.ts +9 -8
  72. package/src/tools/eval.ts +2 -2
  73. package/src/tools/grep.ts +1 -0
  74. package/src/tools/grouped-file-output.ts +11 -2
  75. package/src/tools/native-view.ts +2 -2
  76. package/src/tools/read.ts +12 -4
  77. package/src/tools/renderer.ts +2 -0
  78. package/src/tools/wait.ts +16 -30
@@ -42,12 +42,13 @@ export interface JobsSheetSource {
42
42
  }
43
43
  /**
44
44
  * The jobs pill's sheet: a centred `lg` glass sheet titled Background jobs.
45
- * A selectable list of every job (running first) sits over the selected
46
- * job's detail: status and live elapsed (a task job's `agent` node), cwd,
47
- * live pids, exit code, the full command and a tail-following output pane.
48
- * It re-reads the session every frame, so the caller re-renders it on a
49
- * timer while it is open. ↑/↓ select, X cancels the selected running job,
50
- * Esc or Close dismisses; nothing enters the transcript.
45
+ * A master–detail split (it stacks in a narrow pane): the selectable job list,
46
+ * grouped Running / Recent, beside the selected job's detail — a status pill
47
+ * with live elapsed and Cancel job, its command or task, facts (agent, cwd,
48
+ * live pids, exit code, artifact) and a tail-following output pane. With no
49
+ * jobs it shows an empty state. It re-reads the session every frame, so the
50
+ * caller re-renders it on a timer while it is open. ↑/↓ select, X cancels the
51
+ * selected running job, Esc or Close dismisses; nothing enters the transcript.
51
52
  */
52
53
  export declare class JobsSheet implements Component {
53
54
  #private;
@@ -58,7 +59,7 @@ export declare class JobsSheet implements Component {
58
59
  readonly head: "Background jobs";
59
60
  };
60
61
  constructor(source: JobsSheetSource);
61
- describe(cx: DescribeContext): NativeNode;
62
+ describe(_cx: DescribeContext): NativeNode;
62
63
  /** Rows for a terminal without the native surface: one per job, then the selected job's facts and output tail. */
63
64
  render(width: number): readonly string[];
64
65
  invalidate(): void;
@@ -40,9 +40,14 @@ export declare class LoginDialogComponent extends OverlayPanel {
40
40
  showProgress(message: string): void;
41
41
  /**
42
42
  * A glass sheet over the composer (the dialog replaces the editor in the
43
- * dock; the `overlay` hoists into the terminal's layer): numbered steps —
44
- * open or copy the sign-in link, the device code, the live wait, the paste
45
- * field — and Cancel.
43
+ * dock; the `overlay` hoists into the terminal's layer). Top to bottom: one
44
+ * sentence saying what to do, the device code as a large click-to-copy
45
+ * well, the sign-in link as a read-only field with Copy, the questions
46
+ * (answered ones as label/value lines, the live one as a field), and the
47
+ * flow's status — finished stages checked, the current one spinning. The
48
+ * footer holds Cancel and one primary action: Continue while a field waits
49
+ * for an answer (Open sign-in page then leads the footer as a plain
50
+ * button), else Open sign-in page.
46
51
  */
47
52
  describe(): NativeNode;
48
53
  /** Cancel and Continue run what Esc and Enter run. */
@@ -83,8 +83,16 @@ interface MCPAddWizardOAuthOptions {
83
83
  export declare class MCPAddWizard extends OverlayPanel {
84
84
  #private;
85
85
  constructor(deps: MCPAddWizardDeps, onComplete: (name: string, config: MCPAddWizardConfig, scope: Scope) => void, onCancel: () => void, onOAuth?: (authUrl: string, tokenUrl: string, clientId: string, clientSecret: string, scopes: string, options?: MCPAddWizardOAuthOptions) => Promise<MCPAddWizardOAuthResult>, onTestConnection?: (config: MCPAddWizardConfig) => Promise<void>, onRender?: () => void, initialName?: string);
86
+ /**
87
+ * The sheet: the phase strip, the step's title and lead, its body (field,
88
+ * status, summary), its choices, and a footer whose buttons run what
89
+ * Escape, Enter and Ctrl+C run.
90
+ */
86
91
  describe(_cx: DescribeContext): NativeNode;
87
- /** A click on a choice is Enter on it, exactly as highlighting it with the arrows and pressing Enter. */
92
+ /**
93
+ * A click on a choice is Enter on it, exactly as highlighting it with the
94
+ * arrows and pressing Enter; the footer's buttons run what their keys run.
95
+ */
88
96
  handleNativeEvent(event: NativeUiEvent): void;
89
97
  handleInput(keyData: string): void;
90
98
  }
@@ -4,7 +4,7 @@ import type { Component } from "../tui.js";
4
4
  import type { SgrMouseEvent } from "../mouse.js";
5
5
  import { type ConfiguredThinkingLevel } from "../thinking.js";
6
6
  import { type ThemeColor } from "../theme/theme.js";
7
- import type { TspPickerColumn, TspPickerGroup, TspPickerItem } from "@oh-my-pi/pi-wire";
7
+ import type { TspPickerColumn, TspPickerGroup, TspPickerItem, TspPickerMark } from "@oh-my-pi/pi-wire";
8
8
  import type { NativeChild, NativeNode, NativeUiEvent } from "../native/node.js";
9
9
  /** Canonical display ordering of built-in model roles. */
10
10
  export type ModelRole = "default" | "smol" | "slow" | "vision" | "plan" | "commit" | "tiny" | "memory" | "task" | "advisor" | "image" | "web" | "speech" | "dictation" | "judge";
@@ -198,6 +198,11 @@ export declare function rankModelItems(query: string, items: ReadonlyArray<Model
198
198
  export declare function formatRoleChip(role: string, assignment: RoleAssignment, settings: ModelBrowserSource): string;
199
199
  /** Fact columns of a model picker (Stencil `NATIVE_REDESIGN.md` §4.7); the lowest priority hides first. */
200
200
  export declare const MODEL_PICKER_COLUMNS: readonly TspPickerColumn[];
201
+ /**
202
+ * A provider's picker mark: the terminal's logo for it, else its initials
203
+ * (`amazon-bedrock` → `AB`, `anthropic` → `An`) on its own gradient.
204
+ */
205
+ export declare function providerMark(providerId: string): TspPickerMark;
201
206
  /** The omp theme token of a thinking level's dot (`thinkingHigh`); none for inherit and auto. */
202
207
  export declare function thinkingDotToken(level: ConfiguredThinkingLevel): string | undefined;
203
208
  /**
@@ -41,6 +41,11 @@ export declare class PauseScreenComponent implements Component, OverlayFocusOwne
41
41
  readonly anchor: "center";
42
42
  readonly head: "Paused";
43
43
  };
44
+ /**
45
+ * The sheet: a hero (the pause glyph beside the live hold clock and the
46
+ * session it holds), what the hold means as four facts, and a footer that
47
+ * reassures and resumes. The resume keys live in the button's tooltip.
48
+ */
44
49
  describe(): NativeNode;
45
50
  /** Resume runs what Esc/Enter/Space run. */
46
51
  handleNativeEvent(event: NativeUiEvent): void;
@@ -55,7 +55,11 @@ export declare class ReportPanel extends OverlayPanel {
55
55
  render(width: number): readonly string[];
56
56
  /** Text mode: rows the whole box takes at `width` when nothing caps it. */
57
57
  heightAt(width: number): number;
58
- /** The sheet body (the overlay is the frame, and its body the scroller): the report, then Close (Esc). */
58
+ /**
59
+ * The sheet body (the overlay is the frame, and its body the scroller): the
60
+ * report as `omp.report.body`, which the terminal sets on the reading
61
+ * measure, then Close (Esc) as the sheet's footer.
62
+ */
59
63
  describe(): NativeNode;
60
64
  invalidate(): void;
61
65
  /**
@@ -1,6 +1,6 @@
1
1
  import type { UsageResetCreditDetail } from "@oh-my-pi/pi-ai";
2
2
  import { OverlayPanel } from "../chrome/overlay-box.js";
3
- import type { NativeNode, NativeUiEvent } from "../native/node.js";
3
+ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
4
4
  /** One account row with its redeemable rate-limit reset credits. */
5
5
  export interface ResetUsageAccount {
6
6
  label: string;
@@ -33,11 +33,13 @@ export declare class ResetUsageSelectorComponent extends OverlayPanel {
33
33
  #private;
34
34
  constructor(accounts: ResetUsageAccount[], onSelect: (account: ResetUsageAccount) => void, onCancel: () => void);
35
35
  handleInput(keyData: string): void;
36
- describe(): NativeNode;
36
+ describe(cx: DescribeContext): NativeNode;
37
37
  /**
38
- * A click (or double-click) on an account highlights it and presses Enter:
39
- * moving to another account drops a pending confirmation, so spending a
40
- * reset still takes a second activation of the same account.
38
+ * Picker: a row click selects, a double-click or `Spend reset` presses
39
+ * Enter (so spending still takes a second activation, on the confirm
40
+ * strip), the strip's `Keep` drops the confirmation and `Close` cancels.
41
+ * Card list: a click (or double-click) on an account highlights it and
42
+ * presses Enter.
41
43
  */
42
44
  handleNativeEvent(event: NativeUiEvent): void;
43
45
  }
@@ -1,5 +1,6 @@
1
1
  import { type SgrMouseEvent } from "../index.js";
2
2
  import { OverlayPanel } from "../chrome/overlay-box.js";
3
+ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
3
4
  /** Stored account identity rendered and matched by the session account picker. */
4
5
  export interface SessionPinAccount {
5
6
  position: number;
@@ -17,6 +18,9 @@ export interface SessionPinAccount {
17
18
  export declare class SessionAccountSelectorComponent extends OverlayPanel {
18
19
  #private;
19
20
  constructor(providerName: string, accounts: readonly SessionPinAccount[], onSelect: (account: SessionPinAccount) => void, onCancel: () => void);
21
+ describe(cx: DescribeContext): NativeNode | null;
22
+ /** Picker pointer events drive the list exactly as its keys do. */
23
+ handleNativeEvent(event: NativeUiEvent): void;
20
24
  /** Forward keyboard navigation and cancellation when the wrapper owns focus. */
21
25
  handleInput(keyData: string): void;
22
26
  /** Route mouse selection through the title rows into the account list. */
@@ -24,9 +24,13 @@ export declare class SessionInfoOverlay implements Component {
24
24
  setIgnoreTight(ignore: boolean): this;
25
25
  dispose(): void;
26
26
  /**
27
- * The sheet body (the overlay is the frame): the session id in mono
28
- * (click copies), each report heading as a section of key/value rows, a
29
- * context meter after the leading block, and a Close button (Esc).
27
+ * The sheet body (the overlay is the frame), in three tiers: who the session
28
+ * is (the id and file as copyable mono fields), how full its context window
29
+ * is (a meter under a right-aligned figure), then the report's sections as
30
+ * headed groups. Groups of plain counts (Messages, Tokens, Cost) share a
31
+ * two-column stats grid with right-aligned figures and their Total set off
32
+ * last; the rest (Provider, servers) are key/value rows. A Close button (Esc)
33
+ * ends it.
30
34
  */
31
35
  describe(cx: DescribeContext): NativeNode;
32
36
  /** The Close button runs Esc's path. */
@@ -122,12 +122,12 @@ export declare class UsageDashboardComponent implements Component {
122
122
  dispose(): void;
123
123
  render(width: number): readonly string[];
124
124
  /**
125
- * The sheet body (the terminal's `lg` overlay is the frame): a head row
126
- * (checked ago, Overview/Details tabs, Refresh), then either the provider
127
- * grid of frames with window meters and the activity heatmap, or the
128
- * per-provider detail tables, then Close like the other report sheets.
129
- * `meter`/`chart` fall back to `progress`/`table` on terminals without
130
- * them. Rebuilt only when its inputs change.
125
+ * The sheet body (the terminal's `lg` overlay is the frame): a toolbar
126
+ * (Overview/Details, freshness, Refresh), then either the overview — a
127
+ * strip of headline figures, the quota rows per provider, the activity
128
+ * calendar — or the per-provider detail tables, then Close like the other
129
+ * report sheets. `meter`/`chart` fall back to `progress`/`table` on
130
+ * terminals without them. Rebuilt only when its inputs change.
131
131
  */
132
132
  describe(cx: DescribeContext): NativeNode;
133
133
  /** Tab clicks switch views like Enter/Esc; the Refresh button runs `r`; Close closes from either view. */
@@ -155,7 +155,7 @@ export declare function computeNonMessageBreakdown(session: NonMessageTokenSourc
155
155
  * session and model.
156
156
  */
157
157
  export declare function computeContextBreakdown(session: ContextUsageSession, options: ContextUsageOptions): ContextBreakdown;
158
- /** The `/context` title: the model and its window once a model is selected. */
158
+ /** The `/context` title: the model once one is selected (the body leads with its window). */
159
159
  export declare function contextUsageHead(breakdown: ContextBreakdown): TspText;
160
160
  /**
161
161
  * Native context-usage panel for terminals without `meter`: the cell grid as
@@ -31,8 +31,9 @@ export interface BashToolDetails {
31
31
  timedOut: boolean;
32
32
  pid?: number;
33
33
  };
34
+ /** Background job behind the call; `cancelled`: killed (`proc://<id>/kill`) before it finished. */
34
35
  async?: {
35
- state: "running" | "completed" | "failed";
36
+ state: "running" | "completed" | "failed" | "cancelled";
36
37
  jobId: string;
37
38
  type: "bash";
38
39
  };
@@ -44,9 +44,9 @@ export interface EvalToolDetails {
44
44
  languages?: EvalLanguage[];
45
45
  /** Optional human-readable notice (e.g. fallback explanation). */
46
46
  notice?: string;
47
- /** Present when the cell was auto-backgrounded as an async job. */
47
+ /** Present when the cell was auto-backgrounded as an async job; `cancelled`: killed before it finished. */
48
48
  async?: {
49
- state: "running" | "completed" | "failed";
49
+ state: "running" | "completed" | "failed" | "cancelled";
50
50
  jobId: string;
51
51
  type: "eval";
52
52
  };
@@ -121,9 +121,12 @@ export declare function numberedCode(lines: readonly NumberedLine[], opts?: {
121
121
  * header's suffix or the match count as a chip), then its lines as
122
122
  * {@link numberedCode} with match lines marked and `…` between non-adjacent
123
123
  * runs. Unnumbered body lines stay plain `code`. `maxFiles` keeps only the
124
- * first files (the caller says how many were left out).
124
+ * first files (the caller says how many were left out). `file` owns the lines
125
+ * before any header: a single-file search prints none, yet its lines get the
126
+ * same file row as a directory search's.
125
127
  */
126
128
  export declare function describeGroupedOutput(lines: readonly string[], options?: {
127
129
  lang?: (path: string) => string | undefined;
128
130
  maxFiles?: number;
131
+ file?: string;
129
132
  }): NativeNode[];
@@ -85,7 +85,7 @@ export interface RunFootInput {
85
85
  readonly state: RunState;
86
86
  /** Exit code of a `failed` run; a non-zero code names the state `exit N`. */
87
87
  readonly exitCode?: number;
88
- /** Milliseconds run so far (`running`) or in total; the time is omitted when undefined. */
88
+ /** Milliseconds run so far (`running`, a live `background` job) or in total; omitted when undefined. */
89
89
  readonly elapsedMs?: number;
90
90
  /** Quiet facts (job id, service state, artifact), muted and ` · `-joined. */
91
91
  readonly facts?: readonly string[];
@@ -20,6 +20,12 @@ export interface ReadToolDetails {
20
20
  truncation?: ReadTruncationStats;
21
21
  isDirectory?: boolean;
22
22
  resolvedPath?: string;
23
+ /**
24
+ * Absolute path of the disk file whose image this read returned. A native TSP host that
25
+ * supports `media` shows the file by path instead of the uploaded image bytes. Unset for
26
+ * screenshots, URL reads and other images not backed by a file. Display-only.
27
+ */
28
+ mediaPath?: string;
23
29
  suffixResolution?: {
24
30
  from: string;
25
31
  to: string;
@@ -140,7 +146,7 @@ export declare const readToolRenderer: {
140
146
  }>;
141
147
  details?: ReadToolDetails;
142
148
  isError?: boolean;
143
- }, _options: RenderResultOptions, args?: ReadRenderArgs): NativeToolView;
149
+ }, options: RenderResultOptions, args?: ReadRenderArgs): NativeToolView;
144
150
  mergeCallAndResult: true;
145
151
  };
146
152
  /** Inclusive line range describing one elided span in a structural summary. */
@@ -33,6 +33,8 @@ export interface RenderResultOptions {
33
33
  elapsedMs?: number;
34
34
  /** The call was abandoned without a final result (turn aborted, sealed). Native describe hooks only. */
35
35
  cancelled?: boolean;
36
+ /** The native host shows files by path (`cx.supports("media")`). Native describe hooks only. */
37
+ media?: boolean;
36
38
  }
37
39
  /** Render options for a result, plus the tool-specific context the transcript threads through. */
38
40
  export type RenderResultContextOptions = RenderResultOptions & {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-tui",
4
- "version": "18.10.0",
4
+ "version": "18.10.2",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": {
@@ -41,14 +41,14 @@
41
41
  "gen:glyphs": "bun scripts/gen-glyphs.ts"
42
42
  },
43
43
  "dependencies": {
44
- "@oh-my-pi/omptype": "18.10.0",
45
- "@oh-my-pi/pi-agent-core": "18.10.0",
46
- "@oh-my-pi/pi-ai": "18.10.0",
47
- "@oh-my-pi/pi-catalog": "18.10.0",
48
- "@oh-my-pi/pi-natives": "18.10.0",
49
- "@oh-my-pi/pi-utils": "18.10.0",
50
- "@oh-my-pi/pi-wire": "18.10.0",
51
- "@oh-my-pi/snapcompact": "18.10.0"
44
+ "@oh-my-pi/omptype": "18.10.2",
45
+ "@oh-my-pi/pi-agent-core": "18.10.2",
46
+ "@oh-my-pi/pi-ai": "18.10.2",
47
+ "@oh-my-pi/pi-catalog": "18.10.2",
48
+ "@oh-my-pi/pi-natives": "18.10.2",
49
+ "@oh-my-pi/pi-utils": "18.10.2",
50
+ "@oh-my-pi/pi-wire": "18.10.2",
51
+ "@oh-my-pi/snapcompact": "18.10.2"
52
52
  },
53
53
  "devDependencies": {
54
54
  "kitty-vt-wasm": "^0.2.0"
@@ -57,8 +57,8 @@ interface AppKeybindings {
57
57
  "app.session.rename": true;
58
58
  "app.session.delete": true;
59
59
  "app.session.deleteNoninvasive": true;
60
- "app.tree.foldOrUp": true;
61
- "app.tree.unfoldOrDown": true;
60
+ "app.tree.previousBranch": true;
61
+ "app.tree.nextBranch": true;
62
62
  "app.plan.toggle": true;
63
63
  "app.history.search": true;
64
64
  "app.stt.pushToTalk": true;
@@ -227,13 +227,13 @@ export const KEYBINDINGS = {
227
227
  defaultKeys: "ctrl+backspace",
228
228
  description: "Delete session (non-invasive)",
229
229
  },
230
- "app.tree.foldOrUp": {
231
- defaultKeys: ["ctrl+left", "alt+left"],
232
- description: "Fold or move up",
230
+ "app.tree.previousBranch": {
231
+ defaultKeys: [],
232
+ description: "Jump to the previous branch in /tree",
233
233
  },
234
- "app.tree.unfoldOrDown": {
235
- defaultKeys: ["ctrl+right", "alt+right"],
236
- description: "Unfold or move down",
234
+ "app.tree.nextBranch": {
235
+ defaultKeys: [],
236
+ description: "Jump to the next branch in /tree",
237
237
  },
238
238
  "app.plan.toggle": {
239
239
  defaultKeys: "alt+shift+p",