deck-plugin-sdk 1.2.0 → 1.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deck-plugin-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Build a plugin for Deck, outside the Deck repository.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/shim/bridge.js CHANGED
@@ -9,6 +9,8 @@ const b = () => {
9
9
  return x;
10
10
  };
11
11
 
12
+ export const agentClis = (...a) => b().agentClis(...a);
13
+ export const agentMcpStatus = (...a) => b().agentMcpStatus(...a);
12
14
  export const askSudoPassword = (...a) => b().askSudoPassword(...a);
13
15
  export const backupExport = (...a) => b().backupExport(...a);
14
16
  export const backupInspect = (...a) => b().backupInspect(...a);
@@ -136,6 +138,9 @@ export const httpSend = (...a) => b().httpSend(...a);
136
138
  export const httpSendAs = (...a) => b().httpSendAs(...a);
137
139
  export const httpSendReply = (...a) => b().httpSendReply(...a);
138
140
  export const importIconPack = (...a) => b().importIconPack(...a);
141
+ export const installAgentHooks = (...a) => b().installAgentHooks(...a);
142
+ export const installAgentMcp = (...a) => b().installAgentMcp(...a);
143
+ export const installAgentSkills = (...a) => b().installAgentSkills(...a);
139
144
  export const installClaudeHooks = (...a) => b().installClaudeHooks(...a);
140
145
  export const installClaudeMcp = (...a) => b().installClaudeMcp(...a);
141
146
  export const installFromRegistry = (...a) => b().installFromRegistry(...a);
@@ -181,6 +186,8 @@ export const readTrackMeta = (...a) => b().readTrackMeta(...a);
181
186
  export const remoteHome = (...a) => b().remoteHome(...a);
182
187
  export const remoteStat = (...a) => b().remoteStat(...a);
183
188
  export const remoteSudoPassword = (...a) => b().remoteSudoPassword(...a);
189
+ export const removeAgentHooks = (...a) => b().removeAgentHooks(...a);
190
+ export const removeAgentMcp = (...a) => b().removeAgentMcp(...a);
184
191
  export const removeClaudeHooks = (...a) => b().removeClaudeHooks(...a);
185
192
  export const removeClaudeMcp = (...a) => b().removeClaudeMcp(...a);
186
193
  export const removeLanguage = (...a) => b().removeLanguage(...a);
package/shim/terminals.js CHANGED
@@ -19,11 +19,13 @@ export const attach = (...a) => t().attach(...a);
19
19
  export const bracketPaste = (...a) => t().bracketPaste(...a);
20
20
  export const clearPane = (...a) => t().clearPane(...a);
21
21
  export const closeLeaf = (...a) => t().closeLeaf(...a);
22
+ export const copyFrom = (...a) => t().copyFrom(...a);
22
23
  export const destroy = (...a) => t().destroy(...a);
23
24
  export const findLeaf = (...a) => t().findLeaf(...a);
24
25
  export const focusPane = (...a) => t().focusPane(...a);
25
26
  export const getInstance = (...a) => t().getInstance(...a);
26
27
  export const getLayout = (...a) => t().getLayout(...a);
28
+ export const hasSelection = (...a) => t().hasSelection(...a);
27
29
  export const insertBeside = (...a) => t().insertBeside(...a);
28
30
  export const isPinned = (...a) => t().isPinned(...a);
29
31
  export const isWorkspaceActive = (...a) => t().isWorkspaceActive(...a);
@@ -44,11 +46,14 @@ export const paneLabel = (...a) => t().paneLabel(...a);
44
46
  export const paneLines = (...a) => t().paneLines(...a);
45
47
  export const paneLocation = (...a) => t().paneLocation(...a);
46
48
  export const pasteInto = (...a) => t().pasteInto(...a);
49
+ export const pasteText = (...a) => t().pasteText(...a);
50
+ export const pasteTextInto = (...a) => t().pasteTextInto(...a);
47
51
  export const publishLayout = (...a) => t().publishLayout(...a);
48
52
  export const queueInput = (...a) => t().queueInput(...a);
49
53
  export const refit = (...a) => t().refit(...a);
50
54
  export const reorderTab = (...a) => t().reorderTab(...a);
51
55
  export const restartPane = (...a) => t().restartPane(...a);
56
+ export const runsLines = (...a) => t().runsLines(...a);
52
57
  export const sendInput = (...a) => t().sendInput(...a);
53
58
  export const setLeafLabel = (...a) => t().setLeafLabel(...a);
54
59
  export const setLeafView = (...a) => t().setLeafView(...a);
package/shim/ui.js CHANGED
@@ -51,11 +51,13 @@ export const collectFiles = (...a) => u().collectFiles(...a);
51
51
  export const conflict = (...a) => u().conflict(...a);
52
52
  export const decodeText = (...a) => u().decodeText(...a);
53
53
  export const dispatch = (...a) => u().dispatch(...a);
54
+ export const forLanguage = (...a) => u().forLanguage(...a);
54
55
  export const formatChord = (...a) => u().formatChord(...a);
55
56
  export const getEditorSettings = (...a) => u().getEditorSettings(...a);
56
57
  export const getOverrides = (...a) => u().getOverrides(...a);
57
58
  export const match = (...a) => u().match(...a);
58
59
  export const mediaKind = (...a) => u().mediaKind(...a);
60
+ export const modelOptionsFor = (...a) => u().modelOptionsFor(...a);
59
61
  export const monacoOptionsFrom = (...a) => u().monacoOptionsFrom(...a);
