@silo-code/sdk 0.20.0 → 0.22.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/dist/context-keys.d.ts +18 -3
- package/dist/context-keys.d.ts.map +1 -1
- package/dist/domain-types.d.ts +8 -32
- package/dist/domain-types.d.ts.map +1 -1
- package/dist/editor-service.d.ts +135 -3
- package/dist/editor-service.d.ts.map +1 -1
- package/dist/event.d.ts +28 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +2 -0
- package/dist/event.js.map +1 -0
- package/dist/extension-storage.d.ts +7 -3
- package/dist/extension-storage.d.ts.map +1 -1
- package/dist/file-service.d.ts +48 -4
- package/dist/file-service.d.ts.map +1 -1
- package/dist/index.d.ts +17 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -5
- package/dist/index.js.map +1 -1
- package/dist/layout-service.d.ts +13 -13
- package/dist/layout-service.d.ts.map +1 -1
- package/dist/network-service.d.ts +70 -4
- package/dist/network-service.d.ts.map +1 -1
- package/dist/network-service.js +35 -1
- package/dist/network-service.js.map +1 -1
- package/dist/path.d.ts +62 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +150 -0
- package/dist/path.js.map +1 -0
- package/dist/process-service.d.ts +24 -4
- package/dist/process-service.d.ts.map +1 -1
- package/dist/processes-service.d.ts +1 -1
- package/dist/search-service.d.ts +11 -0
- package/dist/search-service.d.ts.map +1 -1
- package/dist/system-service.d.ts +2 -2
- package/dist/terminal-service.d.ts +66 -0
- package/dist/terminal-service.d.ts.map +1 -1
- package/dist/theme-service.d.ts +23 -7
- package/dist/theme-service.d.ts.map +1 -1
- package/dist/types.d.ts +102 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/workspace-service.d.ts +13 -0
- package/dist/workspace-service.d.ts.map +1 -1
- package/package.json +2 -4
- package/src/context-keys.ts +18 -3
- package/src/domain-types.ts +8 -29
- package/src/editor-service.ts +141 -5
- package/src/event.ts +28 -0
- package/src/extension-storage.ts +8 -3
- package/src/file-service.ts +49 -4
- package/src/index.ts +31 -6
- package/src/layout-service.ts +15 -13
- package/src/network-service.ts +85 -4
- package/src/path.test.ts +135 -0
- package/src/path.ts +188 -0
- package/src/process-service.ts +24 -4
- package/src/processes-service.ts +1 -1
- package/src/search-service.ts +11 -0
- package/src/system-service.ts +2 -2
- package/src/terminal-service.ts +71 -0
- package/src/theme-service.ts +23 -7
- package/src/types.ts +104 -25
- package/src/workspace-service.ts +13 -0
package/src/process-service.ts
CHANGED
|
@@ -67,6 +67,24 @@ export interface ProcessExecOptions {
|
|
|
67
67
|
* {@link Permission}. First-party (bundled) extensions are unscoped.
|
|
68
68
|
*/
|
|
69
69
|
cwd?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Extra environment variables, **merged over** the host's environment (the
|
|
72
|
+
* command inherits the host env; these keys add to or override it). Use it to
|
|
73
|
+
* set things like `GIT_PAGER=cat` or a locale without clobbering `PATH`.
|
|
74
|
+
*/
|
|
75
|
+
env?: Record<string, string>;
|
|
76
|
+
/**
|
|
77
|
+
* Kill the process and reject after this many milliseconds. The whole process
|
|
78
|
+
* group is terminated (not just the direct child), so shell wrappers don't
|
|
79
|
+
* leak orphans. The rejection is an `Error` whose `name` is `"AbortError"`.
|
|
80
|
+
*/
|
|
81
|
+
timeoutMs?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Abort handle. Aborting kills the process (and its group) and rejects the
|
|
84
|
+
* `exec` promise with an `Error` whose `name` is `"AbortError"` — the same
|
|
85
|
+
* shape as a `timeoutMs` expiry, so callers branch on `err.name`.
|
|
86
|
+
*/
|
|
87
|
+
signal?: AbortSignal;
|
|
70
88
|
}
|
|
71
89
|
|
|
72
90
|
/**
|
|
@@ -116,10 +134,12 @@ export interface ProcessService {
|
|
|
116
134
|
* interactive sessions instead.
|
|
117
135
|
*
|
|
118
136
|
* Runs **off the UI thread**, so a slow or network-bound command never
|
|
119
|
-
* stutters the app. The returned promise rejects
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
137
|
+
* stutters the app. The returned promise rejects if the process could not be
|
|
138
|
+
* spawned (e.g. the command was not found), or if a
|
|
139
|
+
* {@link ProcessExecOptions.timeoutMs | timeout} / {@link ProcessExecOptions.signal | abort}
|
|
140
|
+
* fires (an `Error` with `name === "AbortError"`); a command that runs to
|
|
141
|
+
* completion but exits non-zero **resolves** — check
|
|
142
|
+
* {@link ProcessExecResult.code} and {@link ProcessExecResult.stderr}.
|
|
123
143
|
*
|
|
124
144
|
* @param command - Executable to run (resolved via `PATH`), e.g. `"git"`.
|
|
125
145
|
* @param args - Arguments passed verbatim — not shell-interpreted, so no
|
package/src/processes-service.ts
CHANGED
|
@@ -88,7 +88,7 @@ export interface ProcessInfo {
|
|
|
88
88
|
* // Notify when all agents in the workspace are idle.
|
|
89
89
|
* const sub = ctx.processes.subscribe((procs) => {
|
|
90
90
|
* const allIdle = procs.every((p) => p.atPrompt);
|
|
91
|
-
* if (allIdle) ctx.ui.notify(
|
|
91
|
+
* if (allIdle) ctx.ui.notify("info", "All agents finished");
|
|
92
92
|
* });
|
|
93
93
|
* ctx.subscriptions.push(sub);
|
|
94
94
|
*
|
package/src/search-service.ts
CHANGED
|
@@ -43,6 +43,17 @@ export interface SearchOptions {
|
|
|
43
43
|
* is hit, the search stops early and {@link SearchResponse.truncated} is true.
|
|
44
44
|
*/
|
|
45
45
|
maxResults?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Cancel the search. When the signal aborts, the promise returned by
|
|
48
|
+
* {@link SearchService.search} rejects with an `Error` whose `name` is
|
|
49
|
+
* `"AbortError"` (the `fetch` convention — branch on `err.name`).
|
|
50
|
+
*
|
|
51
|
+
* Cancellation is observable immediately, but the native search may still run
|
|
52
|
+
* to completion in the background — its result is simply discarded. Use this
|
|
53
|
+
* to abandon a stale query (e.g. superseded by the next keystroke) rather than
|
|
54
|
+
* to reclaim native CPU the instant you abort.
|
|
55
|
+
*/
|
|
56
|
+
signal?: AbortSignal;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
/**
|
package/src/system-service.ts
CHANGED
|
@@ -53,13 +53,13 @@ export interface SystemInfo {
|
|
|
53
53
|
* ctx.subscriptions.push(
|
|
54
54
|
* ctx.registerCommand({
|
|
55
55
|
* id: "my.reveal-in-finder",
|
|
56
|
-
*
|
|
56
|
+
* label: "Reveal in Finder",
|
|
57
57
|
* run() { ... },
|
|
58
58
|
* }),
|
|
59
59
|
* );
|
|
60
60
|
* }
|
|
61
61
|
*
|
|
62
|
-
* ctx.ui.notify(
|
|
62
|
+
* ctx.ui.notify("info", `Running Silo ${siloVersion} on ${os}/${arch}`);
|
|
63
63
|
* },
|
|
64
64
|
* };
|
|
65
65
|
* ```
|
package/src/terminal-service.ts
CHANGED
|
@@ -98,11 +98,51 @@ export interface TerminalService {
|
|
|
98
98
|
* Open a new terminal in a workspace (defaults to the active one). Returns the
|
|
99
99
|
* created {@link TerminalRecord}; the PTY session spawns lazily when its tab
|
|
100
100
|
* mounts.
|
|
101
|
+
*
|
|
102
|
+
* Returns `undefined` only when `input.workspaceId` is not given and there is
|
|
103
|
+
* no active workspace at the time of the call — in normal use this does not
|
|
104
|
+
* happen because activating any workspace happens before extensions run.
|
|
101
105
|
*/
|
|
102
106
|
create(input?: CreateTerminalInput): TerminalRecord | undefined;
|
|
103
107
|
/** Close and kill every terminal in a workspace (e.g. on workspace delete). */
|
|
104
108
|
closeWorkspace(workspaceId: string): void;
|
|
105
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Write text to a terminal's PTY as if the user typed it. By default a
|
|
112
|
+
* carriage return is appended so the line executes; pass `addNewline: false`
|
|
113
|
+
* to stage text without running it.
|
|
114
|
+
*
|
|
115
|
+
* Works even if the terminal tab has never been shown: the PTY spawns lazily
|
|
116
|
+
* on first mount, and `sendText` force-spawns it on demand (a later mount then
|
|
117
|
+
* attaches to that same session). No-op for an unknown `terminalId`.
|
|
118
|
+
*
|
|
119
|
+
* @param terminalId - The {@link TerminalRecord.id} to write to.
|
|
120
|
+
* @param text - The text to send.
|
|
121
|
+
* @param addNewline - Append a carriage return to execute. Defaults to `true`.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* const term = ctx.terminals.create({ cwd: workspaceFolder });
|
|
126
|
+
* if (term) ctx.terminals.sendText(term.id, "npm run build");
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
sendText(terminalId: string, text: string, addNewline?: boolean): void;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Close one terminal tab and kill its PTY session. No-op if the id is unknown.
|
|
133
|
+
* To reap every terminal in a workspace at once use
|
|
134
|
+
* {@link TerminalService.closeWorkspace}.
|
|
135
|
+
*/
|
|
136
|
+
close(terminalId: string): void;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Set a terminal's user-facing name ({@link TerminalRecord.customName}),
|
|
140
|
+
* shown on its tab and persisted across restarts. Passing an empty string
|
|
141
|
+
* clears the custom name, letting the PTY-derived title take over again.
|
|
142
|
+
* No-op for an unknown `terminalId`.
|
|
143
|
+
*/
|
|
144
|
+
rename(terminalId: string, name: string): void;
|
|
145
|
+
|
|
106
146
|
/**
|
|
107
147
|
* Switch to the workspace containing this terminal and activate its tab in
|
|
108
148
|
* the center dock. No-ops if the terminal id is unknown.
|
|
@@ -168,4 +208,35 @@ export interface TerminalService {
|
|
|
168
208
|
terminalId: string,
|
|
169
209
|
handler: (event: OscEvent) => void,
|
|
170
210
|
): Disposable;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* The record id of the terminal tab that is currently active in the active
|
|
214
|
+
* workspace's center dock, or `null` when an editor tab (or nothing) is
|
|
215
|
+
* active. "Active" is the dock's single active panel — the tab the user is
|
|
216
|
+
* looking at and typing into — so a terminal merely visible in a non-active
|
|
217
|
+
* split does not count.
|
|
218
|
+
*/
|
|
219
|
+
getActive(): string | null;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Subscribe to active-terminal changes. The listener receives the terminal
|
|
223
|
+
* record id whenever a terminal tab becomes the active center-dock panel,
|
|
224
|
+
* and `null` when activation moves elsewhere (an editor tab, or no panel —
|
|
225
|
+
* including transiently during a workspace switch, before the incoming
|
|
226
|
+
* workspace's active tab is published).
|
|
227
|
+
*
|
|
228
|
+
* Fires on tab activation, group activation, and workspace switches.
|
|
229
|
+
* Returns a {@link Disposable} that cancels the subscription.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* // Clear a "needs attention" marker once the user views the terminal.
|
|
234
|
+
* ctx.subscriptions.push(
|
|
235
|
+
* ctx.terminals.subscribeActive((terminalId) => {
|
|
236
|
+
* if (terminalId) attention.delete(terminalId);
|
|
237
|
+
* }),
|
|
238
|
+
* );
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
subscribeActive(listener: (terminalId: string | null) => void): Disposable;
|
|
171
242
|
}
|
package/src/theme-service.ts
CHANGED
|
@@ -15,11 +15,11 @@ export type {
|
|
|
15
15
|
} from "./domain-types";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* A selectable theme contributed via
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* A selectable theme contributed via {@link ThemeService.registerPreset}.
|
|
19
|
+
* Built-in presets (Tokyo Night, Solarized Light, Gruvbox Dark, …) are
|
|
20
|
+
* registered by the `theme-presets` extension; core ships only Dark and Light.
|
|
21
|
+
* A preset's {@link ThemePreset.vars} are injected as CSS custom properties
|
|
22
|
+
* when it is the active theme.
|
|
23
23
|
*
|
|
24
24
|
* @category Registration
|
|
25
25
|
* @public
|
|
@@ -74,8 +74,7 @@ export interface ThemeState {
|
|
|
74
74
|
* Read via {@link ThemeService.getState | getState} /
|
|
75
75
|
* {@link ThemeService.subscribe | subscribe} (e.g. with `useSyncExternalStore`);
|
|
76
76
|
* drive via {@link ThemeService.setActive | setActive} and the custom-theme
|
|
77
|
-
* methods.
|
|
78
|
-
* {@link ExtensionContext.registerThemePreset}.
|
|
77
|
+
* methods. Contribute a new preset via {@link ThemeService.registerPreset}.
|
|
79
78
|
*
|
|
80
79
|
* @category Consumer Services
|
|
81
80
|
* @public
|
|
@@ -99,4 +98,21 @@ export interface ThemeService {
|
|
|
99
98
|
exportTheme(theme: CustomTheme): ThemeExport;
|
|
100
99
|
/** Validate/parse imported JSON into a custom theme (assigns a fresh id). */
|
|
101
100
|
importTheme(data: unknown): CustomTheme;
|
|
101
|
+
/**
|
|
102
|
+
* Register a {@link ThemePreset} (a selectable theme in the picker). The
|
|
103
|
+
* preset appears immediately and is removed when the returned
|
|
104
|
+
* {@link Disposable} is disposed (typically when the extension deactivates).
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* ctx.theme.registerPreset({
|
|
109
|
+
* id: "my-theme",
|
|
110
|
+
* name: "My Theme",
|
|
111
|
+
* base: "dark",
|
|
112
|
+
* colorScheme: "dark",
|
|
113
|
+
* vars: { "--silo-color-bg": "#1a1a2e" },
|
|
114
|
+
* });
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
registerPreset(preset: ThemePreset): Disposable;
|
|
102
118
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Silo extension API — types
|
|
2
|
+
* The Silo extension API — types-first contract plus a small set of blessed
|
|
3
|
+
* runtime helpers.
|
|
3
4
|
*
|
|
4
5
|
* Everything an extension author can see at compile time lives here (plus the
|
|
5
6
|
* service interfaces in the sibling `*-service` files, which this module
|
|
@@ -8,6 +9,12 @@
|
|
|
8
9
|
* never import the host. This is the VS Code (`vscode.d.ts`) / Obsidian
|
|
9
10
|
* (`obsidian-api`) model.
|
|
10
11
|
*
|
|
12
|
+
* **Runtime exports:** the SDK also ships a small set of blessed runtime
|
|
13
|
+
* helpers (`Tooltip`, `useFocusGroup`, `useServiceState`, `DND_MIME`,
|
|
14
|
+
* `PathDeniedError`, `NetworkError`) and peer-depends on React 19. Changes to
|
|
15
|
+
* these can be breaking even when the types are unchanged — treat them with
|
|
16
|
+
* the same care as the type surface.
|
|
17
|
+
*
|
|
11
18
|
* Start with {@link Extension} (the unit you export) and
|
|
12
19
|
* {@link ExtensionContext} (the `ctx` the host hands you).
|
|
13
20
|
*
|
|
@@ -18,7 +25,6 @@
|
|
|
18
25
|
* @packageDocumentation
|
|
19
26
|
*/
|
|
20
27
|
import type React from "react";
|
|
21
|
-
import type { IDockviewPanelProps } from "dockview";
|
|
22
28
|
import type { ContextKeys } from "./context-keys";
|
|
23
29
|
import type { WorkspaceService } from "./workspace-service";
|
|
24
30
|
import type { EditorService } from "./editor-service";
|
|
@@ -54,26 +60,70 @@ export interface Disposable {
|
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
/**
|
|
57
|
-
* The
|
|
58
|
-
* drive the panel's own tab (title, close, focus)
|
|
59
|
-
*
|
|
63
|
+
* The panel API handed to a {@link DockPanelKind} component. Use these methods
|
|
64
|
+
* to drive the panel's own tab (title, close, focus) and update its stored
|
|
65
|
+
* parameters. The host provides the implementation; extensions never construct
|
|
66
|
+
* this object directly.
|
|
60
67
|
*
|
|
61
68
|
* @category Core Types
|
|
62
69
|
* @public
|
|
63
70
|
*/
|
|
64
|
-
export
|
|
71
|
+
export interface DockPanelApi {
|
|
72
|
+
/** Update the title shown in the panel's tab. */
|
|
73
|
+
setTitle(title: string): void;
|
|
74
|
+
/** Programmatically close this panel. */
|
|
75
|
+
close(): void;
|
|
76
|
+
/** Bring this panel to focus (make it the active panel in its group). */
|
|
77
|
+
setActive(): void;
|
|
78
|
+
/** `true` while this panel is the active one in its dock group. */
|
|
79
|
+
readonly isActive: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Subscribe to active-state transitions. The listener is called whenever
|
|
82
|
+
* the panel gains or loses active status, with an event carrying the new
|
|
83
|
+
* state. Returns a {@link Disposable} that cancels the subscription.
|
|
84
|
+
*/
|
|
85
|
+
onDidActiveChange(
|
|
86
|
+
listener: (event: { readonly isActive: boolean }) => void,
|
|
87
|
+
): Disposable;
|
|
88
|
+
/**
|
|
89
|
+
* `true` while this panel is visible — its tab is the selected one in its
|
|
90
|
+
* group. Distinct from {@link DockPanelApi.isActive | isActive}: with split
|
|
91
|
+
* groups, every group's selected tab is visible but only one panel in the
|
|
92
|
+
* whole dock is active.
|
|
93
|
+
*/
|
|
94
|
+
readonly isVisible: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Subscribe to visibility transitions (the panel's tab being selected or
|
|
97
|
+
* deselected in its group). Use to pause expensive work while hidden, or to
|
|
98
|
+
* re-measure on reveal (e.g. the terminal refits xterm when its tab becomes
|
|
99
|
+
* visible again). Returns a {@link Disposable} that cancels the subscription.
|
|
100
|
+
*/
|
|
101
|
+
onDidVisibilityChange(
|
|
102
|
+
listener: (event: { readonly isVisible: boolean }) => void,
|
|
103
|
+
): Disposable;
|
|
104
|
+
/**
|
|
105
|
+
* Shallow-merge `params` into this panel's stored parameters. Keys absent
|
|
106
|
+
* from `params` are left unchanged. Useful for keeping tabs-serializable
|
|
107
|
+
* state (e.g. the open URL in a web-viewer panel) consistent with the UI.
|
|
108
|
+
*/
|
|
109
|
+
updateParameters(params: object): void;
|
|
110
|
+
}
|
|
65
111
|
|
|
66
112
|
/**
|
|
67
113
|
* Props handed to a {@link DockPanelKind} component. Use this type to annotate
|
|
68
|
-
* your component instead of importing
|
|
69
|
-
* directly — the SDK
|
|
70
|
-
*
|
|
114
|
+
* your component instead of importing from the underlying dock framework
|
|
115
|
+
* directly — the SDK owns this surface so extensions remain insulated from
|
|
116
|
+
* host implementation details. The optional generic `T` narrows `params`.
|
|
71
117
|
*
|
|
72
118
|
* @category Core Types
|
|
73
119
|
* @public
|
|
74
120
|
*/
|
|
75
|
-
export
|
|
76
|
-
|
|
121
|
+
export interface DockPanelProps<T extends object = Record<string, unknown>> {
|
|
122
|
+
/** The panel API — drives the tab (title, close, focus, params). */
|
|
123
|
+
api: DockPanelApi;
|
|
124
|
+
/** Serializable parameters forwarded to the panel at open time. */
|
|
125
|
+
params: T;
|
|
126
|
+
}
|
|
77
127
|
|
|
78
128
|
/**
|
|
79
129
|
* Props passed to an {@link Editor} component. An editor renders the contents of
|
|
@@ -164,10 +214,10 @@ export interface NewFileTemplate {
|
|
|
164
214
|
|
|
165
215
|
/**
|
|
166
216
|
* Declarative metadata about a file extension — the open-ended counterpart to
|
|
167
|
-
*
|
|
168
|
-
* surfaces (and, later, tab/explorer icons) can
|
|
169
|
-
* FileType does not register
|
|
170
|
-
* extension at dispatch time.
|
|
217
|
+
* {@link Editor} (which is purely a presenter/renderer). A single source of
|
|
218
|
+
* truth that "New File" surfaces (and, later, tab/explorer icons) can
|
|
219
|
+
* enumerate. Registering a FileType does not register an Editor; the two are
|
|
220
|
+
* matched independently by extension at dispatch time.
|
|
171
221
|
*
|
|
172
222
|
* @category Registration
|
|
173
223
|
* @public
|
|
@@ -196,8 +246,15 @@ export interface Command {
|
|
|
196
246
|
id: string;
|
|
197
247
|
/** Human-readable label (shown where the command surfaces in UI). */
|
|
198
248
|
label: string;
|
|
199
|
-
/**
|
|
200
|
-
|
|
249
|
+
/**
|
|
250
|
+
* The action. May accept arguments passed through from
|
|
251
|
+
* {@link ExtensionContext.executeCommand} and may return a value (sync or
|
|
252
|
+
* async); `executeCommand` resolves with whatever this returns.
|
|
253
|
+
*
|
|
254
|
+
* Zero-argument, void-returning commands are still valid — `() => void`
|
|
255
|
+
* satisfies this type, so existing registrations compile unchanged.
|
|
256
|
+
*/
|
|
257
|
+
run: (...args: unknown[]) => unknown | Promise<unknown>;
|
|
201
258
|
}
|
|
202
259
|
|
|
203
260
|
/**
|
|
@@ -325,16 +382,19 @@ export interface SidePanel {
|
|
|
325
382
|
|
|
326
383
|
/**
|
|
327
384
|
* Registers a kind of dock panel (a tab that can live in the center dock area,
|
|
328
|
-
* e.g. the terminal). Workspaces open panels of registered kinds by id.
|
|
385
|
+
* e.g. the terminal). Workspaces open panels of registered kinds by id. The
|
|
386
|
+
* optional generic `T` is the shape of the params this kind's panels are
|
|
387
|
+
* opened with — annotate your component with `DockPanelProps<T>` and
|
|
388
|
+
* {@link ExtensionContext.registerDockPanelKind} infers it, no casts needed.
|
|
329
389
|
*
|
|
330
390
|
* @category Registration
|
|
331
391
|
* @public
|
|
332
392
|
*/
|
|
333
|
-
export interface DockPanelKind {
|
|
393
|
+
export interface DockPanelKind<T extends object = Record<string, unknown>> {
|
|
334
394
|
/** Unique id for this panel kind. */
|
|
335
395
|
id: string;
|
|
336
|
-
/** The React component
|
|
337
|
-
component: React.ComponentType<
|
|
396
|
+
/** The React component that renders this panel; receives {@link DockPanelProps}. */
|
|
397
|
+
component: React.ComponentType<DockPanelProps<T>>;
|
|
338
398
|
/**
|
|
339
399
|
* When set, this kind appears as an entry in the center dock's **+** add
|
|
340
400
|
* menu (the per-group header button). Omit to keep the kind internal.
|
|
@@ -464,20 +524,39 @@ export interface ExtensionContext {
|
|
|
464
524
|
registerKeybinding(binding: Keybinding): Disposable;
|
|
465
525
|
/** Register a {@link SidePanel} (a left/right column panel). */
|
|
466
526
|
registerSidePanel(panel: SidePanel): Disposable;
|
|
467
|
-
/**
|
|
468
|
-
|
|
527
|
+
/**
|
|
528
|
+
* Register a {@link DockPanelKind} (a center-dock tab kind). The params
|
|
529
|
+
* generic `T` is inferred from the component's {@link DockPanelProps}
|
|
530
|
+
* annotation, so kinds with typed params register without casts.
|
|
531
|
+
*/
|
|
532
|
+
registerDockPanelKind<T extends object = Record<string, unknown>>(
|
|
533
|
+
kind: DockPanelKind<T>,
|
|
534
|
+
): Disposable;
|
|
469
535
|
/** Register a {@link StatusItem} (a status-bar widget). */
|
|
470
536
|
registerStatusItem(item: StatusItem): Disposable;
|
|
471
537
|
/** Register a {@link SettingsPage} (a page in the Settings dialog). */
|
|
472
538
|
registerSettingsPage(page: SettingsPage): Disposable;
|
|
473
|
-
/**
|
|
539
|
+
/**
|
|
540
|
+
* Register a {@link ThemePreset} (a selectable theme in the picker).
|
|
541
|
+
* @deprecated Use {@link ThemeService.registerPreset | ctx.theme.registerPreset()} instead.
|
|
542
|
+
* This method will be removed in a future release.
|
|
543
|
+
*/
|
|
474
544
|
registerThemePreset(preset: ThemePreset): Disposable;
|
|
475
545
|
/**
|
|
476
546
|
* Invoke a registered command by id — including commands contributed by
|
|
477
547
|
* other extensions. The minimal "operate" primitive; pairs with the typed
|
|
478
548
|
* services for read access.
|
|
549
|
+
*
|
|
550
|
+
* Optional positional `args` are forwarded to the command's
|
|
551
|
+
* {@link Command.run} function. The returned `Promise` resolves with the
|
|
552
|
+
* command's return value, or rejects if the command throws, is async and
|
|
553
|
+
* rejects, or the id is not registered. Sync commands dispatch synchronously
|
|
554
|
+
* before the promise settles, so callers that read state the command mutates
|
|
555
|
+
* immediately after `await executeCommand(…)` see the updated state.
|
|
556
|
+
*
|
|
557
|
+
* @typeParam T - Expected return type of the command (defaults to `unknown`).
|
|
479
558
|
*/
|
|
480
|
-
executeCommand(id: string):
|
|
559
|
+
executeCommand<T = unknown>(id: string, ...args: unknown[]): Promise<T>;
|
|
481
560
|
/**
|
|
482
561
|
* Consumer API for driving workspace state — create, rename, reorder,
|
|
483
562
|
* activate, soft close/reopen, and hard delete. Subscribe to a frozen
|
package/src/workspace-service.ts
CHANGED
|
@@ -170,6 +170,12 @@ export interface WorkspaceService {
|
|
|
170
170
|
createFromFolderPicker(): Promise<Workspace | null>;
|
|
171
171
|
create(input: CreateWorkspaceInput): Workspace;
|
|
172
172
|
rename(id: string, name: string): void;
|
|
173
|
+
/**
|
|
174
|
+
* Move a workspace to a new position relative to a reference workspace.
|
|
175
|
+
* @param from - Id of the workspace being dragged / moved.
|
|
176
|
+
* @param to - Id of the reference workspace (the insertion anchor).
|
|
177
|
+
* @param position - Whether to place `from` before or after `to`.
|
|
178
|
+
*/
|
|
173
179
|
reorder(from: string, to: string, position: "before" | "after"): void;
|
|
174
180
|
/** Activate (and reopen if closed). */
|
|
175
181
|
activate(id: string): void;
|
|
@@ -263,6 +269,13 @@ export interface WorkspaceService {
|
|
|
263
269
|
*
|
|
264
270
|
* The Workspaces panel subscribes internally to re-render when providers
|
|
265
271
|
* are added or removed.
|
|
272
|
+
*
|
|
273
|
+
* **No `invalidateSection` by design.** Unlike status rows and badges, a
|
|
274
|
+
* section is a live React component that re-renders on its own internal or
|
|
275
|
+
* context-driven state changes — it is not a snapshot returned from a
|
|
276
|
+
* `provide()` call, so there is nothing for the host to re-query. If a
|
|
277
|
+
* section needs to trigger a full workspace-panel refresh (rare), it should
|
|
278
|
+
* update its own state directly.
|
|
266
279
|
*/
|
|
267
280
|
subscribeSection(listener: () => void): Disposable;
|
|
268
281
|
|