deck-plugin-sdk 0.15.1
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/README.md +77 -0
- package/bin/deck-plugin.mjs +117 -0
- package/build-plugin.mjs +143 -0
- package/package.json +42 -0
- package/shim/bridge.d.ts +5 -0
- package/shim/bridge.js +196 -0
- package/shim/event.d.ts +5 -0
- package/shim/event.js +5 -0
- package/shim/jsx-runtime.js +20 -0
- package/shim/mcp.d.ts +68 -0
- package/shim/monaco.d.ts +5 -0
- package/shim/monaco.js +15 -0
- package/shim/react.js +50 -0
- package/shim/settings.d.ts +5 -0
- package/shim/settings.js +13 -0
- package/shim/terminals.d.ts +4 -0
- package/shim/terminals.js +70 -0
- package/shim/ui.d.ts +14 -0
- package/shim/ui.js +37 -0
- package/template/README.md +17 -0
- package/template/gitignore +4 -0
- package/template/package.json +10 -0
- package/template/plugin.json +8 -0
- package/template/src/plugin.tsx +65 -0
- package/template/tsconfig.json +13 -0
- package/types/components/ConfirmDialog.d.ts +22 -0
- package/types/components/ContextMenu.d.ts +41 -0
- package/types/components/MarkdownToolbar.d.ts +48 -0
- package/types/components/NamePrompt.d.ts +16 -0
- package/types/components/TabStrip.d.ts +26 -0
- package/types/components/Toast.d.ts +48 -0
- package/types/components/TreeRow.d.ts +41 -0
- package/types/components/dragrow.d.ts +34 -0
- package/types/components/menuplace.d.ts +30 -0
- package/types/components/ui.d.ts +102 -0
- package/types/components/useResize.d.ts +24 -0
- package/types/core/bridge.d.ts +670 -0
- package/types/core/editorsettings.d.ts +60 -0
- package/types/core/langmap.d.ts +15 -0
- package/types/core/monaco.d.ts +36 -0
- package/types/core/settingsstore.d.ts +19 -0
- package/types/core/shellpath.d.ts +45 -0
- package/types/core/terminals.d.ts +322 -0
- package/types/core/theme.d.ts +68 -0
- package/types/modules/editor/MarkdownLive.d.ts +61 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
import type * as MonacoNS from "monaco-editor";
|
|
3
|
+
export interface EditorSettings {
|
|
4
|
+
fontSize: number;
|
|
5
|
+
fontFamily: string;
|
|
6
|
+
lineHeight: number;
|
|
7
|
+
letterSpacing: number;
|
|
8
|
+
fontLigatures: boolean;
|
|
9
|
+
tabSize: number;
|
|
10
|
+
insertSpaces: boolean;
|
|
11
|
+
wordWrap: "off" | "on" | "bounded";
|
|
12
|
+
wordWrapColumn: number;
|
|
13
|
+
lineNumbers: "on" | "off" | "relative";
|
|
14
|
+
minimap: boolean;
|
|
15
|
+
minimapSide: "right" | "left";
|
|
16
|
+
renderWhitespace: "none" | "boundary" | "selection" | "all";
|
|
17
|
+
indentGuides: boolean;
|
|
18
|
+
bracketPairColorization: boolean;
|
|
19
|
+
stickyScroll: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Markdown: float the formatting bar over the selection instead of pinning it above the note.
|
|
22
|
+
*
|
|
23
|
+
* Lives with the editor's settings rather than the vault plugin's because MarkdownLive is
|
|
24
|
+
* Deck's own component — every surface that shows a note reads this one value.
|
|
25
|
+
*/
|
|
26
|
+
mdFloatingToolbar: boolean;
|
|
27
|
+
renderLineHighlight: "none" | "line" | "gutter" | "all";
|
|
28
|
+
folding: boolean;
|
|
29
|
+
glyphMargin: boolean;
|
|
30
|
+
rulers: string;
|
|
31
|
+
scrollBeyondLastLine: boolean;
|
|
32
|
+
cursorStyle: "line" | "block" | "underline";
|
|
33
|
+
cursorBlinking: "blink" | "smooth" | "phase" | "expand" | "solid";
|
|
34
|
+
smoothCaret: boolean;
|
|
35
|
+
smoothScrolling: boolean;
|
|
36
|
+
mouseWheelZoom: boolean;
|
|
37
|
+
autoClosingBrackets: boolean;
|
|
38
|
+
autoClosingQuotes: boolean;
|
|
39
|
+
autoSaveDelay: number;
|
|
40
|
+
trimTrailingWhitespace: boolean;
|
|
41
|
+
formatOnSave: boolean;
|
|
42
|
+
formatLineLength: number;
|
|
43
|
+
inlineErrors: boolean;
|
|
44
|
+
inlineBlame: boolean;
|
|
45
|
+
aiCommitCommand: string;
|
|
46
|
+
aiCommitArgs: string;
|
|
47
|
+
aiCommitModel: string;
|
|
48
|
+
agentNotify: boolean;
|
|
49
|
+
agentNotifyFinished: boolean;
|
|
50
|
+
agentNotifyNeedsInput: boolean;
|
|
51
|
+
agentNotifyOsToast: boolean;
|
|
52
|
+
theme: "deck-dark" | "vs-dark" | "hc-black";
|
|
53
|
+
iconTheme: string;
|
|
54
|
+
diffSideBySide: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare const DEFAULT_EDITOR_SETTINGS: EditorSettings;
|
|
57
|
+
export declare function updateEditorSettings(patch: Partial<EditorSettings>): void;
|
|
58
|
+
export declare function getEditorSettings(): EditorSettings;
|
|
59
|
+
export declare function useEditorSettings(): EditorSettings;
|
|
60
|
+
export declare function monacoOptionsFrom(s: EditorSettings): MonacoNS.editor.IEditorOptions;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
/** Extensions claimed by a language definition, lowercase and without the dot. */
|
|
3
|
+
export type ExtensionClaims = ReadonlyMap<string, string>;
|
|
4
|
+
/**
|
|
5
|
+
* The Monaco language id for a path.
|
|
6
|
+
*
|
|
7
|
+
* Three rules, and the order is the whole point:
|
|
8
|
+
*
|
|
9
|
+
* 1. Files whose NAME is the type and have no extension to split off. `.env.local` must be ini,
|
|
10
|
+
* but splitting on "." sees "local"; dockerfile has no extension at all.
|
|
11
|
+
* 2. Extensions a language definition claimed. These are the ones with a server behind them, so
|
|
12
|
+
* a definition naming an extension takes it over from rule 3.
|
|
13
|
+
* 3. The grammar-only map above.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveLanguage(path: string, claims: ExtensionClaims): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
import * as monaco from "monaco-editor";
|
|
3
|
+
type TokenColor = {
|
|
4
|
+
token: string;
|
|
5
|
+
foreground?: string;
|
|
6
|
+
fontStyle?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Repaint the editor for a new background preset. Called by applyTheme().
|
|
10
|
+
*
|
|
11
|
+
* setTheme is what actually repaints live editors — defineTheme alone only updates the
|
|
12
|
+
* registration, so an open editor would keep the old colours until it was recreated.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setEditorSurface(next: {
|
|
15
|
+
app: string;
|
|
16
|
+
card: string;
|
|
17
|
+
elev: string;
|
|
18
|
+
muted: string;
|
|
19
|
+
}): void;
|
|
20
|
+
/** Merge language-specific semantic-token colors into deck-dark (idempotent per token). */
|
|
21
|
+
export declare function addSemanticColors(rules: TokenColor[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* Claim a file extension for a language. Lowercase, without the dot.
|
|
24
|
+
*
|
|
25
|
+
* Last registration wins, which is what makes a user's own definition able to override a
|
|
26
|
+
* built-in one rather than silently losing to it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function registerExtension(ext: string, languageId: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Map a filename to a Monaco language id.
|
|
31
|
+
*
|
|
32
|
+
* The rule itself is in langmap.ts, which has no Monaco import and so can be tested; this only
|
|
33
|
+
* supplies the extensions language definitions have claimed.
|
|
34
|
+
*/
|
|
35
|
+
export declare function languageForPath(path: string): string;
|
|
36
|
+
export { monaco };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
import { type Settings } from "./bridge";
|
|
3
|
+
/** Called by Settings after every write, so readers update without a reload. */
|
|
4
|
+
export declare function publishSettings(s: Settings): void;
|
|
5
|
+
/**
|
|
6
|
+
* Write settings and apply everything that has to happen alongside the write.
|
|
7
|
+
*
|
|
8
|
+
* Settings' own persist() used to be the only path, so anything outside that module (the
|
|
9
|
+
* command palette toggling relay, say) would have had to repeat five steps and would break
|
|
10
|
+
* quietly when one of them changed. Settings still owns its local form state and calls this
|
|
11
|
+
* for the shared half.
|
|
12
|
+
*/
|
|
13
|
+
export declare function saveSettings(next: Settings): void;
|
|
14
|
+
/** Current settings for non-React callers (the palette's providers). */
|
|
15
|
+
export declare const getSettings: () => Settings;
|
|
16
|
+
/** The OS account name — the home directory's last segment. "" if it can't be read. */
|
|
17
|
+
export declare function osAccountName(): Promise<string>;
|
|
18
|
+
export declare function userName(): Promise<string>;
|
|
19
|
+
export declare function useSettings(): Settings;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
/** Quote a path for a shell only when it needs it, so the common case stays readable. */
|
|
3
|
+
export declare function quotePath(p: string): string;
|
|
4
|
+
/** A path found in terminal output, resolved and ready to open. */
|
|
5
|
+
export interface TermPath {
|
|
6
|
+
text: string;
|
|
7
|
+
path: string;
|
|
8
|
+
line?: number;
|
|
9
|
+
start: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Every path CANDIDATE in one row of terminal output, each resolved against `cwd`.
|
|
13
|
+
*
|
|
14
|
+
* A space is both a legal path character and the thing that separates a path from the next word,
|
|
15
|
+
* so "D:\Program Files\Deck" cannot be told from "src/foo.ts and more" by shape alone. Rather
|
|
16
|
+
* than guess, each match is emitted at its shortest extent and then again grown by one
|
|
17
|
+
* space-separated token at a time; `chooseLinks` picks between them once something can say which
|
|
18
|
+
* of those files exists. Candidates that share a `start` are the same match at different lengths.
|
|
19
|
+
*
|
|
20
|
+
* The shortest extent comes first, so a caller that only wants the unambiguous reading can take
|
|
21
|
+
* the first candidate per `start` and never consult the filesystem.
|
|
22
|
+
*
|
|
23
|
+
* ponytail: one row at a time, so a path wrapped across two visual rows is missed, and a relative
|
|
24
|
+
* path resolves against the cwd the pane SPAWNED with, so it is wrong after a `cd`. Absolute
|
|
25
|
+
* paths — what Claude Code and most tools print — are unaffected by both.
|
|
26
|
+
*
|
|
27
|
+
* ponytail: only the END of a path can be recovered this way. A RELATIVE path whose first segment
|
|
28
|
+
* contains a space ("My Docs\a.txt") is anchored at "Docs\a.txt", because the match can only
|
|
29
|
+
* begin where a path-shaped run begins. An absolute path is safe — its drive or leading slash
|
|
30
|
+
* anchors it — and that is the form tools print.
|
|
31
|
+
*/
|
|
32
|
+
export declare function findPaths(row: string, cwd: string): TermPath[];
|
|
33
|
+
/**
|
|
34
|
+
* Pick the links to offer from `findPaths`'s candidates, given which of them exist.
|
|
35
|
+
*
|
|
36
|
+
* `exists` is positional — one entry per candidate. Kept as a parameter rather than a callback so
|
|
37
|
+
* this stays pure and node-testable; the filesystem lives in the caller.
|
|
38
|
+
*
|
|
39
|
+
* For each match (candidates sharing a `start`) the LONGEST existing extent wins: if both
|
|
40
|
+
* "D:\Program" and "D:\Program Files\Deck\deck.exe" existed, the longer one is what was written.
|
|
41
|
+
* Overlapping results are then dropped, because the tail of a space-containing path is itself a
|
|
42
|
+
* relative-path-shaped match at a later column, and two links over one span would let a click
|
|
43
|
+
* land on either.
|
|
44
|
+
*/
|
|
45
|
+
export declare function chooseLinks(candidates: readonly TermPath[], exists: readonly boolean[]): TermPath[];
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
import { Terminal } from "@xterm/xterm";
|
|
3
|
+
import { FitAddon } from "@xterm/addon-fit";
|
|
4
|
+
/** The cap, so Settings can state the real number rather than repeating a literal. */
|
|
5
|
+
export declare const webglLimit: () => number;
|
|
6
|
+
export interface TermOutput {
|
|
7
|
+
id: string;
|
|
8
|
+
data: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TermExit {
|
|
11
|
+
id: string;
|
|
12
|
+
}
|
|
13
|
+
export type SplitDir = "h" | "v";
|
|
14
|
+
export type LayoutNode = {
|
|
15
|
+
kind: "leaf";
|
|
16
|
+
id: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
view?: string;
|
|
19
|
+
} | {
|
|
20
|
+
kind: "split";
|
|
21
|
+
dir: SplitDir;
|
|
22
|
+
a: LayoutNode;
|
|
23
|
+
b: LayoutNode;
|
|
24
|
+
ratio: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A tab, and — with `x`/`y` — a zone on the canvas.
|
|
28
|
+
*
|
|
29
|
+
* The coordinates are OPTIONAL and nothing writes them on load: a tab saved before zones
|
|
30
|
+
* existed has none, and `zoneAt` places it by its index instead. That keeps every layout ever
|
|
31
|
+
* written valid and means the tab strip and the canvas are two views of one list, not two
|
|
32
|
+
* models to keep in sync.
|
|
33
|
+
*/
|
|
34
|
+
export interface LayoutTab {
|
|
35
|
+
id: string;
|
|
36
|
+
title: string;
|
|
37
|
+
root: LayoutNode;
|
|
38
|
+
x?: number;
|
|
39
|
+
y?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface LayoutWorkspace {
|
|
42
|
+
id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
cwd: string;
|
|
45
|
+
tabs: LayoutTab[];
|
|
46
|
+
activeTab: string;
|
|
47
|
+
}
|
|
48
|
+
export interface Layout {
|
|
49
|
+
workspaces: LayoutWorkspace[];
|
|
50
|
+
activeWs: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function publishLayout(l: Layout): void;
|
|
53
|
+
export declare function getLayout(): Layout | null;
|
|
54
|
+
export declare function loadLayoutOnce(): Promise<void>;
|
|
55
|
+
export declare function mutateLayout(fn: (l: Layout) => Layout): void;
|
|
56
|
+
export declare function useLayout(): Layout | null;
|
|
57
|
+
export declare function activeWorkspaceCwd(): string;
|
|
58
|
+
/** Switch the active workspace (+ optionally its active tab) — used by agent-notification clicks. */
|
|
59
|
+
export declare function switchWorkspace(wsId: string, tabId?: string): void;
|
|
60
|
+
/** The workspace whose cwd matches (case/slash-insensitive), for routing an agent hook to a tab. */
|
|
61
|
+
/**
|
|
62
|
+
* How many columns the zone board has. Here rather than only in the UI because the fallback
|
|
63
|
+
* placement below has to agree with what the overview can draw.
|
|
64
|
+
*/
|
|
65
|
+
export declare const ZONE_BOARD = 3;
|
|
66
|
+
/**
|
|
67
|
+
* Where a zone sits on the canvas: its stored coordinates, else its place in the list.
|
|
68
|
+
*
|
|
69
|
+
* The fallback is what makes zones work on a layout that predates them — the tabs you already
|
|
70
|
+
* have become the first row, left to right, without rewriting anything on disk.
|
|
71
|
+
*/
|
|
72
|
+
export declare function zoneAt(tabs: readonly LayoutTab[], id: string, cols?: number): {
|
|
73
|
+
x: number;
|
|
74
|
+
y: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The zone to move to from `id` going `dir`, or null when there is none that way.
|
|
78
|
+
*
|
|
79
|
+
* Nearest in a straight line: same row for left/right, same column for up/down, smallest step.
|
|
80
|
+
* No wrapping — running out of canvas should feel like an edge, not teleport you across it.
|
|
81
|
+
*/
|
|
82
|
+
export declare function zoneToward(tabs: readonly LayoutTab[], id: string, dir: "left" | "right" | "up" | "down"): LayoutTab | null;
|
|
83
|
+
/**
|
|
84
|
+
* Put a zone at a spot on the canvas, swapping with whatever is already there.
|
|
85
|
+
*
|
|
86
|
+
* Swap rather than push-and-shuffle: a zone you did not touch should not move because another
|
|
87
|
+
* one arrived next to it, and with sparse coordinates there is no row to shuffle along anyway.
|
|
88
|
+
*
|
|
89
|
+
* Every tab gets explicit coordinates on the way out, including ones that were still relying on
|
|
90
|
+
* the index fallback — otherwise moving one zone would silently shift the unplaced ones, since
|
|
91
|
+
* their position depends on where they sit in the list.
|
|
92
|
+
*/
|
|
93
|
+
export declare function moveZone(tabs: readonly LayoutTab[], id: string, to: {
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
}): LayoutTab[];
|
|
97
|
+
/** The first free spot on the top row, for a zone created without a position of its own. */
|
|
98
|
+
export declare function nextZoneSpot(tabs: readonly LayoutTab[], cols?: number, rows?: number): {
|
|
99
|
+
x: number;
|
|
100
|
+
y: number;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Is there nowhere left to put a zone?
|
|
104
|
+
*
|
|
105
|
+
* The board is a fixed 3x3 — deliberately, so the overview and the Ctrl+Alt compass are always
|
|
106
|
+
* the same nine cells. A tenth zone has no spot: it drew off the edge of the overview and the
|
|
107
|
+
* compass could not reach it, so it existed but could not be seen or switched to.
|
|
108
|
+
*
|
|
109
|
+
* Checked by every caller that creates one, rather than inside nextZoneSpot, because refusing
|
|
110
|
+
* and reporting why is the caller's job — the keyboard shortcut says so in a toast, and the
|
|
111
|
+
* layout op tells the agent that asked.
|
|
112
|
+
*/
|
|
113
|
+
export declare function zoneBoardFull(tabs: readonly LayoutTab[], cols?: number, rows?: number): boolean;
|
|
114
|
+
export declare function workspaceByCwd(cwd: string): LayoutWorkspace | undefined;
|
|
115
|
+
/** The folder a pane's shell was spawned in — its workspace's cwd. */
|
|
116
|
+
export declare function paneCwd(paneId: string): string;
|
|
117
|
+
/**
|
|
118
|
+
* A pane's display name: its own label, else the title of the tab holding it.
|
|
119
|
+
*
|
|
120
|
+
* Here rather than in the footer that first needed it, because Settings lists the same pinned
|
|
121
|
+
* panes and a second copy of this walk would be a second answer to one question.
|
|
122
|
+
*/
|
|
123
|
+
export declare function paneLabel(paneId: string): string;
|
|
124
|
+
/** Which workspace + tab holds a pane, for jumping to an agent from outside Terminals. */
|
|
125
|
+
export declare function paneLocation(paneId: string): {
|
|
126
|
+
wsId: string;
|
|
127
|
+
wsName: string;
|
|
128
|
+
tabId: string;
|
|
129
|
+
} | undefined;
|
|
130
|
+
/** Give a pane real keyboard focus. No-op if it isn't mounted yet — the caller retries. */
|
|
131
|
+
export declare function focusPane(paneId: string): boolean;
|
|
132
|
+
export declare const termSpawn: (id: string, cwd: string, cols: number, rows: number) => Promise<void>;
|
|
133
|
+
export declare const termWrite: (id: string, data: string) => Promise<void>;
|
|
134
|
+
export declare const termResize: (id: string, cols: number, rows: number) => Promise<void>;
|
|
135
|
+
export declare const termKill: (id: string) => Promise<void>;
|
|
136
|
+
export declare const termList: () => Promise<string[]>;
|
|
137
|
+
/** Delete scrollback logs for panes not in `keep`. Returns how many were removed. */
|
|
138
|
+
export declare const termSweepScrollback: (keep: string[]) => Promise<number>;
|
|
139
|
+
export declare const termScrollback: (id: string) => Promise<string>;
|
|
140
|
+
export declare function leafIds(n: LayoutNode): string[];
|
|
141
|
+
export declare function splitLeaf(n: LayoutNode, id: string, dir: SplitDir, ratio?: number, view?: string): LayoutNode;
|
|
142
|
+
export declare function setLeafLabel(n: LayoutNode, id: string, label: string): LayoutNode;
|
|
143
|
+
/**
|
|
144
|
+
* Turn a pane into a view, or back into a terminal when `view` is empty.
|
|
145
|
+
*
|
|
146
|
+
* The pane keeps its id, so the layout, the splits around it and its place in the tab are
|
|
147
|
+
* untouched — only what it renders changes. Its label goes with the old contents: a terminal
|
|
148
|
+
* named "server" that becomes a notes pane is not the server any more.
|
|
149
|
+
*/
|
|
150
|
+
export declare function setLeafView(n: LayoutNode, id: string, view: string): LayoutNode;
|
|
151
|
+
export declare function closeLeaf(n: LayoutNode, id: string): LayoutNode | null;
|
|
152
|
+
export type DropSide = "left" | "right" | "top" | "bottom";
|
|
153
|
+
/** The leaf node itself (not just its id) — a move carries the pane's label with it. */
|
|
154
|
+
export declare function findLeaf(n: LayoutNode, id: string): LayoutNode | null;
|
|
155
|
+
/** Replace a leaf with a split holding it and `leaf`, ordered by which side `leaf` lands on. */
|
|
156
|
+
export declare function insertBeside(n: LayoutNode, targetId: string, leaf: LayoutNode, side: DropSide): LayoutNode;
|
|
157
|
+
/**
|
|
158
|
+
* Move a pane next to another within one tab. The leaf keeps its id, so the xterm instance (and
|
|
159
|
+
* therefore the running shell and its scrollback) survives — attach() re-parents it on remount.
|
|
160
|
+
* closeLeaf already collapses the split the pane leaves behind.
|
|
161
|
+
*/
|
|
162
|
+
export declare function moveLeaf(root: LayoutNode, srcId: string, targetId: string, side: DropSide): LayoutNode;
|
|
163
|
+
/**
|
|
164
|
+
* Open a new tab in a workspace and return the id of the pane it contains.
|
|
165
|
+
*
|
|
166
|
+
* applyDtCommand's "new-tab" does the same thing but returns nothing, which is fine for an agent
|
|
167
|
+
* driving Deck over HTTP (it can look the pane up afterwards) and useless in-process, where the
|
|
168
|
+
* caller wants to type into the pane it just made. Pair it with queueInput: the pane has no PTY
|
|
169
|
+
* until it is attached to a sized element, so anything written before then is dropped.
|
|
170
|
+
*/
|
|
171
|
+
export declare function openTabInWorkspace(wsId: string, title: string): string | null;
|
|
172
|
+
export declare function applyDtCommand(op: string, args: Record<string, unknown>): string | void;
|
|
173
|
+
interface Instance {
|
|
174
|
+
term: Terminal;
|
|
175
|
+
fit: FitAddon;
|
|
176
|
+
opened: boolean;
|
|
177
|
+
spawned: boolean;
|
|
178
|
+
exited: boolean;
|
|
179
|
+
lastCols: number;
|
|
180
|
+
lastRows: number;
|
|
181
|
+
}
|
|
182
|
+
/** Re-apply the terminal look to every live pane. Called when the settings change, so an open
|
|
183
|
+
* terminal restyles in place instead of only new ones picking it up. A font change alters the
|
|
184
|
+
* cell size, so each pane is refit and its PTY told the new grid — otherwise the shell keeps
|
|
185
|
+
* drawing to the old column count. */
|
|
186
|
+
export declare function applyTerminalLook(): void;
|
|
187
|
+
export declare function useAgentPanesVersion(): number;
|
|
188
|
+
/**
|
|
189
|
+
* How many of a workspace's panes have a shell right now.
|
|
190
|
+
*
|
|
191
|
+
* A pane spawns lazily and is killed by a suspend, so the layout says nothing about whether
|
|
192
|
+
* anything is running in it. This is what distinguishes a workspace worth suspending from one
|
|
193
|
+
* already asleep.
|
|
194
|
+
*/
|
|
195
|
+
export declare function workspaceShellCount(ws: LayoutWorkspace): number;
|
|
196
|
+
/** A workspace is "active" if any of its panes has a LIVE claude agent (not just a shell). */
|
|
197
|
+
export declare function isWorkspaceActive(ws: LayoutWorkspace): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Mark a pane as running an agent right now, without waiting for the sweep.
|
|
200
|
+
*
|
|
201
|
+
* agentPanes is refreshed from Rust every 45s, which is the right cadence for noticing an agent
|
|
202
|
+
* that EXITED but far too slow for one we just started ourselves — the menu would keep offering
|
|
203
|
+
* to start a second one for most of a minute. The next sweep confirms it, or clears it if the
|
|
204
|
+
* command never took.
|
|
205
|
+
*/
|
|
206
|
+
export declare function markAgentStarted(paneId: string): void;
|
|
207
|
+
/** Does this pane have a LIVE claude agent? Used to decide whether closing needs confirming. */
|
|
208
|
+
export declare function paneHasAgent(paneId: string): boolean;
|
|
209
|
+
/** Move a workspace to a new index (drag-reorder). Order is what Ctrl+1..9 indexes into. */
|
|
210
|
+
export declare function moveWorkspace(id: string, toIndex: number): void;
|
|
211
|
+
/**
|
|
212
|
+
* Ctrl+click a file path in terminal output to open it in this workspace's editor.
|
|
213
|
+
*
|
|
214
|
+
* Registered per attach because resolving a relative path needs the pane's cwd, which is what
|
|
215
|
+
* attach is given. The instance outlives its DOM, so the previous provider is disposed first
|
|
216
|
+
* rather than stacking a second one on every re-attach. The matching itself lives in shellpath
|
|
217
|
+
* (no xterm import), where it is exercised by shellpath.check.ts.
|
|
218
|
+
*
|
|
219
|
+
* Only a path that actually exists is offered as a link. Matching the shape of a path is not the
|
|
220
|
+
* same as having one: output wraps mid-path at the edge of a narrow pane, a relative path resolves
|
|
221
|
+
* against the cwd the pane spawned with rather than the one it is in now, and ordinary prose
|
|
222
|
+
* contains slashes ("feature/foo", "and/or"). All three produce a link that opens nothing, so the
|
|
223
|
+
* check is on existence rather than on any single one of those causes.
|
|
224
|
+
*
|
|
225
|
+
* provideLinks is callback-shaped so a provider may answer asynchronously. xterm asks only about
|
|
226
|
+
* the row under the cursor and caches the answer until the buffer changes, so this is a few small
|
|
227
|
+
* IPC calls on hover, not one per line of output.
|
|
228
|
+
*
|
|
229
|
+
* ponytail: fsSize, because it already exists and needs no Rust change. A directory reports 0 on
|
|
230
|
+
* Windows, so this rejects those too — which is right, the editor cannot open one. The cost is
|
|
231
|
+
* that a genuinely empty file is not clickable; a dedicated fs_is_file is not worth that case.
|
|
232
|
+
*/
|
|
233
|
+
/**
|
|
234
|
+
* The last lines a pane has on screen, as plain text.
|
|
235
|
+
*
|
|
236
|
+
* For drawing a pane somewhere it cannot actually be mounted — the zone overview. An xterm has
|
|
237
|
+
* ONE element and `attach` moves it into whichever host mounted last, so a second live copy is
|
|
238
|
+
* not possible: rendering real panes in the overview would pull every terminal out of the zone
|
|
239
|
+
* being looked at. Reading the buffer sidesteps that entirely.
|
|
240
|
+
*
|
|
241
|
+
* Empty for a pane that has not spawned yet, which is the honest answer — there is nothing in it.
|
|
242
|
+
*/
|
|
243
|
+
export declare function paneLines(id: string, max?: number): string[];
|
|
244
|
+
export declare function getInstance(id: string): Instance;
|
|
245
|
+
/**
|
|
246
|
+
* Wrap pasted text in bracketed-paste markers, so the receiving app can tell one paste from
|
|
247
|
+
* typing — and, more importantly, from a paste that arrives in pieces.
|
|
248
|
+
*
|
|
249
|
+
* ConPTY takes about 1KB per input write. A 4KB paste is handed to write_all whole, and
|
|
250
|
+
* Windows still delivers it to the shell in 1KB fragments with gaps between them. An app that
|
|
251
|
+
* decides "paste or typing?" on timing then sees four separate pastes: pasting a long command
|
|
252
|
+
* into Claude Code split it into five messages, each cut mid-line at a 1024-byte boundary.
|
|
253
|
+
* Nothing was lost — only the boundaries were wrong.
|
|
254
|
+
*
|
|
255
|
+
* The markers put the boundaries in the CONTENT, where fragmentation cannot move them: the
|
|
256
|
+
* reader reassembles on ESC[200~ / ESC[201~ rather than on when the bytes happened to land.
|
|
257
|
+
*
|
|
258
|
+
* Chunking the write instead would not fix this. The fragmentation is ConPTY's, below us, and
|
|
259
|
+
* smaller writes would only add more seams.
|
|
260
|
+
*/
|
|
261
|
+
export declare function bracketPaste(text: string, bracketed: boolean): string;
|
|
262
|
+
/** Paste the clipboard text into a terminal's PTY (Ctrl+V and the context-menu Paste). */
|
|
263
|
+
export declare function pasteInto(id: string): Promise<void>;
|
|
264
|
+
export declare function attach(id: string, el: HTMLElement, cwd: string): () => void;
|
|
265
|
+
export declare function queueInput(paneId: string, text: string): void;
|
|
266
|
+
/**
|
|
267
|
+
* Type into a pane whether or not its shell exists yet.
|
|
268
|
+
*
|
|
269
|
+
* queueInput alone is only right for a pane being CREATED — the queue is drained by the spawn, so
|
|
270
|
+
* on a pane that is already running the text would sit there forever. Anything typing into a pane
|
|
271
|
+
* the user picked (the agent launcher) has to handle both.
|
|
272
|
+
*/
|
|
273
|
+
export declare function sendInput(paneId: string, text: string): void;
|
|
274
|
+
/**
|
|
275
|
+
* Size a pane's PTY, and every view of it, to the SMALLER of those views.
|
|
276
|
+
*
|
|
277
|
+
* The single sizing authority. A PTY has one column count, so a pinned pane's two views cannot
|
|
278
|
+
* each own their own size — and when they tried, each view's resize re-fired the other's
|
|
279
|
+
* ResizeObserver, which resized back. Two term_resize calls per cycle, each a full ConPTY screen
|
|
280
|
+
* repaint written into both xterms: that ping-pong was the lag.
|
|
281
|
+
*
|
|
282
|
+
* proposeDimensions(), never fit(): fit() RESIZES as a side effect, which changes the host's
|
|
283
|
+
* layout and re-fires the observer that called us. Measuring first and resizing once — only when
|
|
284
|
+
* the size actually differs — means the observer's next pass finds nothing to do and it settles.
|
|
285
|
+
*/
|
|
286
|
+
export declare function refit(id: string): void;
|
|
287
|
+
/**
|
|
288
|
+
* Clear the screen, the way the shell expects.
|
|
289
|
+
*
|
|
290
|
+
* NOT xterm's term.clear(): that drops the scrollback behind xterm's back while ConPTY still
|
|
291
|
+
* thinks the cursor sits where it was, so PowerShell redraws its prompt at a stale row and
|
|
292
|
+
* typing appears mid-screen with no prompt. Sending Ctrl+L (\x0c) instead lets the program
|
|
293
|
+
* owning the pane do the clearing — PSReadLine clears and reprints its prompt, and a TUI
|
|
294
|
+
* (Claude, vim) treats it as a repaint. Terminal and shell stay in agreement either way.
|
|
295
|
+
*/
|
|
296
|
+
export declare function clearPane(id: string): void;
|
|
297
|
+
/**
|
|
298
|
+
* Kill the pane's shell and start a fresh one in the same xterm, keeping the pane id (so the
|
|
299
|
+
* layout, name and split position survive). Claude is NOT re-resumed: `agentResumed` already
|
|
300
|
+
* holds this id from the first spawn, and a restart is a request for a clean shell.
|
|
301
|
+
*/
|
|
302
|
+
export declare function restartPane(id: string, cwd: string): Promise<void>;
|
|
303
|
+
/**
|
|
304
|
+
* Kill every shell in a workspace, keeping its layout.
|
|
305
|
+
*
|
|
306
|
+
* The same thing a Deck restart does to a workspace you have not opened, done on demand: the
|
|
307
|
+
* panes, splits and zones stay exactly as they are, and each one spawns again — resuming its
|
|
308
|
+
* Claude session — the next time it is attached. What it buys is memory: an xterm buffer, a
|
|
309
|
+
* WebGL context, a ConPTY and a shell per pane, for a project you are not using right now.
|
|
310
|
+
*
|
|
311
|
+
* What does NOT come back is anything the shell was running that Deck did not start: a dev
|
|
312
|
+
* server or a `flutter run` is killed, and nothing recorded the command to type again. Only a
|
|
313
|
+
* Claude session is resumable, because its uuid is the one thing that gets written down.
|
|
314
|
+
*
|
|
315
|
+
* Returns how many shells were actually killed.
|
|
316
|
+
*/
|
|
317
|
+
export declare function suspendWorkspace(wsId: string): Promise<number>;
|
|
318
|
+
export declare function destroy(id: string): void;
|
|
319
|
+
export declare function usePinnedPanes(): string[];
|
|
320
|
+
export declare const isPinned: (id: string) => boolean;
|
|
321
|
+
export declare function togglePin(id: string): void;
|
|
322
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
export type AccentColor = "violet" | "blue" | "cyan" | "green" | "amber" | "red";
|
|
3
|
+
export type BgPreset = "black" | "slate" | "warm" | "midnight" | "charcoal" | "nord" | "plum" | "dracula" | "forest";
|
|
4
|
+
export type Density = "compact" | "cozy";
|
|
5
|
+
/** Accent base/strong pairs. Values match the primitives already in tokens.css. */
|
|
6
|
+
export declare const ACCENTS: Record<AccentColor, {
|
|
7
|
+
label: string;
|
|
8
|
+
base: string;
|
|
9
|
+
strong: string;
|
|
10
|
+
}>;
|
|
11
|
+
/** The five-step neutral ramp, darkest surface first. Borders come from white alpha, so they
|
|
12
|
+
* work across all three without per-preset values. */
|
|
13
|
+
export declare const BG_PRESETS: Record<BgPreset, {
|
|
14
|
+
label: string;
|
|
15
|
+
app: string;
|
|
16
|
+
panel: string;
|
|
17
|
+
card: string;
|
|
18
|
+
elev: string;
|
|
19
|
+
hover: string;
|
|
20
|
+
muted: string;
|
|
21
|
+
}>;
|
|
22
|
+
/** Density scales the type ramp and the shared radii — the two things that set how much fits
|
|
23
|
+
* on screen without touching any component's own padding. */
|
|
24
|
+
export declare const DENSITIES: Record<Density, {
|
|
25
|
+
label: string;
|
|
26
|
+
hint: string;
|
|
27
|
+
scale: number;
|
|
28
|
+
radius: number;
|
|
29
|
+
}>;
|
|
30
|
+
/** Apply the three appearance settings to the document. Safe to call repeatedly. */
|
|
31
|
+
export declare function applyTheme(opts: {
|
|
32
|
+
accent?: AccentColor;
|
|
33
|
+
bgPreset?: BgPreset;
|
|
34
|
+
density?: Density;
|
|
35
|
+
termTheme?: TermTheme;
|
|
36
|
+
}): void;
|
|
37
|
+
/** The values the app starts with, before settings.json has been read. Matches tokens.css. */
|
|
38
|
+
export declare const DEFAULT_APPEARANCE: {
|
|
39
|
+
accent: AccentColor;
|
|
40
|
+
bgPreset: BgPreset;
|
|
41
|
+
density: Density;
|
|
42
|
+
};
|
|
43
|
+
export type TermTheme = "match" | "deck" | "dark" | "dimmed" | "solarized";
|
|
44
|
+
/** Fixed palettes. "match" isn't here — it's derived from the app's accent + background at
|
|
45
|
+
* resolve time (see termThemeColors), so it changes with those settings. */
|
|
46
|
+
export declare const TERM_THEMES: Record<Exclude<TermTheme, "match">, {
|
|
47
|
+
label: string;
|
|
48
|
+
background: string;
|
|
49
|
+
foreground: string;
|
|
50
|
+
cursor: string;
|
|
51
|
+
selectionBackground: string;
|
|
52
|
+
}>;
|
|
53
|
+
/** The label a theme shows in the picker, including the derived "match" entry. */
|
|
54
|
+
export declare const TERM_THEME_LABELS: Record<TermTheme, string>;
|
|
55
|
+
/** Resolve a terminal theme to concrete colours. "match" follows the app's own appearance: the
|
|
56
|
+
* card surface as the background (so a terminal reads as part of the panel it sits in) and the
|
|
57
|
+
* accent as the cursor, so picking a new accent recolours the terminal too. */
|
|
58
|
+
export declare function termThemeColors(theme: TermTheme, accent?: AccentColor, bgPreset?: BgPreset): {
|
|
59
|
+
label: string;
|
|
60
|
+
background: string;
|
|
61
|
+
foreground: string;
|
|
62
|
+
cursor: string;
|
|
63
|
+
selectionBackground: string;
|
|
64
|
+
};
|
|
65
|
+
export declare const TERM_FONTS: {
|
|
66
|
+
value: string;
|
|
67
|
+
label: string;
|
|
68
|
+
}[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
|
|
2
|
+
import { EditorView } from "@codemirror/view";
|
|
3
|
+
export declare function MarkdownLive({ value, path, onChange, onSave, onView, flush, fontSize, onWikiLink, resolveWikiLink, wikiLinkOptions, mermaid, resolveEmbed }: {
|
|
4
|
+
value: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
onChange: (v: string) => void;
|
|
7
|
+
onSave?: () => void;
|
|
8
|
+
/** Hands the live EditorView out, and null on unmount. For a formatting toolbar, which has to
|
|
9
|
+
* dispatch into this editor rather than rewrite the string around it. */
|
|
10
|
+
onView?: (v: EditorView | null) => void;
|
|
11
|
+
/** Left-align the text across the full width instead of a centred document column. The column
|
|
12
|
+
* suits a file you sit and read; a side panel just loses its width to the margins. */
|
|
13
|
+
flush?: boolean;
|
|
14
|
+
/** Base text size in px. Applied through a Compartment so changing it reconfigures the live
|
|
15
|
+
* editor rather than rebuilding it — a remount per zoom step would discard the undo history. */
|
|
16
|
+
fontSize?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Handle a click on a `[[wikilink]]`. Omit and wikilinks are not parsed at all, so the Editor
|
|
19
|
+
* renders a note exactly as it did before this existed.
|
|
20
|
+
*
|
|
21
|
+
* Deck itself has no note-resolution rules — which file `[[Name]]` means is the vault plugin's
|
|
22
|
+
* question, so it answers it.
|
|
23
|
+
*/
|
|
24
|
+
onWikiLink?: (target: string, heading: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Does this wikilink point at a note that exists? Dimmed and struck through when it does not.
|
|
27
|
+
*
|
|
28
|
+
* Deck cannot answer this — which file `[[Name]]` means is the vault's question — so the caller
|
|
29
|
+
* does. Omit it and every link is drawn as though it resolves.
|
|
30
|
+
*/
|
|
31
|
+
resolveWikiLink?: (target: string) => boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Candidates for a `[[` being typed, so a link can be picked rather than remembered.
|
|
34
|
+
*
|
|
35
|
+
* Given whatever has been typed since the brackets. Returns what to offer: `target` is written
|
|
36
|
+
* into the document, `label` and `detail` are what the list shows. Omit it and typing `[[`
|
|
37
|
+
* does nothing special.
|
|
38
|
+
*/
|
|
39
|
+
wikiLinkOptions?: (query: string) => {
|
|
40
|
+
target: string;
|
|
41
|
+
label: string;
|
|
42
|
+
detail?: string;
|
|
43
|
+
}[];
|
|
44
|
+
/**
|
|
45
|
+
* Draw ```mermaid fences as diagrams. The caret inside one shows its source again, so it can
|
|
46
|
+
* be edited, and it redraws when the caret leaves.
|
|
47
|
+
*
|
|
48
|
+
* Off by default: mermaid is a large dependency, loaded on first use, and the Editor already
|
|
49
|
+
* renders a note's diagrams in its Preview view.
|
|
50
|
+
*/
|
|
51
|
+
mermaid?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Where an Obsidian embed's file lives: `![[diagram.png]]` gives "diagram.png" and wants an
|
|
54
|
+
* absolute path back, or null when nothing matches.
|
|
55
|
+
*
|
|
56
|
+
* Resolved by NAME against the whole vault, which is a question only the caller can answer.
|
|
57
|
+
* Omit it and an embed stays as text rather than rendering as a broken image.
|
|
58
|
+
*/
|
|
59
|
+
resolveEmbed?: (name: string) => string | null;
|
|
60
|
+
}): import("react").JSX.Element;
|
|
61
|
+
export default MarkdownLive;
|