60
62
  export const normalizeChord = (...a) => u().normalizeChord(...a);
61
63
  export const onKey = (...a) => u().onKey(...a);
@@ -23,7 +23,7 @@ export declare function TimeInput({ value, onChange, className, }: {
23
23
  onChange: (v: string) => void;
24
24
  className?: string;
25
25
  }): import("react").JSX.Element;
26
- export declare function Select(props: React.SelectHTMLAttributes<HTMLSelectElement>): import("react").JSX.Element;
26
+ export declare function Select({ className, ...props }: React.SelectHTMLAttributes<HTMLSelectElement>): import("react").JSX.Element;
27
27
  export declare function PrimaryButton({ children, ...p }: React.ButtonHTMLAttributes<HTMLButtonElement>): import("react").JSX.Element;
28
28
  export declare function GhostButton({ children, ...p }: React.ButtonHTMLAttributes<HTMLButtonElement>): import("react").JSX.Element;
29
29
  /**
@@ -1,6 +1,6 @@
1
1
  // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
2
  import { type DebugTarget } from "./debugtargets";
3
- import type { AccentColor, BgPreset, Density, TermTheme } from "./theme";
3
+ import type { Accent, Background, Density, Palette, TermCustom, TermTheme } from "./theme";
4
4
  /** Open a URL in the default browser. */
5
5
  export declare const openExternal: (url: string) => Promise<void>;
