deck-plugin-sdk 1.4.0 → 1.6.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.
Files changed (40) hide show
  1. package/README.md +96 -77
  2. package/bin/deck-plugin.mjs +149 -116
  3. package/build-plugin.mjs +48 -26
  4. package/package.json +6 -1
  5. package/packages.mjs +107 -0
  6. package/shim/bridge.js +73 -90
  7. package/shim/event.js +6 -1
  8. package/shim/scope.js +6 -0
  9. package/shim/terminals.js +1 -0
  10. package/shim/ui.d.ts +1 -0
  11. package/shim/ui.js +7 -1
  12. package/template/AGENTS.md +77 -0
  13. package/template/CLAUDE.md +1 -0
  14. package/template/README.md +20 -17
  15. package/template/gitignore +4 -4
  16. package/template/plugin.json +9 -9
  17. package/template/src/assets.d.ts +16 -0
  18. package/template/src/plugin.tsx +65 -65
  19. package/types/components/ActivityBar.d.ts +3 -1
  20. package/types/components/ContextMenu.d.ts +3 -0
  21. package/types/components/TabStrip.d.ts +6 -1
  22. package/types/components/ui.d.ts +48 -1
  23. package/types/components/useResize.d.ts +8 -1
  24. package/types/core/bookmarks.d.ts +79 -0
  25. package/types/core/bridge.d.ts +294 -156
  26. package/types/core/browser.d.ts +189 -0
  27. package/types/core/browserurl.d.ts +64 -0
  28. package/types/core/editorsession.d.ts +55 -0
  29. package/types/core/editorsettings.d.ts +9 -0
  30. package/types/core/fileview.d.ts +35 -0
  31. package/types/core/notifications.d.ts +84 -0
  32. package/types/core/notifyapi.d.ts +39 -0
  33. package/types/core/terminals.d.ts +7 -0
  34. package/types/modules/editor/DiffPeek.d.ts +19 -0
  35. package/types/modules/editor/MonacoHosts.d.ts +19 -6
  36. package/types/modules/editor/detectlang.d.ts +3 -0
  37. package/types/modules/editor/editorstatus.d.ts +2 -0
  38. package/types/modules/editor/hunks.d.ts +54 -0
  39. package/types/modules/editor/models.d.ts +11 -0
  40. package/types/modules/editor/tree.d.ts +0 -6
