@fresh-editor/fresh-editor 0.3.6 → 0.3.8

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.
@@ -252,6 +252,10 @@ type ViewportInfo = {
252
252
  */
253
253
  height: number;
254
254
  };
255
+ type ScreenSize = {
256
+ width: number;
257
+ height: number;
258
+ };
255
259
  type KeyEventPayload = {
256
260
  /**
257
261
  * Key name (e.g. `"a"`, `"escape"`, `"f1"`).
@@ -319,15 +323,18 @@ type ViewTokenWireKind = {
319
323
  } | "Newline" | "Space" | "Break" | {
320
324
  "BinaryByte": number;
321
325
  };
326
+ type TokenColor = [number, number, number] | string;
322
327
  type ViewTokenStyle = {
323
328
  /**
324
- * Foreground color as RGB tuple
329
+ * Foreground color. Either `[r, g, b]` or a named/theme string —
330
+ * see [`TokenColor`].
325
331
  */
326
- fg: [number, number, number] | null;
332
+ fg: TokenColor | null;
327
333
  /**
328
- * Background color as RGB tuple
334
+ * Background color. Either `[r, g, b]` or a named/theme string —
335
+ * see [`TokenColor`].
329
336
  */
330
- bg: [number, number, number] | null;
337
+ bg: TokenColor | null;
331
338
  /**
332
339
  * Whether to render in bold
333
340
  */
@@ -336,6 +343,10 @@ type ViewTokenStyle = {
336
343
  * Whether to render in italic
337
344
  */
338
345
  italic: boolean;
346
+ /**
347
+ * Whether to render with underline
348
+ */
349
+ underline: boolean;
339
350
  };
340
351
  type PromptSuggestion = {
341
352
  /**
@@ -445,6 +456,23 @@ type WindowInfo = {
445
456
  * Absolute project root.
446
457
  */
447
458
  root: string;
459
+ /**
460
+ * Project this session belongs to — the canonical repo
461
+ * root (or arbitrary directory) the user pointed the
462
+ * new-session form at. `null` for legacy sessions that
463
+ * predate the Project Path field. The Orchestrator Open
464
+ * dialog filters by this so the "this project's sessions"
465
+ * view is one keystroke away from the all-projects view.
466
+ */
467
+ project_path?: string | null;
468
+ /**
469
+ * `true` when the session shares its working tree with
470
+ * other sessions (worktree-creation was off at session
471
+ * time, or the session lives in a non-git directory).
472
+ * Persistence-only field; defaults to `false` and isn't
473
+ * emitted when false.
474
+ */
475
+ shared_worktree?: boolean;
448
476
  };
449
477
  type JsDiagnostic = {
450
478
  /**
@@ -593,6 +621,50 @@ type TerminalResult = {
593
621
  */
594
622
  splitId: number | null;
595
623
  };
624
+ type CreateWindowWithTerminalOptions = {
625
+ /**
626
+ * Absolute path to the new session's worktree / project
627
+ * root. Relative paths are rejected (logged, no window
628
+ * created).
629
+ */
630
+ root: string;
631
+ /**
632
+ * Human-readable label for the new session. When empty,
633
+ * defaults to the basename of `root`.
634
+ */
635
+ label: string;
636
+ /**
637
+ * Working directory for the spawned terminal. Defaults to
638
+ * `root` when omitted.
639
+ */
640
+ cwd?: string;
641
+ /**
642
+ * Argv to spawn directly inside the PTY. `None` keeps the
643
+ * shell-and-type behaviour; `Some([cmd, ...args])` runs the
644
+ * command as the PTY child (used by Orchestrator so the
645
+ * agent process is the PTY's direct child).
646
+ */
647
+ command?: Array<string>;
648
+ /**
649
+ * Tab title override. Defaults to `command[0]`'s basename
650
+ * when `command` is set, or "Terminal N" otherwise.
651
+ */
652
+ title?: string;
653
+ };
654
+ type SessionWithTerminalResult = {
655
+ /**
656
+ * The new window's id.
657
+ */
658
+ windowId: number;
659
+ /**
660
+ * The seeded terminal's id (for `sendTerminalInput`, etc.).
661
+ */
662
+ terminalId: number;
663
+ /**
664
+ * The seeded terminal buffer's id.
665
+ */
666
+ bufferId: number;
667
+ };
596
668
  type CreateTerminalOptions = {
597
669
  /**
598
670
  * Working directory for the terminal (defaults to editor cwd)
@@ -629,6 +701,27 @@ type CreateTerminalOptions = {
629
701
  * target session's membership set rather than the active one's.
630
702
  */
631
703
  windowId?: WindowId;
704
+ /**
705
+ * Argv to spawn directly inside the PTY instead of the host's
706
+ * configured shell. `None` (default) keeps the historical
707
+ * behaviour: spawn the user's shell and let the caller type into
708
+ * it via `sendTerminalInput`. `Some([cmd, ...args])` runs that
709
+ * exact command as the PTY child — no shell middleman, so the
710
+ * process exits cleanly when the agent does and the
711
+ * terminal-buffer's `terminal_exit` plugin hook reflects the
712
+ * agent's real exit status. Used by Orchestrator so a session
713
+ * with agent `python3` is just python3 in the PTY rather than
714
+ * bash-running-python3-as-a-subshell-command.
715
+ */
716
+ command?: Array<string>;
717
+ /**
718
+ * Tab title for the terminal buffer. Defaults to `command[0]`
719
+ * (when `command` is set) or `"Terminal N"` (the historical
720
+ * auto-numbered title). If another terminal in the same window
721
+ * already uses the requested title, the host appends `" (k)"`
722
+ * to disambiguate. Empty string is treated the same as `None`.
723
+ */
724
+ title?: string;
632
725
  };
633
726
  type CursorInfo = {
634
727
  /**
@@ -673,6 +766,13 @@ type OverlayOptions = {
673
766
  */
674
767
  extendToLineEnd: boolean;
675
768
  /**
769
+ * When `true`, `fg` is applied only on cells whose existing fg
770
+ * matches this overlay's resolved bg — i.e. a same-colour fg/bg
771
+ * collision. Lets a row-wide overlay stay legible on tokens that
772
+ * share the bg's colour without repainting unrelated tokens.
773
+ */
774
+ fgOnCollisionOnly: boolean;
775
+ /**
676
776
  * Optional URL for OSC 8 terminal hyperlinks.
677
777
  * When set, the overlay text becomes a clickable hyperlink in terminals
678
778
  * that support OSC 8 escape sequences.
@@ -816,6 +916,15 @@ type WidgetSpec = {
816
916
  focused: boolean;
817
917
  intent: ButtonKind;
818
918
  key?: string | null;
919
+ /**
920
+ * When true, the button renders in a muted style, is dropped
921
+ * from the Tab cycle, and clicks on it are ignored. Use for
922
+ * actions that aren't currently available against the
923
+ * surrounding state (e.g. "Archive" on the base session). The
924
+ * button still occupies its layout cell so the surrounding
925
+ * row doesn't reshuffle when the disabled flag flips.
926
+ */
927
+ disabled: boolean;
819
928
  } | {
820
929
  "kind": "spacer";
821
930
  cols: number;
@@ -923,6 +1032,41 @@ type WidgetSpec = {
923
1032
  * `LabeledSection` or a flexible row.
924
1033
  */
925
1034
  fullWidth: boolean;
1035
+ /**
1036
+ * Optional completion candidates. When non-empty AND
1037
+ * `label` is non-empty (the chrome trigger), the
1038
+ * renderer paints a popup directly under the input,
1039
+ * inside a unified box: the input's normal `╰─...─╯`
1040
+ * bottom border becomes a dimmed `┄` separator, the
1041
+ * labeled section's side borders extend down through
1042
+ * the candidate rows, and a single `╰─...─╯` bottom
1043
+ * closes the whole block. Candidates render left-
1044
+ * aligned with the input's text (the position right
1045
+ * after `[`), with the host-managed selected index
1046
+ * highlighted.
1047
+ *
1048
+ * Smart-key dispatch on a focused Text-with-completions:
1049
+ * Up/Down moves selection (host-internal, no event),
1050
+ * Tab fires `completion_accept` with the selected
1051
+ * candidate, Enter / Escape fire `completion_dismiss`
1052
+ * (the dispatcher's normal "Enter focus-advance / Esc
1053
+ * close panel" only runs once the popup is closed).
1054
+ *
1055
+ * Plugins push candidates in response to the text
1056
+ * widget's `change` event via
1057
+ * `WidgetMutation::SetCompletions`. An empty `items`
1058
+ * closes the popup.
1059
+ */
1060
+ completions?: Array<string | CompletionItem>;
1061
+ /**
1062
+ * How many candidate rows the popup paints at once
1063
+ * when it opens. Excess candidates stay reachable
1064
+ * via Up/Down (host auto-scrolls to keep selection
1065
+ * in view) or the mouse wheel; a thumb glyph paints
1066
+ * in the right edge of the popup whenever there's
1067
+ * more to scroll. `0` (default) falls back to `5`.
1068
+ */
1069
+ completionsVisibleRows: number;
926
1070
  key?: string | null;
927
1071
  } | {
928
1072
  "kind": "labeledSection";
@@ -967,6 +1111,10 @@ type WidgetSpec = {
967
1111
  "kind": "raw";
968
1112
  entries: Array<TextPropertyEntry>;
969
1113
  key?: string | null;
1114
+ } | {
1115
+ "kind": "overlay";
1116
+ child: WidgetSpec;
1117
+ key?: string | null;
970
1118
  };
971
1119
  type WidgetAction = {
972
1120
  "kind": "focusAdvance";
@@ -991,6 +1139,10 @@ type WidgetMutation = {
991
1139
  widgetKey: string;
992
1140
  value: string;
993
1141
  cursorByte?: number | null;
1142
+ } | {
1143
+ "kind": "setCompletions";
1144
+ widgetKey: string;
1145
+ items: Array<string | CompletionItem>;
994
1146
  } | {
995
1147
  "kind": "setChecked";
996
1148
  widgetKey: string;
@@ -1013,6 +1165,18 @@ type WidgetMutation = {
1013
1165
  widgetKey: string;
1014
1166
  checked: boolean;
1015
1167
  keys: Array<string>;
1168
+ } | {
1169
+ "kind": "appendTreeNodes";
1170
+ widgetKey: string;
1171
+ newNodes: Array<TreeNode>;
1172
+ newItemKeys: Array<string>;
1173
+ } | {
1174
+ "kind": "setRawEntries";
1175
+ widgetKey: string;
1176
+ entries: Array<TextPropertyEntry>;
1177
+ } | {
1178
+ "kind": "setFocusKey";
1179
+ widgetKey: string;
1016
1180
  };
1017
1181
  type SearchTakeResult = {
1018
1182
  /**
@@ -1442,7 +1606,9 @@ interface EditorAPI {
1442
1606
  * contexts only (e.g. `"tour-active"`, `"review-mode"`), not built-in
1443
1607
  * editor modes.
1444
1608
  */
1445
- registerCommand(name: string, description: string, handlerName: string, context?: string | null): boolean;
1609
+ registerCommand(name: string, description: string, handlerName: string, context?: string | null, options?: {
1610
+ terminalBypass?: boolean;
1611
+ } | null): boolean;
1446
1612
  /**
1447
1613
  * Unregister a command by name
1448
1614
  */
@@ -1456,6 +1622,17 @@ interface EditorAPI {
1456
1622
  */
1457
1623
  executeAction(actionName: string): boolean;
1458
1624
  /**
1625
+ * Register a custom statusbar token.
1626
+ * Token will be named "plugin_name:token_name" where plugin_name is the current plugin.
1627
+ * Returns true if registration succeeded, false if invalid or already registered.
1628
+ */
1629
+ registerStatusBarElement(tokenName: string, title: string): boolean;
1630
+ /**
1631
+ * Set the value of a status-bar token for a specific buffer.
1632
+ * The full token key sent to the editor is "plugin_name:token_name".
1633
+ */
1634
+ setStatusBarValue(bufferId: number, tokenName: string, value: string): boolean;
1635
+ /**
1459
1636
  * Translate a string - reads plugin name from __pluginName__ global
1460
1637
  * Args is optional - can be omitted, undefined, null, or an object
1461
1638
  */
@@ -1502,6 +1679,13 @@ interface EditorAPI {
1502
1679
  */
1503
1680
  getViewport(): ViewportInfo | null;
1504
1681
  /**
1682
+ * Total terminal dimensions in cells. Unlike `getViewport()`
1683
+ * (which reports the active split, shrunk by any vertical
1684
+ * split layout), this reflects the full terminal — what a
1685
+ * floating overlay sized by `heightPct` actually gets.
1686
+ */
1687
+ getScreenSize(): ScreenSize;
1688
+ /**
1505
1689
  * List every split with its active buffer and viewport.
1506
1690
  *
1507
1691
  * Plugins that need to operate on every visible buffer
@@ -1585,6 +1769,27 @@ interface EditorAPI {
1585
1769
  */
1586
1770
  openFileInSplit(splitId: number, path: string, line: number, column: number): boolean;
1587
1771
  /**
1772
+ * Open `path` as a regular buffer in forced large-file (file-backed)
1773
+ * mode. The file is created (empty) if missing — designed for
1774
+ * buffers that will be filled by a concurrent `spawnProcess` with
1775
+ * `stdoutTo`. Resolves with the new buffer's id, or `null` on
1776
+ * failure.
1777
+ *
1778
+ * Pair with `refreshBufferFromDisk` to grow the buffer as the
1779
+ * streaming write advances.
1780
+ */
1781
+ openFileStreaming(path: string): Promise<number | null>;
1782
+ /**
1783
+ * Re-stat the file backing `bufferId` and extend the buffer if the
1784
+ * file has grown. Resolves with the new total byte length, or
1785
+ * `null` if the buffer has no file path or doesn't exist.
1786
+ *
1787
+ * Used to drive a streaming display: while a `spawnProcess` writes
1788
+ * to a temp file, the plugin polls this on a timer so the buffer
1789
+ * length tracks the file length.
1790
+ */
1791
+ refreshBufferFromDisk(bufferId: number): Promise<number | null>;
1792
+ /**
1588
1793
  * Show a buffer in the current split
1589
1794
  */
1590
1795
  showBuffer(bufferId: number): boolean;
@@ -1593,6 +1798,30 @@ interface EditorAPI {
1593
1798
  */
1594
1799
  closeBuffer(bufferId: number): boolean;
1595
1800
  /**
1801
+ * Close other buffers in split
1802
+ */
1803
+ closeOtherBuffersInSplit(bufferId: number, splitId: number): boolean;
1804
+ /**
1805
+ * Close all buffers in split
1806
+ */
1807
+ closeAllBuffersInSplit(splitId: number): boolean;
1808
+ /**
1809
+ * Close buffers to right in split
1810
+ */
1811
+ closeBuffersToRightInSplit(bufferId: number, splitId: number): boolean;
1812
+ /**
1813
+ * Close buffers to left in split
1814
+ */
1815
+ closeBuffersToLeftInSplit(bufferId: number, splitId: number): boolean;
1816
+ /**
1817
+ * Move the active tab to the left in the active split
1818
+ */
1819
+ moveTabToLeft(): boolean;
1820
+ /**
1821
+ * Move the active tab to the right in the active split
1822
+ */
1823
+ moveTabToRight(): boolean;
1824
+ /**
1596
1825
  * Start a frame-buffer animation over an arbitrary screen region.
1597
1826
  * Returns an animation id usable with `cancelAnimation`.
1598
1827
  */
@@ -1635,6 +1864,41 @@ interface EditorAPI {
1635
1864
  */
1636
1865
  getAuthorityLabel(): string;
1637
1866
  /**
1867
+ * Current Workspace Trust level for the active project:
1868
+ * `"restricted"`, `"trusted"`, or `"blocked"` (empty `""` when trust
1869
+ * state is unavailable, e.g. the default local authority).
1870
+ *
1871
+ * Trust is a per-project, user-granted decision. Plugins that run
1872
+ * repo-controlled work (env activation, project tooling, repo-local
1873
+ * binaries) MUST gate on this and treat anything other than
1874
+ * `"trusted"` as "do not execute".
1875
+ */
1876
+ workspaceTrustLevel(): "restricted" | "trusted" | "blocked" | "";
1877
+ /**
1878
+ * Activate an environment by setting the live env recipe: an activation
1879
+ * shell `snippet` (e.g. `eval "$(direnv export bash)"`,
1880
+ * `source .venv/bin/activate`, or `""` for a pure login shell) run in
1881
+ * `dir` (defaults to the workspace). It is re-evaluated on demand on the
1882
+ * active backend and applied to every spawn — language servers,
1883
+ * formatters, `spawnProcess` — so they see the project environment. No
1884
+ * authority rebuild; the LSP is restarted to pick it up.
1885
+ *
1886
+ * Honored only when `workspaceTrustLevel() === "trusted"` (it runs
1887
+ * repo-controlled code). Call `clearEnv()` to deactivate.
1888
+ */
1889
+ setEnv(snippet: string, dir?: string): void;
1890
+ /**
1891
+ * Deactivate the environment set by `setEnv` — spawns return to the
1892
+ * inherited environment.
1893
+ */
1894
+ clearEnv(): void;
1895
+ /**
1896
+ * Whether an environment is currently active (a recipe was set via
1897
+ * `setEnv`). Survives the restart `setEnv` triggers, so a plugin can
1898
+ * re-establish its file watch and reflect activation after reloading.
1899
+ */
1900
+ envActive(): boolean;
1901
+ /**
1638
1902
  * Join path components (variadic - accepts multiple string arguments)
1639
1903
  * Always uses forward slashes for cross-platform consistency (like Node.js path.posix.join)
1640
1904
  *
@@ -1750,6 +2014,64 @@ interface EditorAPI {
1750
2014
  */
1751
2015
  getUserConfig(): unknown;
1752
2016
  /**
2017
+ * Declare a boolean config field for the calling plugin.
2018
+ *
2019
+ * Validates `options` synchronously: the JS call throws if any
2020
+ * unknown key is present or if `default` isn't a boolean. The
2021
+ * Settings UI grows a "Plugin Settings → <plugin>" sub-category
2022
+ * containing a toggle for this field. Returns the current value
2023
+ * (user-set if present, otherwise the declared `default`).
2024
+ */
2025
+ defineConfigBoolean(name: string, options: {
2026
+ default: boolean;
2027
+ description?: string;
2028
+ }): boolean;
2029
+ /**
2030
+ * Declare an integer config field for the calling plugin. Throws on
2031
+ * invalid options or if the default falls outside `minimum/maximum`.
2032
+ */
2033
+ defineConfigInteger(name: string, options: {
2034
+ default: number;
2035
+ description?: string;
2036
+ minimum?: number;
2037
+ maximum?: number;
2038
+ }): number;
2039
+ /**
2040
+ * Declare a floating-point number config field. Throws on bad
2041
+ * options or default outside `minimum/maximum`.
2042
+ */
2043
+ defineConfigNumber(name: string, options: {
2044
+ default: number;
2045
+ description?: string;
2046
+ minimum?: number;
2047
+ maximum?: number;
2048
+ }): number;
2049
+ /**
2050
+ * Declare a free-form string config field.
2051
+ */
2052
+ defineConfigString(name: string, options: {
2053
+ default: string;
2054
+ description?: string;
2055
+ }): string;
2056
+ /**
2057
+ * Declare an array-of-strings config field (e.g. a list of
2058
+ * patterns). The Settings UI renders this as a list editor.
2059
+ */
2060
+ defineConfigStringArray(name: string, options: {
2061
+ default: string[];
2062
+ description?: string;
2063
+ }): string[];
2064
+ /**
2065
+ * Get the calling plugin's settings as a JS object.
2066
+ *
2067
+ * Returns the merged value at `config.plugins.<plugin_name>.settings`.
2068
+ * The shape comes from whatever the plugin declared via
2069
+ * `editor.definePluginConfig(...)` (defaults pre-populated by the
2070
+ * host, user overrides on top from the Settings UI). Returns `null`
2071
+ * if the plugin hasn't declared a schema and has no user-set value.
2072
+ */
2073
+ getPluginConfig(): unknown;
2074
+ /**
1753
2075
  * Reload configuration from file
1754
2076
  */
1755
2077
  reloadConfig(): void;
@@ -1972,6 +2294,21 @@ interface EditorAPI {
1972
2294
  */
1973
2295
  clearFolds(bufferId: number): boolean;
1974
2296
  /**
2297
+ * Publish a set of toggleable fold ranges on the buffer. Same
2298
+ * shape an LSP `foldingRange` response would take. Unlike
2299
+ * `addFold`, this does *not* pre-collapse anything — the
2300
+ * standard fold-toggle keybinding finds the range under the
2301
+ * cursor and collapses or expands it on demand. Replacing call
2302
+ * replaces the prior set.
2303
+ *
2304
+ * `ranges` is a JS array of objects shaped
2305
+ * `{ startLine, endLine, kind? }` (lines are 0-indexed).
2306
+ * `kind` is one of `"comment"`, `"imports"`, `"region"` per
2307
+ * the LSP spec; omitted/unknown values are accepted as plain
2308
+ * folds.
2309
+ */
2310
+ setFoldingRanges(bufferId: number, rangesArr: Record<string, unknown>[]): boolean;
2311
+ /**
1975
2312
  * Add a soft break point for marker-based line wrapping
1976
2313
  */
1977
2314
  addSoftBreak(bufferId: number, namespace: string, position: number, indent: number): boolean;
@@ -2046,6 +2383,13 @@ interface EditorAPI {
2046
2383
  * theme-key string (e.g. `"editor.line_number_fg"`). Theme keys
2047
2384
  * are resolved at render time so the line follows theme changes.
2048
2385
  * Both default to `null` (no foreground / transparent background).
2386
+ * * `gutterGlyph` — optional single character (any short string)
2387
+ * rendered in the line-number column on this virtual line's
2388
+ * first visual row. Use to mark e.g. a deletion line with "-"
2389
+ * so the indicator sits next to the deleted content instead
2390
+ * of on the following source line.
2391
+ * * `gutterColor` — color for `gutterGlyph`, same shape as
2392
+ * `fg`/`bg`. Falls back to the theme's line-number fg.
2049
2393
  */
2050
2394
  addVirtualLine(bufferId: number, position: number, text: string, options: Record<string, unknown>, above: boolean, namespace: string, priority: number): boolean;
2051
2395
  /**
@@ -2409,6 +2753,15 @@ interface EditorAPI {
2409
2753
  */
2410
2754
  focusBufferGroupPanel(groupId: number, panelName: string): boolean;
2411
2755
  /**
2756
+ * Re-point a buffer-group's panel at a different buffer id.
2757
+ *
2758
+ * Streaming plugins (e.g. git-log) allocate one file-backed
2759
+ * buffer per item and call this on navigation to swap which
2760
+ * buffer the panel displays — instead of mutating a single
2761
+ * shared buffer's contents. Resolves with `true` on success.
2762
+ */
2763
+ setBufferGroupPanelBuffer(groupId: number, panelName: string, bufferId: number): Promise<boolean>;
2764
+ /**
2412
2765
  * Set virtual buffer content (takes array of entry objects)
2413
2766
  *
2414
2767
  * Note: entries should be TextPropertyEntry[] - uses manual parsing for HashMap support
@@ -2474,8 +2827,13 @@ interface EditorAPI {
2474
2827
  unmountFloatingWidget(panelId: number): boolean;
2475
2828
  /**
2476
2829
  * Spawn a process (async, returns request_id)
2830
+ *
2831
+ * Optional 4th argument `stdoutTo: string` pipes the child's stdout
2832
+ * directly into the named file instead of buffering it. The
2833
+ * resolved `SpawnResult.stdout` is empty in that case; the bytes
2834
+ * land on disk for `openFile` to pick up as a file-backed buffer.
2477
2835
  */
2478
- spawnProcess(command: string, args: string[], cwd?: string): ProcessHandle<SpawnResult>;
2836
+ spawnProcess(command: string, args: string[], cwd?: string, stdoutTo?: string): ProcessHandle<SpawnResult>;
2479
2837
  /**
2480
2838
  * Spawn a process on the host regardless of the active authority.
2481
2839
  *
@@ -2527,6 +2885,19 @@ interface EditorAPI {
2527
2885
  */
2528
2886
  clearRemoteIndicatorState(): void;
2529
2887
  /**
2888
+ * Fetch a URL over HTTP(S) and stream the response body into `target_path`.
2889
+ *
2890
+ * Resolves with a `SpawnResult`-shaped value: `exit_code` is `0` on a
2891
+ * 2xx response (file written), the HTTP status code on non-2xx
2892
+ * (target file untouched), and `-1` on transport errors. `stderr`
2893
+ * carries an error message in the non-success cases; `stdout` is
2894
+ * always empty.
2895
+ *
2896
+ * This uses the editor's built-in HTTP client (`ureq`), so plugins
2897
+ * don't need `curl`/`wget` on PATH.
2898
+ */
2899
+ httpFetch(url: string, targetPath: string): ProcessHandle<SpawnResult>;
2900
+ /**
2530
2901
  * Wait for a process to complete and get its result (async)
2531
2902
  */
2532
2903
  spawnProcessWait(processId: number): Promise<SpawnResult>;
@@ -2579,6 +2950,14 @@ interface EditorAPI {
2579
2950
  */
2580
2951
  createTerminal(opts?: CreateTerminalOptions): Promise<TerminalResult>;
2581
2952
  /**
2953
+ * Create a new editor window seeded with an agent terminal as
2954
+ * its only buffer. Atomic — replaces the legacy
2955
+ * `createWindow` + `setActiveWindow` + `createTerminal`
2956
+ * chain that left a transient `[No Name]` tab alongside the
2957
+ * agent terminal.
2958
+ */
2959
+ createWindowWithTerminal(opts: CreateWindowWithTerminalOptions): Promise<SessionWithTerminalResult>;
2960
+ /**
2582
2961
  * Send input data to a terminal
2583
2962
  */
2584
2963
  sendTerminalInput(terminalId: number, data: string): boolean;
@@ -2635,6 +3014,33 @@ interface EditorAPI {
2635
3014
  getPluginApi<K extends keyof FreshPluginRegistry>(name: K): FreshPluginRegistry[K] | null;
2636
3015
  }
2637
3016
  /**
3017
+ * Typed overload of `editor.defineConfigEnum`. The macro-generated
3018
+ * signature can't express `<E extends string>` propagating from the
3019
+ * `values` array into the return type, so it's declared here. Use
3020
+ * `as const` on the `values` array to get a literal-union return:
3021
+ *
3022
+ * ```ts
3023
+ * const mode = editor.defineConfigEnum("mode", {
3024
+ * values: ["normal", "insert"] as const,
3025
+ * default: "normal",
3026
+ * });
3027
+ * mode; // typed as "normal" | "insert"
3028
+ * ```
3029
+ *
3030
+ * Typed overload of `editor.getPluginConfig`. Plugins that declared
3031
+ * their fields via `defineConfigX` can pass the shape type explicitly:
3032
+ * `editor.getPluginConfig<{ autoEnable: boolean; ... }>()`. Without
3033
+ * the generic, falls back to `unknown`.
3034
+ */
3035
+ interface EditorAPI {
3036
+ defineConfigEnum<E extends string>(name: string, options: {
3037
+ values: readonly E[];
3038
+ default: NoInfer<E>;
3039
+ description?: string;
3040
+ }): E;
3041
+ getPluginConfig<T = unknown>(): T;
3042
+ }
3043
+ /**
2638
3044
  * Maps every hook event name to its payload type.
2639
3045
  *
2640
3046
  * Payloads match the flat JSON produced by `hook_args_to_json` on the Rust