6
6
  export interface AppProc {
@@ -44,12 +44,30 @@ export interface Settings {
44
44
  reduceMotion: boolean;
45
45
  /** The Servers list (hosts from ~/.ssh/config) under the workspace list. */
46
46
  serversList: boolean;
47
+ /** The mouse wheel over a tab bar switches tabs rather than scrolling the bar. */
48
+ tabWheelSwitch: boolean;
49
+ /** Install plugin and language updates at startup instead of only announcing them. */
50
+ pluginAutoUpdate: boolean;
47
51
  soundOnFire: boolean;
48
52
  playerPlacement: "fixed" | "floating";
49
- accent: AccentColor;
50
- bgPreset: BgPreset;
53
+ accent: Accent;
54
+ bgPreset: Background;
55
+ /** The colours of the "custom" background, each "#rrggbb". Kept when a preset is picked, so
56
+ * going back to Custom finds them again. */
57
+ customTheme?: Partial<Palette>;
58
+ /** Custom palettes the user saved by name, shown as cards beside the presets. */
59
+ savedThemes?: {
60
+ id: string;
61
+ name: string;
62
+ palette: Partial<Palette>;
63
+ }[];
64
+ /** The saved theme the custom colours came from, which edits are written back to. */
65
+ savedThemeId?: string;
51
66
  density: Density;
67
+ uiZoom: number;
52
68
  termTheme: TermTheme;
69
+ /** The "custom" terminal theme's colours. Kept when another theme is picked. */
70
+ termCustom?: Partial<TermCustom>;
53
71
  termFont: string;
54
72
  termFontSize: number;
55
73
  termScrollback: number;
@@ -75,6 +93,12 @@ export interface Settings {
75
93
  drawerHidden: string[];
76
94
  /** Drawer tabs left-to-right. Ids missing from it keep their discovery order, after the rest. */
77
95
  drawerOrder: string[];
96
+ /** Which side of the footer each drawer tab and readout sits on, in order (core/footerlayout.ts).
97
+ * Absent until something is moved: drawer tabs left, readouts right, in the orders above. */
98
+ footerLayout?: {
99
+ left: string[];
100
+ right: string[];
101
+ };
78
102
  httpMcpRevealSecrets: boolean;
79
103
  /**
80
104
  * What to call the user: shown to the others when sharing (a Canvas board's cursor and the
@@ -523,6 +547,30 @@ export declare const claudeMcpStatus: () => Promise<string>;
523
547
  export declare const claudeMcpEntry: () => Promise<string>;
524
548
  export declare const installClaudeMcp: () => Promise<string>;
525
549
  export declare const removeClaudeMcp: () => Promise<void>;
550
+ /**
551
+ * The same for any AI coding agent Deck knows: "claude", "codex", "gemini" or "cursor". Each keeps
552
+ * its MCP servers somewhere else (see agentmcp.rs); the status is the same four answers, with
553
+ * "no-node" when nothing could run the server whatever the config says.
554
+ */
555
+ export declare const agentMcpStatus: (agent: string) => Promise<string>;
556
+ export declare const installAgentMcp: (agent: string) => Promise<string>;
557
+ export declare const removeAgentMcp: (agent: string) => Promise<void>;
558
+ /** Deck's hooks for an agent that has them ("claude", "codex"): what the Agents panel and the
559
+ * agent notifications hear from. Merged into the agent's own settings, backed up first. */
560
+ export declare const installAgentHooks: (agent: string) => Promise<void>;
561
+ export declare const removeAgentHooks: (agent: string) => Promise<void>;
562
+ /**
563
+ * Deck's skills (how to use its MCP tools) for an agent that reads skills: "claude" or "codex".
564
+ * Each comes back with what happened to it: "installed", "updated", "current", "kept-yours" (a
565
+ * skill of that name that is not Deck's) or "kept-edited" (Deck's, changed since). Deck only
566
+ * replaces a skill folder it wrote and nobody has edited.
567
+ */
568
+ export declare const installAgentSkills: (agent: string) => Promise<{
569
+ skill: string;
570
+ outcome: string;
571
+ }[]>;
572
+ /** Which agent command-line tools are on PATH: any of claude, codex, gemini, cursor-agent, cursor. */
573
+ export declare const agentClis: () => Promise<string[]>;
526
574
  export declare const removeClaudeHooks: () => Promise<void>;
527
575
  export declare const notifyOs: (title: string, body: string) => Promise<void>;
528
576
  export declare const gitStatus: (dir: string) => Promise<GitStatusRow[]>;
@@ -1,5 +1,11 @@
1
1
  // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
2
  import type * as MonacoNS from "monaco-editor";
3
+ /** What a language may set differently from the editor-wide value. Absent means "as everywhere". */
4
+ export interface LanguageOverride {
5
+ tabSize?: number;
6
+ insertSpaces?: boolean;
7
+ formatOnSave?: boolean;
8
+ }
3
9
  export interface EditorSettings {
4
10
  fontSize: number;
5
11
  fontFamily: string;
@@ -38,9 +44,32 @@ export interface EditorSettings {
38
44
  mouseWheelZoom: boolean;
39
45
  autoClosingBrackets: boolean;
40
46
  autoClosingQuotes: boolean;
47
+ /** When a file writes itself to disk. Off (the default) means only Ctrl+S saves. */
48
+ autoSave: "off" | "afterDelay" | "onFocusChange";
41
49
  autoSaveDelay: number;
42
50
  trimTrailingWhitespace: boolean;
43
51
  formatOnSave: boolean;
52
+ formatOnPaste: boolean;
53
+ /** Completion: popping up while typing, on a trigger character like ".", and what Enter does. */
54
+ quickSuggestions: boolean;
55
+ suggestOnTriggerCharacters: boolean;
56
+ acceptSuggestionOnEnter: "on" | "smart" | "off";
57
+ snippetSuggestions: "top" | "bottom" | "inline" | "none";
58
+ /** Renaming an HTML/JSX tag renames its closing tag as you type. */
59
+ linkedEditing: boolean;
60
+ /** Lines kept visible above and below the cursor when it moves near an edge. */
61
+ cursorSurroundingLines: number;
62
+ multiCursorModifier: "alt" | "ctrlCmd";
63
+ /** Copy or cut with nothing selected takes the whole line. */
64
+ emptySelectionClipboard: boolean;
65
+ /** The file tree: names or globs to hide (comma-separated), dotfiles, following the open file. */
66
+ treeHide: string;
67
+ treeShowDotfiles: boolean;
68
+ treeFollowActive: boolean;
69
+ /** The folders above what is in view stay pinned at the top of the tree while it scrolls. */
70
+ treeStickyScroll: boolean;
71
+ /** Per-language overrides, keyed by Monaco language id ("python", "typescript"). */
72
+ languageOverrides: Record<string, LanguageOverride>;
44
73
  formatLineLength: number;
45
74
  inlineErrors: boolean;
46
75
  inlineBlame: boolean;
@@ -66,4 +95,17 @@ export declare function getEditorSettings(): EditorSettings;
66
95
  /** For a store outside React that reacts to a setting (lsp.ts re-asks for inlay hints). */
67
96
  export declare function subscribeEditorSettings(cb: () => void): () => void;
68
97
  export declare function useEditorSettings(): EditorSettings;
98
+ /** A language's own value for each overridable setting, else the editor-wide one. */
99
+ export declare function forLanguage(s: EditorSettings, languageId: string | undefined): {
100
+ tabSize: number;
101
+ insertSpaces: boolean;
102
+ formatOnSave: boolean;
103
+ };
104
+ /** The model options for a file of `languageId`. */
105
+ export declare function modelOptionsFor(s: EditorSettings, languageId: string | undefined): {
106
+ tabSize: number;
107
+ insertSpaces: boolean;
108
+ };
109
+ /** Whether the file tree shows an entry, under these settings (core/treehide.ts). */
110
+ export declare const treeShows: (s: EditorSettings, name: string) => boolean;
69
111
  export declare function monacoOptionsFrom(s: EditorSettings): MonacoNS.editor.IEditorOptions;
@@ -1,193 +1,195 @@
1
- // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
- import { monaco } from "./monaco";
3
- /** How to launch the server — passed straight to Rust, which implements the strategies. */
4
- interface ServerSpec {
5
- /** "path" | "node-module" | "exe-search" — see resolve_server() in lsp.rs. */
6
- strategy: string;
7
- command?: string;
8
- module?: string;
9
- args?: string[];
10
- /** How to install the server, for the Install button in Settings › Languages. */
11
- install?: Install;
12
- }
13
- /**
14
- * What to install for a server or a debugger, as one of a few kinds Deck turns into a command
15
- * itself (tools.rs): a definition from the registry never names a command to run.
16
- */
17
- export type InstallSpec = {
18
- kind: "pip" | "npm";
19
- packages: string[];
20
- } | {
21
- kind: "github-release";
22
- name: string;
23
- repo: string;
24
- tag: string;
25
- asset: string;
26
- sha256: string;
27
- };
28
- /** A structured install, or a sentence for what Deck cannot install itself (an SDK). */
29
- export type Install = InstallSpec | string;
30
- /** An install as one sentence, for where a button would not fit or there is nothing to run. */
31
- export declare function installText(i: Install): string;
32
- /** Whether Deck can run it (an Install button), rather than only describe it. */
33
- export declare const canInstall: (i: Install | undefined) => i is InstallSpec;
34
- /** A language's server or debugger install entry, if its definition has one. */
35
- export declare function installFor(languageId: string, what: "server" | "debug"): Install | undefined;
36
- /** A language's debug adapter, or null when its definition names none (or there is no such language). */
37
- export declare function debugAdapterFor(languageId: string): {
38
- adapter: ServerSpec;
39
- type: string;
40
- rootMarker: string;
41
- launch?: Record<string, unknown>;
42
- launchUnless?: string;
43
- install?: Install;
44
- } | null;
45
- /**
46
- * Whether a language's debug adapter runs on this machine: starts it and sees whether it is still
47
- * running a moment later. Resolves to what was run, rejects with why not (the adapter's first line
48
- * of output: Python's "No module named debugpy", Node's "Cannot find module"). Null when the
49
- * language names no adapter.
50
- */
51
- export declare function probeDebugger(languageId: string): Promise<string | null>;
52
- /**
53
- * Load every language definition from %APPDATA%\Deck\languages.
54
- *
55
- * This is the ONLY source of languages. Deck used to compile a few in from src/languages/, which
56
- * meant the shipped ones and a user's own obeyed different rules — one needed a rebuild to
57
- * change, the other a restart, and only the first could carry snippets. Now there is one kind of
58
- * language definition, and Deck ships none: an empty folder means Monaco's own highlighting and
59
- * no language server, which is a coherent state rather than a broken one.
60
- *
61
- * Never rejects. A language that fails to load is one language that does not work; it is not a
62
- * reason for the editor not to start, and the same contract loadPlugins states.
63
- */
64
- export declare function loadExternalLanguages(): Promise<void>;
65
- /** One language, as Settings lists it. Flattened from its LangDef — the panel shows what a
66
- * definition claims, not the definition itself. */
67
- export interface LoadedLanguage {
68
- languageId: string;
69
- serverId: string;
70
- extensions: string[];
71
- rootMarker: string;
72
- strategy: string;
73
- /** The command or node module the strategy will look for. */
74
- command: string;
75
- /** The folder it came from, which is the name to look for on disk. */
76
- folder: string;
77
- /** language.json's version, or "" when it has none (a pack from before versions). */
78
- version: string;
79
- /** Its lucide icon name and colour from language.json; "" when it names none. */
80
- icon: string;
81
- color: string;
82
- snippets?: number;
83
- }
84
- export interface LanguageError {
85
- folder: string;
86
- message: string;
87
- }
88
- /** Every language definition that loaded. */
89
- export declare function loadedLanguages(): readonly LoadedLanguage[];
90
- /**
91
- * Re-read the languages folder whenever it changes on disk. Called once at startup.
92
- *
93
- * What makes installing a language from the registry take effect without a restart, the same way
94
- * the plugin watcher does for a plugin. Debounced: writing a definition and its snippets emits
95
- * several events, and each would otherwise re-read the whole folder.
96
- *
97
- * Only NEW definitions and changed data are picked up. A language whose server is already
98
- * running keeps that session — lsp.rs owns it, and restarting one because a snippet file changed
99
- * would lose whatever it had analysed.
100
- */
101
- export declare function watchLanguages(): void;
102
- /**
103
- * Whether a language's server is actually installed, without opening a file of that type.
104
- *
105
- * Until this existed, a definition naming a server you do not have was only discoverable by
106
- * opening such a file and reading the error — so "Python needs basedpyright installed" was
107
- * something Deck knew and never said.
108
- *
109
- * `root` is optional and usually empty: a node module resolves from the project's node_modules
110
- * first, so a check with no project answers "is it installed globally".
111
- */
112
- export declare function probeLanguage(languageId: string, root?: string): Promise<string>;
113
- /**
114
- * Folders that failed to load, and why.
115
- *
116
- * The point of surfacing these: a definition with a typo is otherwise completely silent — the
117
- * language simply does not work, with nothing on screen to say a file was even read.
118
- */
119
- export declare function languageErrors(): readonly LanguageError[];
120
- export declare function lspSupports(languageId: string): boolean;
121
- export type LspPhase = "starting" | "ready" | "error" | "stopped";
122
- export interface LspStatus {
123
- id: string;
124
- serverId: string;
125
- root: string;
126
- phase: LspPhase;
127
- detail: string;
128
- log: string[];
129
- }
130
- /** React hook: current LSP server statuses (for the editor indicator). */
131
- export declare function useLspStatus(): LspStatus[];
132
- export declare function lspErrorVersion(): number;
133
- /** Live path -> error count. Read after subscribing to changes with subscribeLspErrors. */
134
- export declare function lspErrorCounts(): Map<string, number>;
135
- export declare function subscribeLspErrors(cb: () => void): () => void;
136
- /** Notify the server a document is open. Call when a file tab opens. */
137
- export declare function lspOpenDoc(path: string, content: string, root: string): Promise<void>;
138
- /**
139
- * Notify the server a document changed. Call for EVERY Monaco change, synchronously — no
140
- * debounce.
141
- *
142
- * Under incremental sync each notification describes one edit relative to the server's current
143
- * copy, so dropping or reordering any of them desynchronizes the document permanently. That is
144
- * also why this is no longer debounced: a debounce necessarily drops intermediate states, which
145
- * is only legal when every message carries the whole file. Sending immediately has the better
146
- * property anyway — completion and hover fire on the keystroke, so under the old 300ms debounce
147
- * they queried a server whose buffer was up to 300ms stale and answered for a position that did
148
- * not exist there yet.
149
- *
150
- * `changes` comes straight from Monaco's content-change event. Its ranges are in pre-edit
151
- * coordinates and it orders them end-of-document first, which is exactly what LSP expects for a
152
- * sequentially-applied batch: applying a later-in-document edit never shifts an earlier range.
153
- * Do not sort them.
154
- */
155
- export declare function lspChangeDoc(path: string, content: string, root: string, changes?: readonly monaco.editor.IModelContentChange[]): Promise<void>;
156
- /** Notify the server a document closed. Call when a tab closes. */
157
- export declare function lspCloseDoc(path: string, root: string): Promise<void>;
158
- /** One result of a project-wide symbol search (Ctrl+T). `line` and `col` are 1-based. */
159
- export interface ProjectSymbol {
160
- name: string;
161
- kind: number;
162
- container: string;
163
- path: string;
164
- line: number;
165
- col: number;
166
- }
167
- /**
168
- * Classes, functions and the rest whose name matches `query`, from every language server running
169
- * for `root` (a TypeScript and a Python server can share one), each server's own ranking kept and
170
- * the lists joined. Only servers already running answer: Ctrl+T does not start one. [] for an
171
- * empty query.
172
- */
173
- export declare function workspaceSymbols(root: string, query: string): Promise<ProjectSymbol[]>;
174
- /** A file's outline from its language server, or [] when no server has it open. Also what the
175
- * debugger's inline values use to find the function a frame is in. */
176
- export declare function documentSymbols(model: monaco.editor.ITextModel): Promise<monaco.languages.DocumentSymbol[]>;
177
- type OpenFileHandler = (path: string, line: number, column: number) => void;
178
- export declare function setLspOpenFileHandler(fn: OpenFileHandler): void;
179
- /** Stop the servers no project has touched for IDLE_STOP_MS. Exported for the check. */
180
- export declare function stopIdleServers(now?: number): string[];
181
- /** Stop all sessions (e.g. on workspace close). */
182
- export declare function lspStopAll(): void;
183
- /** Restart one server (UI action from the status popover). */
184
- /**
185
- * Stop a language server. The next file opened for that root starts a fresh one, which is why
186
- * this is both the Restart action and the memory readout's stop button — there is no difference
187
- * between the two beyond what the caller says about it.
188
- *
189
- * Deleting the frontend session alongside the process matters: leaving it would send didOpen to
190
- * a dead pipe on the next open, and the editor would sit at "ready" with no diagnostics.
191
- */
192
- export declare function lspRestart(id: string): Promise<void>;
193
- export {};
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ import { monaco } from "./monaco";
3
+ /** How to launch the server — passed straight to Rust, which implements the strategies. */
4
+ interface ServerSpec {
5
+ /** "path" | "node-module" | "exe-search" — see resolve_server() in lsp.rs. */
6
+ strategy: string;
7
+ command?: string;
8
+ module?: string;
9
+ args?: string[];
10
+ /** How to install the server, for the Install button in Settings › Languages. */
11
+ install?: Install;
12
+ }
13
+ /**
14
+ * What to install for a server or a debugger, as one of a few kinds Deck turns into a command
15
+ * itself (tools.rs): a definition from the registry never names a command to run.
16
+ */
17
+ export type InstallSpec = {
18
+ kind: "pip" | "npm";
19
+ packages: string[];
20
+ } | {
21
+ kind: "github-release";
22
+ name: string;
23
+ repo: string;
24
+ tag: string;
25
+ asset: string;
26
+ sha256: string;
27
+ };
28
+ /** A structured install, or a sentence for what Deck cannot install itself (an SDK). */
29
+ export type Install = InstallSpec | string;
30
+ /** An install as one sentence, for where a button would not fit or there is nothing to run. */
31
+ export declare function installText(i: Install): string;
32
+ /** Whether Deck can run it (an Install button), rather than only describe it. */
33
+ export declare const canInstall: (i: Install | undefined) => i is InstallSpec;
34
+ /** A language's server or debugger install entry, if its definition has one. */
35
+ export declare function installFor(languageId: string, what: "server" | "debug"): Install | undefined;
36
+ /** A language's debug adapter, or null when its definition names none (or there is no such language). */
37
+ export declare function debugAdapterFor(languageId: string): {
38
+ adapter: ServerSpec;
39
+ type: string;
40
+ rootMarker: string;
41
+ launch?: Record<string, unknown>;
42
+ launchUnless?: string;
43
+ install?: Install;
44
+ } | null;
45
+ /**
46
+ * Whether a language's debug adapter runs on this machine: starts it and sees whether it is still
47
+ * running a moment later. Resolves to what was run, rejects with why not (the adapter's first line
48
+ * of output: Python's "No module named debugpy", Node's "Cannot find module"). Null when the
49
+ * language names no adapter.
50
+ */
51
+ export declare function probeDebugger(languageId: string): Promise<string | null>;
52
+ /**
53
+ * Load every language definition from %APPDATA%\Deck\languages.
54
+ *
55
+ * This is the ONLY source of languages. Deck used to compile a few in from src/languages/, which
56
+ * meant the shipped ones and a user's own obeyed different rules — one needed a rebuild to
57
+ * change, the other a restart, and only the first could carry snippets. Now there is one kind of
58
+ * language definition, and Deck ships none: an empty folder means Monaco's own highlighting and
59
+ * no language server, which is a coherent state rather than a broken one.
60
+ *
61
+ * Never rejects. A language that fails to load is one language that does not work; it is not a
62
+ * reason for the editor not to start, and the same contract loadPlugins states.
63
+ */
64
+ export declare function loadExternalLanguages(): Promise<void>;
65
+ /** One language, as Settings lists it. Flattened from its LangDef — the panel shows what a
66
+ * definition claims, not the definition itself. */
67
+ export interface LoadedLanguage {
68
+ languageId: string;
69
+ serverId: string;
70
+ extensions: string[];
71
+ rootMarker: string;
72
+ strategy: string;
73
+ /** The command or node module the strategy will look for. */
74
+ command: string;
75
+ /** The folder it came from, which is the name to look for on disk. */
76
+ folder: string;
77
+ /** language.json's version, or "" when it has none (a pack from before versions). */
78
+ version: string;
79
+ /** Its lucide icon name and colour from language.json; "" when it names none. */
80
+ icon: string;
81
+ color: string;
82
+ snippets?: number;
83
+ }
84
+ export interface LanguageError {
85
+ folder: string;
86
+ message: string;
87
+ }
88
+ export declare function subscribeLanguages(fn: () => void): () => void;
89
+ export declare function languagesVersion(): number;
90
+ /** Every language definition that loaded. */
91
+ export declare function loadedLanguages(): readonly LoadedLanguage[];
92
+ /**
93
+ * Re-read the languages folder whenever it changes on disk. Called once at startup.
94
+ *
95
+ * What makes installing a language from the registry take effect without a restart, the same way
96
+ * the plugin watcher does for a plugin. Debounced: writing a definition and its snippets emits
97
+ * several events, and each would otherwise re-read the whole folder.
98
+ *
99
+ * Only NEW definitions and changed data are picked up. A language whose server is already
100
+ * running keeps that session — lsp.rs owns it, and restarting one because a snippet file changed
101
+ * would lose whatever it had analysed.
102
+ */
103
+ export declare function watchLanguages(): void;
104
+ /**
105
+ * Whether a language's server is actually installed, without opening a file of that type.
106
+ *
107
+ * Until this existed, a definition naming a server you do not have was only discoverable by
108
+ * opening such a file and reading the error — so "Python needs basedpyright installed" was
109
+ * something Deck knew and never said.
110
+ *
111
+ * `root` is optional and usually empty: a node module resolves from the project's node_modules
112
+ * first, so a check with no project answers "is it installed globally".
113
+ */
114
+ export declare function probeLanguage(languageId: string, root?: string): Promise<string>;
115
+ /**
116
+ * Folders that failed to load, and why.
117
+ *
118
+ * The point of surfacing these: a definition with a typo is otherwise completely silent — the
119
+ * language simply does not work, with nothing on screen to say a file was even read.
120
+ */
121
+ export declare function languageErrors(): readonly LanguageError[];
122
+ export declare function lspSupports(languageId: string): boolean;
123
+ export type LspPhase = "starting" | "ready" | "error" | "stopped";
124
+ export interface LspStatus {
125
+ id: string;
126
+ serverId: string;
127
+ root: string;
128
+ phase: LspPhase;
129
+ detail: string;
130
+ log: string[];
131
+ }
132
+ /** React hook: current LSP server statuses (for the editor indicator). */
133
+ export declare function useLspStatus(): LspStatus[];
134
+ export declare function lspErrorVersion(): number;
135
+ /** Live path -> error count. Read after subscribing to changes with subscribeLspErrors. */
136
+ export declare function lspErrorCounts(): Map<string, number>;
137
+ export declare function subscribeLspErrors(cb: () => void): () => void;
138
+ /** Notify the server a document is open. Call when a file tab opens. */
139
+ export declare function lspOpenDoc(path: string, content: string, root: string): Promise<void>;
140
+ /**
141
+ * Notify the server a document changed. Call for EVERY Monaco change, synchronously — no
142
+ * debounce.
143
+ *
144
+ * Under incremental sync each notification describes one edit relative to the server's current
145
+ * copy, so dropping or reordering any of them desynchronizes the document permanently. That is
146
+ * also why this is no longer debounced: a debounce necessarily drops intermediate states, which
147
+ * is only legal when every message carries the whole file. Sending immediately has the better
148
+ * property anyway — completion and hover fire on the keystroke, so under the old 300ms debounce
149
+ * they queried a server whose buffer was up to 300ms stale and answered for a position that did
150
+ * not exist there yet.
151
+ *
152
+ * `changes` comes straight from Monaco's content-change event. Its ranges are in pre-edit
153
+ * coordinates and it orders them end-of-document first, which is exactly what LSP expects for a
154
+ * sequentially-applied batch: applying a later-in-document edit never shifts an earlier range.
155
+ * Do not sort them.
156
+ */
157
+ export declare function lspChangeDoc(path: string, content: string, root: string, changes?: readonly monaco.editor.IModelContentChange[]): Promise<void>;
158
+ /** Notify the server a document closed. Call when a tab closes. */
159
+ export declare function lspCloseDoc(path: string, root: string): Promise<void>;
160
+ /** One result of a project-wide symbol search (Ctrl+T). `line` and `col` are 1-based. */
161
+ export interface ProjectSymbol {
162
+ name: string;
163
+ kind: number;
164
+ container: string;
165
+ path: string;
166
+ line: number;
167
+ col: number;
168
+ }
169
+ /**
170
+ * Classes, functions and the rest whose name matches `query`, from every language server running
171
+ * for `root` (a TypeScript and a Python server can share one), each server's own ranking kept and
172
+ * the lists joined. Only servers already running answer: Ctrl+T does not start one. [] for an
173
+ * empty query.
174
+ */
175
+ export declare function workspaceSymbols(root: string, query: string): Promise<ProjectSymbol[]>;
176
+ /** A file's outline from its language server, or [] when no server has it open. Also what the
177
+ * debugger's inline values use to find the function a frame is in. */
178
+ export declare function documentSymbols(model: monaco.editor.ITextModel): Promise<monaco.languages.DocumentSymbol[]>;
179
+ type OpenFileHandler = (path: string, line: number, column: number) => void;
180
+ export declare function setLspOpenFileHandler(fn: OpenFileHandler): void;
181
+ /** Stop the servers no project has touched for IDLE_STOP_MS. Exported for the check. */
182
+ export declare function stopIdleServers(now?: number): string[];
183
+ /** Stop all sessions (e.g. on workspace close). */
184
+ export declare function lspStopAll(): void;
185
+ /** Restart one server (UI action from the status popover). */
186
+ /**
187
+ * Stop a language server. The next file opened for that root starts a fresh one, which is why
188
+ * this is both the Restart action and the memory readout's stop button — there is no difference
189
+ * between the two beyond what the caller says about it.
190
+ *
191
+ * Deleting the frontend session alongside the process matters: leaving it would send didOpen to
192
+ * a dead pipe on the next open, and the editor would sit at "ready" with no diagnostics.
193
+ */
194
+ export declare function lspRestart(id: string): Promise<void>;
195
+ export {};
@@ -16,6 +16,7 @@ export declare function setEditorSurface(next: {
16
16
  card: string;
17
17
  elev: string;
18
18
  muted: string;
19
+ text?: string;
19
20
  }): void;
20
21
  /** Merge language-specific semantic-token colors into deck-dark (idempotent per token). */
21
22
  export declare function addSemanticColors(rules: TokenColor[]): void;
@@ -11,6 +11,15 @@ export declare function publishSettings(s: Settings): void;
11
11
  * for the shared half.
12
12
  */
13
13
  export declare function saveSettings(next: Settings): void;
14
+ /** The zoom steps Ctrl+= and Ctrl+- move through, in percent, as a browser's do. */
15
+ export declare const ZOOM_STEPS: number[];
16
+ /**
17
+ * Zoom the whole window: the webview's own zoom, the same as a browser's Ctrl+=, rather than CSS
18
+ * `zoom`, which leaves xterm and Monaco measuring the mouse in unzoomed pixels.
19
+ */
20
+ export declare function applyZoom(pct: number | undefined): void;
21
+ /** One step in or out from the current zoom, or back to 100% with dir 0. Saved like any setting. */
22
+ export declare function stepZoom(dir: -1 | 0 | 1): void;
14
23
  /** Current settings for non-React callers (the palette's providers). */
15
24
  export declare const getSettings: () => Settings;
16
25
  export declare function userName(): Promise<string>;
@@ -318,7 +318,31 @@ export declare function getInstance(id: string): Instance;
318
318
  * smaller writes would only add more seams.
319
319
  */
320
320
  export declare function bracketPaste(text: string, bracketed: boolean): string;
321
- /** Paste the clipboard text into a terminal's PTY (Ctrl+V and the context-menu Paste). */
321
+ /** Whether a terminal has text selected, for its right-click menu's Copy. */
322
+ export declare const hasSelection: (id: string) => boolean;
323
+ /**
324
+ * Copy a terminal's selection, then clear it: with the selection kept, the next Ctrl+C copied
325
+ * again instead of interrupting the program, until something was clicked.
326
+ */
327
+ export declare function copyFrom(id: string): void;
328
+ /**
329
+ * A paste's line breaks as the Enter key sends them. Text copied on Windows carries CRLF, and
330
+ * written raw each line arrived as Enter plus a stray line feed. xterm's own paste does this
331
+ * conversion; Deck writes pastes itself, so it does it here.
332
+ */
333
+ export declare const pasteText: (text: string) => string;
334
+ /**
335
+ * A pasted line break that will run a command: one ending a line, outside a bracketed paste.
336
+ * The shell (PowerShell, cmd) takes each as Enter, so pasting two lines ran the first at once.
337
+ */
338
+ export declare const runsLines: (text: string, bracketed: boolean) => boolean;
339
+ /**
340
+ * Paste text into a terminal: line breaks as Enter, bracketed when the app asked for it, and
341
+ * when it would run lines in a shell that cannot tell a paste from typing, asked first, the way
342
+ * Windows Terminal asks. Focus goes back to the terminal afterwards, as a menu click takes it.
343
+ */
344
+ export declare function pasteTextInto(id: string, text: string): Promise<void>;
345
+ /** Paste the clipboard into a terminal, from its right-click menu (no key event to read). */
322
346
  export declare function pasteInto(id: string): Promise<void>;
323
347
  export declare function attach(id: string, el: HTMLElement, cwd: string): () => void;
324
348
  export declare function queueInput(paneId: string, text: string): void;
@@ -1,6 +1,28 @@
1
1
  // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
2
  export type AccentColor = "violet" | "blue" | "cyan" | "green" | "amber" | "red";
3
+ /** A preset's name, or a custom colour as "#rrggbb". */
4
+ export type Accent = AccentColor | `#${string}`;
3
5
  export type BgPreset = "black" | "slate" | "warm" | "midnight" | "charcoal" | "nord" | "plum" | "dracula" | "forest";
6
+ /** A preset, or "custom": the user's own colours, from `customTheme`. */
7
+ export type Background = BgPreset | "custom";
8
+ /**
9
+ * Every colour a theme sets, so a custom one can set them all: the five surfaces darkest first,
10
+ * and the three text colours. Each is "#rrggbb", which is what a colour picker reads and writes.
11
+ */
12
+ export interface Palette {
13
+ app: string;
14
+ panel: string;
15
+ card: string;
16
+ elev: string;
17
+ hover: string;
18
+ text: string;
19
+ textSecondary: string;
20
+ muted: string;
21
+ /** What is drawn on the accent: a primary button's label, a switch's knob. */
22
+ onAccent: string;
23
+ }
24
+ /** "#rrggbb" as "r g b", the form the rgb(var(--x) / alpha) tokens take. */
25
+ export declare const channels: (hex: string) => string;
4
26
  export type Density = "compact" | "cozy";
5
27
  /** Accent base/strong pairs. Values match the primitives already in tokens.css. */
6
28
  export declare const ACCENTS: Record<AccentColor, {
@@ -27,23 +49,54 @@ export declare const DENSITIES: Record<Density, {
27
49
  scale: number;
28
50
  radius: number;
29
51
  }>;
52
+ /** The colours a background setting resolves to. A custom one missing a colour (or with none
53
+ * saved) takes it from the near-black preset, so a half-filled palette still draws. */
54
+ export declare function paletteOf(bgPreset?: string, custom?: Partial<Palette>): Palette;
55
+ /** Whether a "#rrggbb" background is light: relative luminance over the midpoint. */
56
+ export declare function isLightColor(hex: string): boolean;
57
+ /** Whether an accent is a custom colour rather than a preset's name. */
58
+ export declare const isCustomAccent: (accent?: string) => accent is `#${string}`;
59
+ /**
60
+ * An accent's base and strong colours. A custom one has no hand-picked strong shade, so it is the
61
+ * base mixed toward black, which is what the presets' pairs are. Anything unknown (a preset that
62
+ * was removed) falls back to violet.
63
+ */
64
+ export declare function accentOf(accent?: string): {
65
+ base: string;
66
+ strong: string;
67
+ };
30
68
  /** Apply the three appearance settings to the document. Safe to call repeatedly. */
31
69
  export declare function applyTheme(opts: {
32
- accent?: AccentColor;
33
- bgPreset?: BgPreset;
70
+ accent?: Accent;
71
+ bgPreset?: Background;
72
+ customTheme?: Partial<Palette>;
34
73
  density?: Density;
35
74
  termTheme?: TermTheme;
75
+ termCustom?: Partial<TermCustom>;
36
76
  }): void;
37
77
  /** The values the app starts with, before settings.json has been read. Matches tokens.css. */
38
78
  export declare const DEFAULT_APPEARANCE: {
39
- accent: AccentColor;
40
- bgPreset: BgPreset;
79
+ accent: Accent;
80
+ bgPreset: Background;
41
81
  density: Density;
42
82
  };
43
- export type TermTheme = "match" | "deck" | "dark" | "dimmed" | "solarized";
83
+ export type TermTheme = "match" | "deck" | "dark" | "dimmed" | "solarized" | "custom";
84
+ /** The eight ANSI colours programs print with. Bright variants follow them in a custom theme. */
85
+ export declare const ANSI_KEYS: readonly ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"];
86
+ export type Ansi = Record<(typeof ANSI_KEYS)[number], string>;
87
+ /** xterm's own defaults, which every theme but a custom one leaves in place. */
88
+ export declare const XTERM_ANSI: Ansi;
89
+ /** A custom terminal theme: every colour, each "#rrggbb". */
90
+ export interface TermCustom {
91
+ background: string;
92
+ foreground: string;
93
+ cursor: string;
94
+ selection: string;
95
+ ansi: Ansi;
96
+ }
44
97
  /** Fixed palettes. "match" isn't here — it's derived from the app's accent + background at
45
98
  * resolve time (see termThemeColors), so it changes with those settings. */
46
- export declare const TERM_THEMES: Record<Exclude<TermTheme, "match">, {
99
+ export declare const TERM_THEMES: Record<Exclude<TermTheme, "match" | "custom">, {
47
100
  label: string;
48
101
  background: string;
49
102
  foreground: string;
@@ -55,13 +108,16 @@ export declare const TERM_THEME_LABELS: Record<TermTheme, string>;
55
108
  /** Resolve a terminal theme to concrete colours. "match" follows the app's own appearance: the
56
109
  * card surface as the background (so a terminal reads as part of the panel it sits in) and the
57
110
  * accent as the cursor, so picking a new accent recolours the terminal too. */
58
- export declare function termThemeColors(theme: TermTheme, accent?: AccentColor, bgPreset?: BgPreset): {
111
+ export declare function termThemeColors(theme: TermTheme, accent?: Accent, bgPreset?: Background, custom?: Partial<Palette>, term?: Partial<TermCustom>): {
59
112
  label: string;
60
113
  background: string;
61
114
  foreground: string;
62
115
  cursor: string;
63
116
  selectionBackground: string;
117
+ ansi?: Ansi;
64
118
  };
119
+ /** A custom terminal theme with every colour filled: what is missing comes from the Deck theme. */
120
+ export declare function customTerm(t?: Partial<TermCustom>): TermCustom;
65
121
  export declare const TERM_FONTS: {
66
122
  value: string;
67
123
  label: string;
@@ -0,0 +1,5 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ /** "dist, *.log" as one case-insensitive whole-name pattern each: * is any run, ? one character. */
3
+ export declare function hidePatterns(text: string): RegExp[];
4
+ /** Whether the tree shows an entry named `name`. */
5
+ export declare function treeVisible(name: string, hide: string, dotfiles: boolean): boolean;