@@ -0,0 +1,189 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ import { type RecentPage } from "./browserurl";
3
+ import { type Bookmarks } from "./bookmarks";
4
+ /**
5
+ * `home`: the pane shows Deck's start page, and its webview (if it has one) is hidden. `back` and
6
+ * `forward`: whether the page has history that way. `private`: nothing it visits is kept.
7
+ * `page`: which of Deck's own pages the pane shows instead of a site, with `home` set too so the
8
+ * webview stays hidden ("" with `home` is the start page).
9
+ */
10
+ export type DeckPage = "" | "history" | "bookmarks" | "settings" | "downloads" | "passwords" | "extensions";
11
+ export interface BrowserState {
12
+ url: string;
13
+ title: string;
14
+ loading: boolean;
15
+ home: boolean;
16
+ page: DeckPage;
17
+ back: boolean;
18
+ forward: boolean;
19
+ private: boolean;
20
+ /** The find bar: shown, and the matches the search has (index is the current one, from 1). */
21
+ findOpen: boolean;
22
+ findCount: number;
23
+ findIndex: number;
24
+ /** The site's icon, whether the page plays sound and is muted, and its zoom (1 = 100%). */
25
+ favicon: string;
26
+ playing: boolean;
27
+ muted: boolean;
28
+ zoom: number;
29
+ /** The tab's own volume, 0 to 1, over what the page sets (VOLUME_JS in browser.rs). */
30
+ volume: number;
31
+ /** Ads and trackers the ad blocker refused on the current page. */
32
+ blocked: number;
33
+ /** The device the page is laid out as (DeviceBar), "" for the page's own size. */
34
+ device: string;
35
+ /** The device turned on its side (width and height swapped). */
36
+ rotated: boolean;
37
+ /** Devices shown side by side (DeviceBar), the first in the pane's own webview; [] for one. */
38
+ devices: string[];
39
+ }
40
+ export declare const subscribeBrowser: (f: () => void) => () => void;
41
+ export declare const browserState: (pane: string) => BrowserState | undefined;
42
+ /**
43
+ * The pane is gone (closed, or its tab or workspace was): close its webview and forget its page.
44
+ * Called from terminals.ts's destroy(), which every way of removing a pane goes through.
45
+ */
46
+ export declare function closeBrowserPane(pane: string): void;
47
+ /** The find bar registers how to focus its box, for Ctrl+F while it is already open. */
48
+ export declare function registerFindBox(pane: string, focus: () => void): () => void;
49
+ /** Open the find bar (Ctrl+F), or put the keyboard back in it when it is open. */
50
+ export declare function openFind(pane: string): void;
51
+ /** Close it and clear the page's highlights. */
52
+ export declare function closeFind(pane: string): void;
53
+ /** Show the start page in the pane, or leave it for `url`. */
54
+ export declare const showHome: (pane: string) => void;
55
+ export declare const leaveHome: (pane: string, url: string) => void;
56
+ /** Show the history page in the pane. */
57
+ export declare const showHistory: (pane: string) => void;
58
+ /** Show the bookmarks page in the pane. */
59
+ export declare const showBookmarks: (pane: string) => void;
60
+ /** Show the downloads in the pane. */
61
+ export declare const showDownloads: (pane: string) => void;
62
+ /** Show the extensions in the pane. */
63
+ export declare const showExtensions: (pane: string) => void;
64
+ /** Show the password vault in the pane. */
65
+ export declare const showPasswords: (pane: string) => void;
66
+ /** Show the browser's settings in the pane. */
67
+ export declare const showBrowserSettings: (pane: string) => void;
68
+ /** A new pane's kind, before anything else is known about it. */
69
+ export declare const startPane: (pane: string, isPrivate: boolean) => void;
70
+ /** Every ad and tracker blocked so far. */
71
+ export declare const totalBlocked: () => number;
72
+ /** The user's own ad blocker rules, as text. */
73
+ export declare const myFilters: () => Promise<string>;
74
+ /** Save them, and put them to work. */
75
+ export declare function saveMyFilters(text: string): Promise<void>;
76
+ /** Lay the pane's page out as a device (DeviceBar's ids), or as itself (""). */
77
+ export declare const setDevice: (pane: string, device: string) => void;
78
+ export declare const setRotated: (pane: string, rotated: boolean) => void;
79
+ /** Show these devices side by side (the first in the pane's own webview), or one ([]). */
80
+ export declare const setDevices: (pane: string, devices: string[]) => void;
81
+ /** A side-by-side device's webview rather than a pane's own. */
82
+ export declare function isMirror(pane: string): boolean;
83
+ /** The pane a mirror belongs to (a pane is its own). */
84
+ export declare function paneOf(id: string): string;
85
+ export declare function addMirror(id: string): void;
86
+ export declare function removeMirror(id: string): void;
87
+ /** Close a pane's mirrors from the `from`th on: side by side switched off, a device taken away, the
88
+ * pane closed. Not when the pane is only out of sight: a mirror stays, hidden, as the pane's own
89
+ * webview does, so coming back neither reloads it nor races a close against a reopen. */
90
+ export declare function closeMirrors(pane: string, from?: number): void;
91
+ /** Mute or unmute a pane's page. */
92
+ export declare const setMuted: (pane: string, muted: boolean) => undefined;
93
+ /** The tab's volume, 0 to 1. Kept for the tab, and sent again to each page it loads. */
94
+ export declare function setVolume(pane: string, v: number): void;
95
+ /** A browser pane says how to tell whether it has the keyboard and is showing a page. */
96
+ export declare function registerZoomTarget(pane: string, holds: () => boolean): () => void;
97
+ /** The browser pane whose page Deck's zoom keys should zoom, if the keyboard is in one. */
98
+ export declare const activeBrowserPage: () => string | undefined;
99
+ /** Zoom the pane's page a step in or out, or back to 100% (0). */
100
+ export declare function stepZoom(pane: string, dir: -1 | 0 | 1): void;
101
+ /** The URL a just-opened browser pane should show, if a page asked for it. */
102
+ export declare const takeWaitingUrl: () => {
103
+ url: string;
104
+ private: boolean;
105
+ } | undefined;
106
+ /** A new browser tab, on `url` or on the start page. */
107
+ export declare const newBrowserTab: (url?: string, isPrivate?: boolean) => boolean | void;
108
+ /** Read once, before the first browser pane asks. */
109
+ export declare const loadPanes: () => Promise<void>;
110
+ /** The page a pane was on when Deck last closed. */
111
+ export declare const savedPage: (pane: string) => string | undefined;
112
+ /** How Ctrl+Shift+B shows or hides the bookmarks bar: set by the browser pane, which holds the settings. */
113
+ export declare const setBarToggle: (f: () => void) => void;
114
+ /** Bookmark the pane's page, as its star does: Ctrl+D, and the browser menu. */
115
+ export declare const pressStar: (pane: string) => void | undefined;
116
+ /** The pane's star registers how to bookmark the page, for Ctrl+D. */
117
+ export declare function registerStar(pane: string, run: () => void): () => void;
118
+ /** The pane's key in the address bar registers what Ctrl+Shift+L does: fill the login, or offer the choice. */
119
+ export declare function registerVaultKey(pane: string, run: () => void): () => void;
120
+ /** The pane's address bar registers how to focus it, for Ctrl+L. */
121
+ export declare function registerAddressBar(pane: string, focus: () => void): () => void;
122
+ /** Tell Rust which chords to take from a page. Called when a browser pane mounts and whenever a
123
+ * binding changes. */
124
+ export declare function syncBrowserKeys(): void;
125
+ export interface Pin {
126
+ title: string;
127
+ url: string;
128
+ }
129
+ export declare const subscribeLists: (f: () => void) => () => void;
130
+ export declare const listsSnapshot: () => number;
131
+ export declare const browserPins: () => Pin[];
132
+ export declare const recentPages: () => RecentPage[];
133
+ export declare const ensureLists: () => undefined;
134
+ /** `id` is Rust's, for pausing and cancelling, and starts again each run; `key` is unique for good.
135
+ * `session`: started since Deck opened, so the toolbar shows it. */
136
+ export interface Download {
137
+ key: string;
138
+ id: number;
139
+ pane: string;
140
+ url: string;
141
+ path: string;
142
+ received: number;
143
+ total: number;
144
+ state: "running" | "paused" | "done" | "failed";
145
+ started: number;
146
+ session: boolean;
147
+ /** An extension being installed from the store (extensions.rs), not a file: its name once known. */
148
+ extension?: string;
149
+ }
150
+ export declare const subscribeDownloads: (f: () => void) => () => void;
151
+ export declare const downloadsSnapshot: () => number;
152
+ /** Newest first. */
153
+ export declare const browserDownloads: () => Download[];
154
+ /** Take one finished download off the list (the file stays). */
155
+ export declare function forgetDownload(key: string): void;
156
+ /** Take every finished download off the list. */
157
+ export declare function clearDownloads(): void;
158
+ export declare const browserBookmarks: () => Bookmarks;
159
+ export declare function setBookmarks(next: Bookmarks): void;
160
+ /** A Chromium browser's bookmarks on this machine, one per profile that has any. */
161
+ export interface BookmarkSource {
162
+ browser: string;
163
+ profile: string;
164
+ path: string;
165
+ }
166
+ /** Every profile of Chrome, Edge and Brave with a Bookmarks file. A browser not installed is no error. */
167
+ export declare function findBookmarkSources(): Promise<BookmarkSource[]>;
168
+ /** Import one source's bookmarks as a "From Chrome" folder in each root. Returns how many pages. */
169
+ export declare function importBookmarks(src: BookmarkSource): Promise<number>;
170
+ /** Every bookmark to a bookmarks HTML file, which any browser imports, and Deck too. How many pages. */
171
+ export declare function exportBookmarks(path: string): Promise<number>;
172
+ /** A bookmarks HTML file (Deck's own export, or any browser's) merged in, into folders of the same
173
+ * name and without pages already bookmarked. How many pages it added. */
174
+ export declare function importBookmarksFile(path: string): Promise<number>;
175
+ export declare function setPins(next: Pin[]): void;
176
+ /** Forget one page, or every visit between `from` and `to` (all of them when neither is given). */
177
+ export declare function forgetHistory(url: string): void;
178
+ export declare function forgetHistory(range: {
179
+ from?: number;
180
+ to?: number;
181
+ }): void;
182
+ export declare const forgetRecent: (url: string) => void;
183
+ export declare const serversSnapshot: () => number;
184
+ export declare const devServers: () => string[];
185
+ export declare function noteTermOutput(pane: string, chunk: string): void;
186
+ export declare function forgetTermPane(pane: string): void;
187
+ /** Where a pane's page is on screen, in Deck's CSS pixels, while it shows one. */
188
+ export declare const pageBox: (pane: string) => DOMRect | null;
189
+ export declare function trackBrowser(pane: string, el: HTMLElement, url: string): () => void;
@@ -0,0 +1,64 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ export type SearchEngine = "google" | "brave" | "duckduckgo" | "bing";
3
+ export declare const SEARCH_ENGINES: Record<SearchEngine, {
4
+ label: string;
5
+ home: string;
6
+ query: string;
7
+ }>;
8
+ export declare const searchUrl: (engine: SearchEngine, q: string) => string;
9
+ /**
10
+ * What was typed into the address bar or the start page's search box, as a URL to open.
11
+ *
12
+ * A scheme is kept; a local host gets plain http (dev servers rarely have TLS); a Windows or Unix
13
+ * path to a file becomes file:///; text with a space, or a single word with no dot, is a search;
14
+ * anything else is a host and gets https.
15
+ */
16
+ export declare function toUrl(typed: string, engine: SearchEngine): string;
17
+ /**
18
+ * Local URLs in a chunk of terminal output: what a dev server prints when it starts ("Local:
19
+ * http://localhost:5173/"). 0.0.0.0 is where a server listens, not somewhere to go, so it becomes
20
+ * localhost. A trailing dot or comma is the sentence's, not the URL's.
21
+ */
22
+ export declare function devUrls(chunk: string): string[];
23
+ /** The web addresses in a line of terminal output, where each starts and its text: what Ctrl+click
24
+ * opens. A trailing dot, comma or closing bracket is the sentence's, not the address's. */
25
+ export declare function findUrls(line: string): {
26
+ start: number;
27
+ text: string;
28
+ }[];
29
+ export interface RecentPage {
30
+ url: string;
31
+ title: string;
32
+ }
33
+ /** Whether `url` is a search engine's results page: on the way somewhere, not a place to go back to. */
34
+ export declare const isSearchPage: (url: string) => boolean;
35
+ /** One page in the history: how often it was opened, and when last (browser_history.rs keeps them). */
36
+ export interface Visit {
37
+ url: string;
38
+ title: string;
39
+ count: number;
40
+ last: number;
41
+ }
42
+ export interface Suggestion {
43
+ url: string;
44
+ title: string;
45
+ kind: "pin" | "bookmark" | "history";
46
+ }
47
+ /**
48
+ * What the address bar offers for `typed`: pinned sites, bookmarks and history whose address or
49
+ * title holds every word typed. An address that starts with what was typed comes first, then by
50
+ * how often and how lately it was visited, a pin or a bookmark counting as often.
51
+ */
52
+ export declare function suggest(typed: string, sources: {
53
+ pins?: readonly {
54
+ url: string;
55
+ title: string;
56
+ }[];
57
+ bookmarks?: readonly {
58
+ url: string;
59
+ title: string;
60
+ }[];
61
+ history?: readonly Visit[];
62
+ }, now: number, limit?: number): Suggestion[];
63
+ /** A day's heading in the history: Today, Yesterday, or the date. */
64
+ export declare function dayLabel(t: number, now: number): string;
@@ -0,0 +1,55 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ export interface SessionTab {
3
+ /** Older sessions can also hold "graph" and "pr" tabs, from before git moved to the Git
4
+ * plugin. The Editor skips them on restore. */
5
+ /** "untitled" is a buffer never saved (Ctrl+N), path `untitled:Untitled-N`: restored from
6
+ * `content` alone, with no disk read. An older Deck skips the kind, as it skips "graph". */
7
+ kind: "file" | "media" | "graph" | "pr" | "untitled";
8
+ path: string;
9
+ rel: string | null;
10
+ dirty?: string;
11
+ /** untitled: its whole text, and the language picked by hand for it (none: detected). */
12
+ content?: string;
13
+ lang?: string;
14
+ }
15
+ export interface WorkspaceSession {
16
+ tabs: SessionTab[];
17
+ activeId: string | null;
18
+ expanded: string[];
19
+ /** A typed-but-uncommitted message. Per root, because a message belongs to the repo it
20
+ * describes. Only the active module is mounted, so without this a half-written message is
21
+ * destroyed by switching to a terminal to check something — which is exactly when you switch. */
22
+ commitMsg?: string;
23
+ /** Collapsed Source Control rows: the two section headers, and folders in tree view. Per root
24
+ * because the keys are paths in this repo. A Set on the way in and out; an array here because
25
+ * that is what survives JSON. */
26
+ scmCollapsed?: string[];
27
+ }
28
+ /** A file to open, and optionally where in it to land. */
29
+ export interface PendingFile {
30
+ path: string;
31
+ line?: number;
32
+ }
33
+ export declare function queueOpenFiles(files: (string | PendingFile)[], instance?: EditorInstance): void;
34
+ /** Take everything queued for one editor, leaving its queue empty. */
35
+ export declare function drainOpenFiles(instance?: EditorInstance): PendingFile[];
36
+ /**
37
+ * Which editor is asking.
38
+ *
39
+ * There are two: the Editor tab, which opens whatever folder you point it at, and the one inside
40
+ * Terminals, which follows that workspace's cwd. They are separate windows onto different work,
41
+ * so their open folder and their UI prefs are stored per instance. Open TABS already separate on
42
+ * their own — loadSession is keyed by root, and the two rarely share one.
43
+ */
44
+ export type EditorInstance = "tab" | "terminals";
45
+ export declare function loadEditorRoot(instance: EditorInstance, pane?: string): string;
46
+ export declare function saveEditorRoot(instance: EditorInstance, root: string, pane?: string): void;
47
+ export interface GlobalUi {
48
+ mdMode: "edit" | "live" | "split" | "preview";
49
+ panel: "explorer" | "search" | "debug" | "scm";
50
+ sidebarW: number;
51
+ }
52
+ export declare function loadSession(root: string): WorkspaceSession | null;
53
+ export declare function saveSession(root: string, s: WorkspaceSession): void;
54
+ export declare function loadUi(instance: EditorInstance): Partial<GlobalUi>;
55
+ export declare function saveUi(instance: EditorInstance, ui: GlobalUi): void;
@@ -80,6 +80,15 @@ export interface EditorSettings {
80
80
  agentNotifyFinished: boolean;
81
81
  agentNotifyNeedsInput: boolean;
82
82
  agentNotifyOsToast: boolean;
83
+ /** Layout: the file panel docked beside the code or a drawer over it (Ctrl+B either way), the
84
+ * status as a bar along the bottom or a pill floating over the code, and the file's path on its
85
+ * own row under the tabs or in the tab line. */
86
+ layoutFiles: "docked" | "drawer";
87
+ layoutStatus: "bar" | "pill";
88
+ layoutPath: "row" | "tabs";
89
+ /** With the files in a drawer: Search, Source Control and Debug as icons in the tab line, or
90
+ * along the top of the drawer. */
91
+ layoutViews: "tabs" | "drawer";
83
92
  theme: "deck-dark" | "vs-dark" | "hc-black";
84
93
  iconTheme: string;
85
94
  diffSideBySide: boolean;
@@ -0,0 +1,35 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ /** The view showing `path` in plugin `pluginId`'s pane view. */
3
+ export declare const fileView: (pluginId: string, path: string) => string;
4
+ /** A view id's own part, and the file it was opened on if any. */
5
+ export declare function splitView(view: string): {
6
+ base: string;
7
+ file?: string;
8
+ };
9
+ /**
10
+ * What two views are compared by, so one file is one tab however its path was spelled: the file
11
+ * tree, a terminal link and Quick Open can each give the same file with other slashes or case
12
+ * (Windows paths are case-insensitive). The stored view keeps the path as given, for the title.
13
+ */
14
+ export declare function viewKey(view: string): string;
15
+ /** A path's extension, lowercased with its dot (".pdf"), or "" when it has none. */
16
+ export declare const extOf: (path: string) => string;
17
+ /** The last part of a path, for a tab's title. */
18
+ export declare const fileName: (path: string) => string;
19
+ /** Extensions as a plugin wrote them (".pdf", "PDF", "pdf"), as extOf returns them. */
20
+ export declare const normaliseExts: (exts: unknown) => string[];
21
+ /**
22
+ * Which loaded plugin opens which file types, from each plugin's `opens` export. Filled by the
23
+ * plugin loader (plugins.ts) on every load; here so that anything can ask without importing it.
24
+ */
25
+ export declare const fileOpeners: {
26
+ id: string;
27
+ exts: string[];
28
+ }[];
29
+ /** The id of the plugin that opens `path` (by its extension), or undefined: the Editor's. */
30
+ export declare function pluginForFile(path: string): string | undefined;
31
+ /**
32
+ * Open `path` in the plugin that claims its type, as a tab of its own. False when no plugin does,
33
+ * so the caller opens it in the Editor as before. Every way Deck opens a file asks this first.
34
+ */
35
+ export declare function openWithPlugin(path: string): boolean;
@@ -0,0 +1,84 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ /**
3
+ * attention: needs you now (a meeting starting, someone asking to join a board, a timer about to
4
+ * fire). activity: something finished in the background (a download, a timer that ran).
5
+ */
6
+ export type NotifKind = "input" | "done" | "attention" | "activity" | "update" | "error" | "news" | "plugin";
7
+ /**
8
+ * A button on a card and on its bell row. `nav` (a deck-navigate target) and `act` (a handler
9
+ * registered with onNotifAction) survive a restart; `run`, a plugin's own function, does not, so
10
+ * after a restart that button is gone from the bell.
11
+ */
12
+ export interface NotifAction {
13
+ label: string;
14
+ primary?: boolean;
15
+ nav?: string;
16
+ act?: string;
17
+ run?: () => void;
18
+ }
19
+ export interface Notif {
20
+ id: string;
21
+ kind: NotifKind;
22
+ title: string;
23
+ body: string;
24
+ ts: number;
25
+ /** Replaces an earlier notification with the same key. */
26
+ key?: string;
27
+ /** The workspace an agent notification is about: a click goes there. */
28
+ wsId?: string;
29
+ /** Where a click on the card itself goes, when it is not about a workspace. */
30
+ nav?: string;
31
+ /** Who posted it, shown beside the time: a plugin's name. */
32
+ source?: string;
33
+ actions?: NotifAction[];
34
+ /** Seen: the bell has been opened since it came. Read: the bell was closed after that. */
35
+ seen?: boolean;
36
+ read?: boolean;
37
+ }
38
+ export type Card = Notif & {
39
+ sticky: boolean;
40
+ };
41
+ /** The kinds Settings lists. What's new counts as an update. */
42
+ export type PrefKind = "input" | "done" | "attention" | "activity" | "update" | "error" | "plugin";
43
+ export type Channel = "card" | "bell" | "sound" | "os";
44
+ export declare const PREF_KINDS: {
45
+ kind: PrefKind;
46
+ label: string;
47
+ desc: string;
48
+ }[];
49
+ /**
50
+ * Whether a kind shows on a channel. Until it is set in Settings › Notifications, the agent kinds
51
+ * follow the four switches that Settings › AI agents used to have (on at all, finished, needs input,
52
+ * Windows), so nobody's choice flips.
53
+ */
54
+ export declare function prefFor(kind: PrefKind, ch: Channel): boolean;
55
+ export declare const useNotifCards: () => Card[];
56
+ export declare function useNotifHistory(): Notif[];
57
+ /** Whether Deck is the window in front, for a caller that only speaks up when you are away. */
58
+ export declare const deckInFront: () => boolean;
59
+ /**
60
+ * Post a notification. Returns its id, or "" when the user has every channel for its kind off.
61
+ * `transient`: a card only, never kept in the bell, for something in progress that a result will
62
+ * replace or resolveKey will take down (a hot reload while it runs).
63
+ */
64
+ export declare function notify(n: Omit<Notif, "id" | "ts" | "seen" | "read"> & {
65
+ sticky?: boolean;
66
+ transient?: boolean;
67
+ }): string;
68
+ /** The card's ✕: it goes, and its key stays quiet (see notify) until resolved or acted on. */
69
+ export declare function closeCard(id: string): void;
70
+ /** The card goes; the bell keeps it. */
71
+ export declare function dismissCard(id: string): void;
72
+ /** Gone from the bell, and its card with it. */
73
+ export declare function removeNotif(id: string): void;
74
+ /** What a key was about is dealt with (an agent was answered): its card goes, its row is read. */
75
+ export declare function resolveKey(key: string): void;
76
+ export declare function clearNotifs(): void;
77
+ /** The bell was opened: the badge clears, the rows stay lifted until it closes. */
78
+ export declare function markSeen(): void;
79
+ export declare function markRead(): void;
80
+ /** What a persisted action's `act` runs. Registered by the module that posts it, at import. */
81
+ export declare function onNotifAction(name: string, run: () => unknown): void;
82
+ /** A click on the card or the row itself: where it is about, then the card goes. */
83
+ export declare function openNotif(n: Notif): void;
84
+ export declare function runAction(n: Notif, a: NotifAction): void;
@@ -0,0 +1,39 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ export interface PluginNotification {
3
+ title: string;
4
+ /**
5
+ * Which of Settings › Notifications' rows it follows. "plugin" (the default) for a plugin's own
6
+ * news; "attention" for something that needs the user now (a meeting starting, a request to
7
+ * join), which also reaches Windows while Deck is behind; "activity" for something that finished
8
+ * in the background; "error" for a failure.
9
+ */
10
+ kind?: "plugin" | "attention" | "activity" | "error";
11
+ body?: string;
12
+ /** The plugin's name, shown beside the time. */
13
+ source: string;
14
+ /** Replaces this plugin's earlier notification with the same key, rather than adding another. */
15
+ key?: string;
16
+ /** Stays until dismissed instead of going after a few seconds. The bell keeps it either way. */
17
+ sticky?: boolean;
18
+ /**
19
+ * Something in progress: a card only, with no sound, never kept in the bell. Take it down with
20
+ * dismissNotification when it is done, or replace it (same key) with the result.
21
+ */
22
+ transient?: boolean;
23
+ /**
24
+ * Buttons on the card and on its bell row. `run` is the plugin's own function, so it lasts only
25
+ * as long as this session: after a restart the row is still in the bell, without its buttons.
26
+ */
27
+ actions?: {
28
+ label: string;
29
+ primary?: boolean;
30
+ run: () => void;
31
+ }[];
32
+ }
33
+ /**
34
+ * Post a notification: a card in the corner and a row in the bell, as Settings › Notifications
35
+ * says for plugins. For a passing word ("Copied") use toast() instead, which the bell does not keep.
36
+ */
37
+ export declare function notify(n: PluginNotification): void;
38
+ /** Take down this plugin's notification with that key: its card goes, its bell row is marked read. */
39
+ export declare function dismissNotification(source: string, key: string): void;
@@ -50,6 +50,8 @@ export interface LayoutWorkspace {
50
50
  cwd: string;
51
51
  tabs: LayoutTab[];
52
52
  activeTab: string;
53
+ /** Its colour on the sidebar's collapsed rail, by index (Terminals' TONES); none picks one from the name. */
54
+ color?: number;
53
55
  }
54
56
  export interface Layout {
55
57
  workspaces: LayoutWorkspace[];
@@ -300,6 +302,11 @@ export declare function moveWorkspace(id: string, toIndex: number): void;
300
302
  * Empty for a pane that has not spawned yet, which is the honest answer — there is nothing in it.
301
303
  */
302
304
  export declare function paneLines(id: string, max?: number): string[];
305
+ /**
306
+ * Open a file in Deck the way its file tree does: in the plugin that opens its type (a .pdf in the
307
+ * PDF plugin), otherwise in this workspace's Editor, at `line` when given.
308
+ */
309
+ export declare function openFile(path: string, line?: number): void;
303
310
  export declare function getInstance(id: string): Instance;
304
311
  /**
305
312
  * Wrap pasted text in bracketed-paste markers, so the receiving app can tell one paste from
@@ -0,0 +1,19 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ import { type RefObject } from "react";
3
+ import { monaco } from "../../core/monaco";
4
+ import { type DirtyRange } from "./hunks";
5
+ /**
6
+ * The peek, for the editor in `edRef` showing `path` with the gutter's `ranges`. Returns what to
7
+ * render (a portal into the overlay), or null while closed.
8
+ *
9
+ * `clean` is whether the editor holds what is on disk: the changes are git's, read from disk, so
10
+ * their line numbers only fit the buffer when it has no unsaved edits. Staging and reverting wait
11
+ * for a save otherwise. `readBase` gives the text a change is against: the index's copy of the
12
+ * file for a change in the working tree, HEAD's for a staged one.
13
+ */
14
+ export declare function useDiffPeek(edRef: RefObject<monaco.editor.IStandaloneCodeEditor | null>, path: string, ranges: DirtyRange[] | undefined, opts: {
15
+ clean: boolean;
16
+ onStage: (r: DirtyRange) => Promise<void>;
17
+ onUnstage: (r: DirtyRange) => Promise<void>;
18
+ readBase: (staged: boolean) => Promise<string>;
19
+ }): import("react").ReactPortal | null;
@@ -1,8 +1,8 @@
1
1
  // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
2
  import { monaco } from "../../core/monaco";
3
3
  import { type EditorSettings } from "../../core/editorsettings";
4
- import type { DirtyRange } from "./tree";
5
- declare function MonacoEditorInner({ path, rel, value, onChange, onSave, gotoLine, gotoCol, gotoNonce, highlight, dirty, settings, onEditor }: {
4
+ import type { DirtyRange } from "./hunks";
5
+ declare function MonacoEditorInner({ path, rel, value, onChange, onSave, gotoLine, gotoCol, gotoNonce, highlight, dirty, settings, onEditor, clean, onStageChange, onUnstageChange, onReadBase }: {
6
6
  path: string;
7
7
  rel?: string | null;
8
8
  value: string;
@@ -22,6 +22,13 @@ declare function MonacoEditorInner({ path, rel, value, onChange, onSave, gotoLin
22
22
  /** Hands the live editor out, and null on unmount. For a formatting toolbar, which has to
23
23
  * dispatch into this instance rather than rewrite the string around it. */
24
24
  onEditor?: (e: monaco.editor.IStandaloneCodeEditor | null) => void;
25
+ /** The buffer matches the file on disk, which the gutter's changes were read from. */
26
+ clean?: boolean;
27
+ /** Stage or unstage one change from the gutter's peek (DiffPeek.tsx). */
28
+ onStageChange?: (r: DirtyRange) => Promise<void>;
29
+ onUnstageChange?: (r: DirtyRange) => Promise<void>;
30
+ /** The text the file's changes are against: the index's copy, or HEAD's for a staged change. */
31
+ onReadBase?: (staged: boolean) => Promise<string>;
25
32
  }): import("react").JSX.Element;
26
33
  /**
27
34
  * Monaco owns its buffer, so this component re-rendering achieves nothing on its own — yet it was
@@ -35,13 +42,19 @@ declare function MonacoEditorInner({ path, rel, value, onChange, onSave, gotoLin
35
42
  */
36
43
  export declare const MonacoEditor: import("react").MemoExoticComponent<typeof MonacoEditorInner>;
37
44
  export declare function applyLineChanges(original: monaco.editor.ITextModel, modified: monaco.editor.ITextModel, diffs: monaco.editor.ILineChange[]): string;
45
+ type HunkRun = (change: monaco.editor.ILineChange, models: {
46
+ original: monaco.editor.ITextModel;
47
+ modified: monaco.editor.ITextModel;
48
+ }) => void;
49
+ /**
50
+ * Per-change buttons in a diff's gutter: stage (or unstage) one change, and, given `revert`, put
51
+ * one change back to the left side's text. Each change gets them at its first line.
52
+ */
38
53
  export interface HunkAction {
39
54
  label: string;
40
55
  unstage: boolean;
41
- run: (change: monaco.editor.ILineChange, models: {
42
- original: monaco.editor.ITextModel;
43
- modified: monaco.editor.ITextModel;
44
- }) => void;
56
+ run: HunkRun;
57
+ revert?: HunkRun;
45
58
  }
46
59
  /** A side of a diff: LEFT the old version, RIGHT the new — GitHub's names, which line comments use. */
47
60
  export type DiffSide = "LEFT" | "RIGHT";
@@ -0,0 +1,3 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ /** A Monaco language id (only ones Monaco ships), "plaintext" when nothing stands out. */
3
+ export declare function detectLanguage(text: string): string;
@@ -10,6 +10,8 @@ export interface EditorStatus {
10
10
  author: string;
11
11
  summary: string;
12
12
  } | null;
13
+ /** The shown model's Monaco language id: an untitled buffer's changes as it is detected. */
14
+ lang?: string;
13
15
  }
14
16
  export declare let editorStatus: EditorStatus;
15
17
  export declare function setEditorStatus(patch: Partial<EditorStatus>): void;
@@ -0,0 +1,54 @@
1
+ // GENERATED by sdk/gen-types.mjs from Deck's source — do not edit.
2
+ /** One change: lines `oldStart..` of the base replaced by lines `newStart..` of the file. */
3
+ export interface Hunk {
4
+ oldStart: number;
5
+ oldCount: number;
6
+ /** For a deletion (newCount 0), the line the removed lines were after; 0 at the very top. */
7
+ newStart: number;
8
+ newCount: number;
9
+ /** The base's lines and the file's, without git's prefix or a trailing \r. */
10
+ removed: string[];
11
+ added: string[];
12
+ /** The hunk exactly as git printed it, from its @@ line on, for a patch. */
13
+ raw: string[];
14
+ }
15
+ /** One file's diff: the lines before the first hunk (its header), and the hunks. */
16
+ export interface FileDiff {
17
+ header: string[];
18
+ hunks: Hunk[];
19
+ }
20
+ /** A changed line range in the file, for the gutter. */
21
+ export interface DirtyRange {
22
+ start: number;
23
+ end: number;
24
+ type: "added" | "modified" | "deleted";
25
+ /** Staged: in the index already, so shown dimmed. */
26
+ staged?: boolean;
27
+ hunk: Hunk;
28
+ }
29
+ /** Parse `git diff --unified=0` for one file. Empty text is an empty diff. */
30
+ export declare function parseDiff(diff: string): FileDiff;
31
+ /** Where a hunk sits in the file. A deletion is drawn on the line it follows (the first, at the top). */
32
+ export declare function rangeOf(h: Hunk): Omit<DirtyRange, "hunk">;
33
+ /**
34
+ * The gutter's ranges: every unstaged change, and every staged one that has not been changed again
35
+ * since it was staged.
36
+ *
37
+ * `unstaged` is the file against the index; `sinceHead`, when given, the file against HEAD. Both
38
+ * are in the file's own line numbers, which a diff of the index against HEAD (`--cached`) would
39
+ * not be once there are unstaged edits too. A change against HEAD that touches no unstaged line is
40
+ * entirely in the index: that is a staged one.
41
+ */
42
+ export declare function dirtyRanges(unstaged: FileDiff, sinceHead?: FileDiff): DirtyRange[];
43
+ /** A patch holding just this hunk, for `git apply --cached --unidiff-zero`. */
44
+ export declare function hunkPatch(file: FileDiff, h: Hunk): string;
45
+ /** The hunk in `file` with the same removed and added lines as `h`: a staged change, found in `--cached`. */
46
+ export declare function sameHunk(file: FileDiff, h: Hunk): Hunk | undefined;
47
+ /**
48
+ * The edit that puts a hunk's base lines back in the file, as a range in 1-based lines and
49
+ * columns and its replacement text. `lineCount` and `maxColumn` describe the file as it is.
50
+ */
51
+ export declare function revertEdit(h: Hunk, lineCount: number, maxColumn: (line: number) => number, eol?: string): {
52
+ range: [number, number, number, number];
53
+ text: string;
54
+ };