@achasoft/dsh-advanced-sidebar 0.1.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/LICENSE +21 -0
- package/README.md +205 -0
- package/cordis.patch.yml +158 -0
- package/lib/client.js +24890 -0
- package/lib/client.js.map +1 -0
- package/lib/host.js +3156 -0
- package/lib/index.js +20 -0
- package/lib/remote.js +1994 -0
- package/lib/typert.host.js +2000 -0
- package/package.json +136 -0
- package/types/client/ActionMenu.d.ts +36 -0
- package/types/client/Glyphs.d.ts +49 -0
- package/types/client/PanelHost.d.ts +24 -0
- package/types/client/Seats.d.ts +16 -0
- package/types/client/SettingsCard.d.ts +22 -0
- package/types/client/contract.d.ts +358 -0
- package/types/client/controller.d.ts +224 -0
- package/types/client/cx.d.ts +16 -0
- package/types/client/index.d.ts +39 -0
- package/types/client/locales.d.ts +474 -0
- package/types/client/panels/ChangesPanel.d.ts +22 -0
- package/types/client/panels/FilesPanel.d.ts +16 -0
- package/types/client/panels/PreviewPanel.d.ts +27 -0
- package/types/client/panels/TasksPanel.d.ts +28 -0
- package/types/client/panels/TerminalPanel.d.ts +40 -0
- package/types/client/panels/shared.d.ts +65 -0
- package/types/client/target.d.ts +23 -0
- package/types/client/terminal-screen.d.ts +95 -0
- package/types/client/ui/Alert.d.ts +30 -0
- package/types/client/ui/Badge.d.ts +24 -0
- package/types/client/ui/Button.d.ts +28 -0
- package/types/client/ui/Calendar.d.ts +65 -0
- package/types/client/ui/DatePicker.d.ts +41 -0
- package/types/client/ui/Dialog.d.ts +61 -0
- package/types/client/ui/DropdownMenu.d.ts +98 -0
- package/types/client/ui/Input.d.ts +25 -0
- package/types/client/ui/Layer.d.ts +56 -0
- package/types/client/ui/Select.d.ts +49 -0
- package/types/client/ui/Separator.d.ts +15 -0
- package/types/client/ui/Tabs.d.ts +49 -0
- package/types/client/ui/Toggle.d.ts +57 -0
- package/types/client/ui/Tooltip.d.ts +22 -0
- package/types/client/ui/anchor.d.ts +92 -0
- package/types/client/ui/index.d.ts +42 -0
- package/types/client/use-capability.d.ts +27 -0
- package/types/host/deletion.d.ts +57 -0
- package/types/host/files.d.ts +43 -0
- package/types/host/git.d.ts +198 -0
- package/types/host/index.d.ts +210 -0
- package/types/host/open-in.d.ts +93 -0
- package/types/host/paths.d.ts +55 -0
- package/types/host/porcelain.d.ts +51 -0
- package/types/host/preview.d.ts +185 -0
- package/types/host/run.d.ts +72 -0
- package/types/host/tasks.d.ts +80 -0
- package/types/host/terminals.d.ts +86 -0
- package/types/host/types.d.ts +877 -0
- package/types/index.d.ts +17 -0
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract of the `advancedSidebar` Remote namespace, plus the shape of the
|
|
3
|
+
* `advanced-sidebar` settings section both halves address.
|
|
4
|
+
*
|
|
5
|
+
* Every endpoint returns a discriminated result rather than throwing: the RPC gateway erases a
|
|
6
|
+
* business exception into one opaque transport failure, and each panel's next move depends on which
|
|
7
|
+
* class the failure was — a missing `git` binary asks for an install, a denied path asks for a
|
|
8
|
+
* different workspace, and a timeout asks to retry.
|
|
9
|
+
* @module @achasoft/dsh-advanced-sidebar/host
|
|
10
|
+
*/
|
|
11
|
+
/** One external application the Open in submenu can hand a path to. */
|
|
12
|
+
export interface OpenInEditor {
|
|
13
|
+
/** Stable id used by the Open in request and by a profile patch overriding this row. */
|
|
14
|
+
readonly id: string;
|
|
15
|
+
/** Menu text. Deployment-owned, because the same command is called different things per install. */
|
|
16
|
+
readonly label: string;
|
|
17
|
+
/** Executable name or absolute path; resolved on the Host, never shell-interpreted. */
|
|
18
|
+
readonly command: string;
|
|
19
|
+
/**
|
|
20
|
+
* Arguments placed before the path. An empty list passes the path alone.
|
|
21
|
+
*
|
|
22
|
+
* Mutable, unlike every other field here: this one is validated by a Schemastery `z.array`, whose
|
|
23
|
+
* inferred source type is a mutable array, and a `readonly` element type makes the whole section
|
|
24
|
+
* unassignable to its own schema.
|
|
25
|
+
*/
|
|
26
|
+
args: string[];
|
|
27
|
+
}
|
|
28
|
+
/** What happens to a session's durable log when Delete is confirmed. */
|
|
29
|
+
export type DeleteMode = 'archive' | 'purge';
|
|
30
|
+
/** The `advanced-sidebar` settings section: everything a deployment or a person can change. */
|
|
31
|
+
export interface AdvancedSidebarSettings {
|
|
32
|
+
/** Show the menu trigger in the session header, acting on the open session. */
|
|
33
|
+
readonly showInSessionHeader: boolean;
|
|
34
|
+
/** Offer the Git changes entry. */
|
|
35
|
+
readonly showChanges: boolean;
|
|
36
|
+
/** Offer the Terminal entry. */
|
|
37
|
+
readonly showTerminal: boolean;
|
|
38
|
+
/** Offer the Files entry. */
|
|
39
|
+
readonly showFiles: boolean;
|
|
40
|
+
/** Offer the Background tasks entry. */
|
|
41
|
+
readonly showTasks: boolean;
|
|
42
|
+
/** Offer the Open in submenu. */
|
|
43
|
+
readonly showOpenIn: boolean;
|
|
44
|
+
/** Offer the Archive entry. */
|
|
45
|
+
readonly showArchive: boolean;
|
|
46
|
+
/** Offer the Delete entry. */
|
|
47
|
+
readonly showDelete: boolean;
|
|
48
|
+
/** Offer the Preview entry. */
|
|
49
|
+
readonly showPreview: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Dock width in pixels, and where a resize is stored. The dock clamps it to what the app frame
|
|
52
|
+
* can spare at render time, so a wide preference is safe on a narrow window.
|
|
53
|
+
*/
|
|
54
|
+
readonly panelWidth: number;
|
|
55
|
+
/** Ask before Delete commits. */
|
|
56
|
+
readonly confirmDelete: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* `archive` hides the session and keeps its log; `purge` also removes the backend's per-session
|
|
59
|
+
* artifact, which no other harness capability can undo.
|
|
60
|
+
*/
|
|
61
|
+
readonly deleteMode: DeleteMode;
|
|
62
|
+
/** Offer Stop on a live background task. */
|
|
63
|
+
readonly allowTaskKill: boolean;
|
|
64
|
+
/** Offer the output of a settled, already-reported background task. */
|
|
65
|
+
readonly showTaskOutput: boolean;
|
|
66
|
+
/** Largest number of changed files one status reading returns. */
|
|
67
|
+
readonly gitMaxFiles: number;
|
|
68
|
+
/** Largest patch, in bytes, one diff reading returns. */
|
|
69
|
+
readonly gitDiffMaxBytes: number;
|
|
70
|
+
/** Wall-clock bound on each `git` invocation that only reads. */
|
|
71
|
+
readonly gitTimeoutMs: number;
|
|
72
|
+
/**
|
|
73
|
+
* Wall-clock bound on `git commit`, which is separate because it is the one invocation that runs
|
|
74
|
+
* somebody else's code: a `pre-commit` hook can take far longer than any reading, and killing it
|
|
75
|
+
* mid-run would leave the index locked.
|
|
76
|
+
*/
|
|
77
|
+
readonly gitCommitTimeoutMs: number;
|
|
78
|
+
/** Offer Stage and Unstage in the Changes panel. */
|
|
79
|
+
readonly allowGitStaging: boolean;
|
|
80
|
+
/** Offer Commit in the Changes panel; requires {@link allowGitStaging}. */
|
|
81
|
+
readonly allowGitCommit: boolean;
|
|
82
|
+
/** Offer Push in the Changes panel. */
|
|
83
|
+
readonly allowGitPush: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Wall-clock bound on `git push`, separate because it is the one invocation that waits on a
|
|
86
|
+
* network and on a remote's own processing.
|
|
87
|
+
*/
|
|
88
|
+
readonly gitPushTimeoutMs: number;
|
|
89
|
+
/** Offer the model-written commit message in the Changes panel; requires {@link allowGitCommit}. */
|
|
90
|
+
readonly allowCommitMessageDraft: boolean;
|
|
91
|
+
/** System prompt for the drafted commit message; empty uses this plugin's own. */
|
|
92
|
+
readonly commitMessagePrompt: string;
|
|
93
|
+
/** Largest staged patch, in bytes, sent to the model when drafting a commit message. */
|
|
94
|
+
readonly commitMessageMaxBytes: number;
|
|
95
|
+
/** Shell for the panel terminal; empty resolves `$SHELL`, then the platform default. */
|
|
96
|
+
readonly terminalShell: string;
|
|
97
|
+
/** Retained terminal output in characters; the head is dropped past it. */
|
|
98
|
+
readonly terminalScrollback: number;
|
|
99
|
+
/** How many panel terminals may be open at once across every workspace. */
|
|
100
|
+
readonly maxTerminals: number;
|
|
101
|
+
/** TERM-to-KILL grace when a panel terminal is closed. */
|
|
102
|
+
readonly terminalGraceMs: number;
|
|
103
|
+
/** Largest file preview, in bytes, the Files panel will read. */
|
|
104
|
+
readonly filesMaxPreviewBytes: number;
|
|
105
|
+
/** Largest number of entries one directory listing returns. */
|
|
106
|
+
readonly filesMaxEntries: number;
|
|
107
|
+
/** List dot-prefixed entries in the Files panel. */
|
|
108
|
+
readonly filesShowHidden: boolean;
|
|
109
|
+
/** External applications offered under Open in; mutable for the same reason as {@link OpenInEditor.args}. */
|
|
110
|
+
editors: OpenInEditor[];
|
|
111
|
+
/**
|
|
112
|
+
* Launch configurations offered by the Preview panel, merged after any the workspace's own
|
|
113
|
+
* `.claude/launch.json` carries. A name declared in both places is taken from the file, so a
|
|
114
|
+
* repository stays the authority on how to run itself.
|
|
115
|
+
*/
|
|
116
|
+
previews: PreviewLaunchConfig[];
|
|
117
|
+
/** Read `.claude/launch.json` from the workspace. */
|
|
118
|
+
previewsFromLaunchFile: boolean;
|
|
119
|
+
/** How many preview servers may run at once across every workspace. */
|
|
120
|
+
maxPreviews: number;
|
|
121
|
+
/** How long to wait for a started server's port to accept a connection, in milliseconds. */
|
|
122
|
+
previewReadyTimeoutMs: number;
|
|
123
|
+
/** Retained preview output in characters; the head is dropped past it. */
|
|
124
|
+
previewScrollback: number;
|
|
125
|
+
/** TERM-to-KILL grace when a preview server is stopped. */
|
|
126
|
+
previewGraceMs: number;
|
|
127
|
+
}
|
|
128
|
+
/** Availability of one Host-backed panel, with the reason when it is unavailable. */
|
|
129
|
+
export interface CapabilityState {
|
|
130
|
+
/** Whether the panel can do its work on this Host right now. */
|
|
131
|
+
readonly available: boolean;
|
|
132
|
+
/** Operator diagnostic shown in place of the panel body; absent while available. */
|
|
133
|
+
readonly reason?: string;
|
|
134
|
+
/** Free-form identity of what answers for the capability (`git version 2.45.1`, `/bin/zsh`). */
|
|
135
|
+
readonly detail?: string;
|
|
136
|
+
}
|
|
137
|
+
/** One Open in target as the menu should render it. */
|
|
138
|
+
export interface OpenInTargetView {
|
|
139
|
+
/** Matches {@link OpenInEditor.id}, or `reveal` for the operating system's own file manager. */
|
|
140
|
+
readonly id: string;
|
|
141
|
+
/** Menu text. */
|
|
142
|
+
readonly label: string;
|
|
143
|
+
/** Whether the target resolved on this Host; unavailable targets render disabled, not hidden. */
|
|
144
|
+
readonly available: boolean;
|
|
145
|
+
/** `reveal` hands the path to the desktop; `command` launches a resolved executable. */
|
|
146
|
+
readonly kind: 'reveal' | 'command';
|
|
147
|
+
}
|
|
148
|
+
/** What the browser needs to decide which entries are live before it opens the menu. */
|
|
149
|
+
export interface AdvancedSidebarView {
|
|
150
|
+
/** `git` presence and version. */
|
|
151
|
+
readonly git: CapabilityState;
|
|
152
|
+
/** Whether a panel terminal can be allocated, and which shell would answer. */
|
|
153
|
+
readonly terminal: CapabilityState;
|
|
154
|
+
/** Whether the Host exposes a filesystem this plugin may read. */
|
|
155
|
+
readonly files: CapabilityState;
|
|
156
|
+
/** Whether a preview server can be started, and how many are already running. */
|
|
157
|
+
readonly preview: CapabilityState & {
|
|
158
|
+
/** How many preview servers this plugin currently holds open. */
|
|
159
|
+
readonly running: number;
|
|
160
|
+
};
|
|
161
|
+
/** Whether a job registry is mounted, and what may be done to a record. */
|
|
162
|
+
readonly tasks: CapabilityState & {
|
|
163
|
+
/** A live task can be stopped (registry mounted AND the setting allows it). */
|
|
164
|
+
readonly canKill: boolean;
|
|
165
|
+
/** A settled, already-reported task's output can be shown without consuming the model's read. */
|
|
166
|
+
readonly canReadOutput: boolean;
|
|
167
|
+
};
|
|
168
|
+
/** Every Open in target in menu order, available or not. */
|
|
169
|
+
readonly openIn: readonly OpenInTargetView[];
|
|
170
|
+
/** Whether Delete can remove the durable artifact, and what it would do today. */
|
|
171
|
+
readonly deletion: {
|
|
172
|
+
/** Whether the session-persistence backend exposes a per-session artifact to remove. */
|
|
173
|
+
readonly canPurge: boolean;
|
|
174
|
+
/** The configured mode; `purge` degrades to `archive` when {@link canPurge} is false. */
|
|
175
|
+
readonly mode: DeleteMode;
|
|
176
|
+
/** Why purging is unavailable, when it is. */
|
|
177
|
+
readonly reason?: string;
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* The resolved settings section.
|
|
181
|
+
*
|
|
182
|
+
* Carried here because the browser cannot always read it: `ctx.settingsScope` resolves to a real
|
|
183
|
+
* document only on a loopback connection, and answers `unavailable` with no value on every remote
|
|
184
|
+
* Web Client. Without this field the whole surface would decide it was switched off and render
|
|
185
|
+
* nothing. The bound scope stays the authority where it HAS a value — it is live and writable —
|
|
186
|
+
* and this is what the surface falls back to.
|
|
187
|
+
*/
|
|
188
|
+
readonly settings: AdvancedSidebarSettings;
|
|
189
|
+
/** Epoch ms the view was assembled, so a stale panel can say how old its facts are. */
|
|
190
|
+
readonly readAt: number;
|
|
191
|
+
}
|
|
192
|
+
/** Per-path state in one of git's two indexes. */
|
|
193
|
+
export type GitFileState = 'unmodified' | 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechange' | 'untracked' | 'ignored' | 'conflicted';
|
|
194
|
+
/** One changed path as `git status --porcelain=v2` reported it. */
|
|
195
|
+
export interface GitFileChange {
|
|
196
|
+
/** Repository-relative POSIX path — the identity a later diff request repeats. */
|
|
197
|
+
readonly path: string;
|
|
198
|
+
/** Source path of a rename or copy. */
|
|
199
|
+
readonly oldPath?: string;
|
|
200
|
+
/** State in the index (what a commit would record). */
|
|
201
|
+
readonly index: GitFileState;
|
|
202
|
+
/** State in the working tree (what is not staged yet). */
|
|
203
|
+
readonly worktree: GitFileState;
|
|
204
|
+
/** True for a path in neither index, reported by `--porcelain=v2`'s `?` records. */
|
|
205
|
+
readonly untracked: boolean;
|
|
206
|
+
/** True for an unresolved merge conflict (`u` records). */
|
|
207
|
+
readonly conflicted: boolean;
|
|
208
|
+
}
|
|
209
|
+
/** A repository reading: branch position and the three change groups. */
|
|
210
|
+
export interface GitStatusSuccess {
|
|
211
|
+
readonly ok: true;
|
|
212
|
+
/** Absolute path of the repository root, which may sit above the workspace directory. */
|
|
213
|
+
readonly repositoryRoot: string;
|
|
214
|
+
/** Requested directory relative to {@link repositoryRoot}, POSIX, empty at the root itself. */
|
|
215
|
+
readonly prefix: string;
|
|
216
|
+
/** Current branch; absent while detached or on an unborn branch. */
|
|
217
|
+
readonly branch?: string;
|
|
218
|
+
/** Configured upstream of {@link branch}. */
|
|
219
|
+
readonly upstream?: string;
|
|
220
|
+
/** Commits ahead of {@link upstream}. */
|
|
221
|
+
readonly ahead: number;
|
|
222
|
+
/** Commits behind {@link upstream}. */
|
|
223
|
+
readonly behind: number;
|
|
224
|
+
/** True while HEAD names a commit rather than a branch. */
|
|
225
|
+
readonly detached: boolean;
|
|
226
|
+
/** Paths whose index state differs from HEAD. */
|
|
227
|
+
readonly staged: readonly GitFileChange[];
|
|
228
|
+
/** Tracked paths whose working tree differs from the index. */
|
|
229
|
+
readonly unstaged: readonly GitFileChange[];
|
|
230
|
+
/** Paths git does not track. */
|
|
231
|
+
readonly untracked: readonly GitFileChange[];
|
|
232
|
+
/** Unresolved merge conflicts, listed separately because neither group describes them. */
|
|
233
|
+
readonly conflicted: readonly GitFileChange[];
|
|
234
|
+
/** True when the reading stopped at `gitMaxFiles` and the lists are incomplete. */
|
|
235
|
+
readonly truncated: boolean;
|
|
236
|
+
/** What the panel may do to this repository, and who a commit would be authored by. */
|
|
237
|
+
readonly write: GitWriteCapability;
|
|
238
|
+
/** Epoch ms of the reading. */
|
|
239
|
+
readonly readAt: number;
|
|
240
|
+
}
|
|
241
|
+
/** Why a git reading could not be produced. */
|
|
242
|
+
export type GitFailureCode =
|
|
243
|
+
/** No filesystem capability is mounted, so no path could be resolved. */
|
|
244
|
+
'no-filesystem'
|
|
245
|
+
/** `git` is not on this Host. */
|
|
246
|
+
| 'no-git'
|
|
247
|
+
/** The directory is not inside a git repository. */
|
|
248
|
+
| 'not-a-repository'
|
|
249
|
+
/** git ran and exited non-zero; the message carries its stderr. */
|
|
250
|
+
| 'git-failed'
|
|
251
|
+
/** git exceeded `gitTimeoutMs`. */
|
|
252
|
+
| 'timeout'
|
|
253
|
+
/** The caller abandoned the request. */
|
|
254
|
+
| 'cancelled'
|
|
255
|
+
/** The requested path left the workspace it was asked about. */
|
|
256
|
+
| 'path-denied'
|
|
257
|
+
/** The operation is switched off in the advanced-sidebar settings. */
|
|
258
|
+
| 'disabled'
|
|
259
|
+
/** `git commit` was asked for with nothing staged. */
|
|
260
|
+
| 'nothing-staged'
|
|
261
|
+
/** `git commit` was asked for with a blank message. */
|
|
262
|
+
| 'empty-message'
|
|
263
|
+
/** git has no `user.name`/`user.email`, so it has no author to record. */
|
|
264
|
+
| 'no-identity'
|
|
265
|
+
/** The branch has no upstream, so `git push` has no default destination. */
|
|
266
|
+
| 'no-upstream'
|
|
267
|
+
/** HEAD names no branch, so there is nothing to push. */
|
|
268
|
+
| 'detached-head'
|
|
269
|
+
/** No model is configured on this Host, so no message can be drafted. */
|
|
270
|
+
| 'no-model'
|
|
271
|
+
/** The model request failed; the message carries what it said. */
|
|
272
|
+
| 'llm-failed';
|
|
273
|
+
/** Whether the repository can be written from the panel, and whether it could commit right now. */
|
|
274
|
+
export interface GitWriteCapability {
|
|
275
|
+
/** Staging and unstaging are offered. */
|
|
276
|
+
readonly canStage: boolean;
|
|
277
|
+
/** Committing is offered. */
|
|
278
|
+
readonly canCommit: boolean;
|
|
279
|
+
/** Pushing is offered. */
|
|
280
|
+
readonly canPush: boolean;
|
|
281
|
+
/** The model-written commit message is offered, and a model is mounted to write it. */
|
|
282
|
+
readonly canDraftMessage: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Author identity `git commit` would use, as `Name <email>`.
|
|
285
|
+
*
|
|
286
|
+
* Absent means git has none configured, and a commit would fail with its own long explanation.
|
|
287
|
+
* Reported here so the panel can say so before the button is pressed rather than after.
|
|
288
|
+
*/
|
|
289
|
+
readonly author?: string;
|
|
290
|
+
}
|
|
291
|
+
/** A classified git failure, carried as a value. */
|
|
292
|
+
export interface GitFailure {
|
|
293
|
+
readonly ok: false;
|
|
294
|
+
readonly code: GitFailureCode;
|
|
295
|
+
readonly message: string;
|
|
296
|
+
}
|
|
297
|
+
/** Reading of a workspace's git state. */
|
|
298
|
+
export type GitStatusResult = GitStatusSuccess | GitFailure;
|
|
299
|
+
/** Which repository directory to read. */
|
|
300
|
+
export interface GitStatusRequest {
|
|
301
|
+
/** Absolute Host directory — the workspace path the panel was opened for. */
|
|
302
|
+
readonly workspacePath: string;
|
|
303
|
+
}
|
|
304
|
+
/** Which version of one path to diff. */
|
|
305
|
+
export interface GitDiffRequest {
|
|
306
|
+
/** Absolute Host directory the status reading came from. */
|
|
307
|
+
readonly workspacePath: string;
|
|
308
|
+
/** Repository-relative POSIX path, exactly as {@link GitFileChange.path} spelled it. */
|
|
309
|
+
readonly path: string;
|
|
310
|
+
/** Diff the index against HEAD rather than the working tree against the index. */
|
|
311
|
+
readonly staged: boolean;
|
|
312
|
+
/** The path is untracked, so the patch is synthesized against an empty blob. */
|
|
313
|
+
readonly untracked: boolean;
|
|
314
|
+
}
|
|
315
|
+
/** One unified patch. */
|
|
316
|
+
export interface GitDiffSuccess {
|
|
317
|
+
readonly ok: true;
|
|
318
|
+
/** Echo of the requested path. */
|
|
319
|
+
readonly path: string;
|
|
320
|
+
/** Unified diff text; empty when the two versions are identical. */
|
|
321
|
+
readonly patch: string;
|
|
322
|
+
/** True when git reported a binary difference and produced no text. */
|
|
323
|
+
readonly binary: boolean;
|
|
324
|
+
/** True when the patch was cut at `gitDiffMaxBytes`. */
|
|
325
|
+
readonly truncated: boolean;
|
|
326
|
+
}
|
|
327
|
+
/** Patch for one path, or a classified failure. */
|
|
328
|
+
export type GitDiffResult = GitDiffSuccess | GitFailure;
|
|
329
|
+
/** Move paths into or out of the index. */
|
|
330
|
+
export interface GitStageRequest {
|
|
331
|
+
/** Absolute Host directory the status reading came from. */
|
|
332
|
+
readonly workspacePath: string;
|
|
333
|
+
/**
|
|
334
|
+
* Repository-relative POSIX paths, exactly as {@link GitFileChange.path} spelled them.
|
|
335
|
+
*
|
|
336
|
+
* Every one is proved to sit inside the repository before git sees it, and each is passed after
|
|
337
|
+
* `--` as a literal path rather than a pathspec, so neither an option nor a glob can be smuggled
|
|
338
|
+
* through. An empty list is refused.
|
|
339
|
+
*/
|
|
340
|
+
readonly paths: readonly string[];
|
|
341
|
+
}
|
|
342
|
+
/** Settlement of a stage or unstage, carrying the reading that follows it. */
|
|
343
|
+
export interface GitWriteSuccess {
|
|
344
|
+
readonly ok: true;
|
|
345
|
+
/** The repository state after the write, so the panel needs no second round trip. */
|
|
346
|
+
readonly status: GitStatusSuccess;
|
|
347
|
+
}
|
|
348
|
+
/** Stage/unstage outcome. */
|
|
349
|
+
export type GitStageResult = GitWriteSuccess | GitFailure;
|
|
350
|
+
/** Record the staged changes. */
|
|
351
|
+
export interface GitCommitRequest {
|
|
352
|
+
/** Absolute Host directory the status reading came from. */
|
|
353
|
+
readonly workspacePath: string;
|
|
354
|
+
/** Commit message; passed as one argument to `-m`, never interpreted by a shell. */
|
|
355
|
+
readonly message: string;
|
|
356
|
+
/** Replace the previous commit instead of adding one. */
|
|
357
|
+
readonly amend: boolean;
|
|
358
|
+
}
|
|
359
|
+
/** A recorded commit, with the reading that follows it. */
|
|
360
|
+
export interface GitCommitSuccess {
|
|
361
|
+
readonly ok: true;
|
|
362
|
+
/** Abbreviated hash of the new commit. */
|
|
363
|
+
readonly commit: string;
|
|
364
|
+
/** First line of the recorded message. */
|
|
365
|
+
readonly subject: string;
|
|
366
|
+
/** The repository state after the commit. */
|
|
367
|
+
readonly status: GitStatusSuccess;
|
|
368
|
+
/**
|
|
369
|
+
* Anything the commit printed on stderr while still succeeding — a hook's advice, a warning.
|
|
370
|
+
* Empty for an ordinary commit.
|
|
371
|
+
*/
|
|
372
|
+
readonly notes: string;
|
|
373
|
+
}
|
|
374
|
+
/** Commit outcome. */
|
|
375
|
+
export type GitCommitResult = GitCommitSuccess | GitFailure;
|
|
376
|
+
/** Send the current branch's commits to its remote. */
|
|
377
|
+
export interface GitPushRequest {
|
|
378
|
+
/** Absolute Host workspace directory. */
|
|
379
|
+
readonly workspacePath: string;
|
|
380
|
+
/**
|
|
381
|
+
* Publish a branch that has no upstream, recording the remote it was pushed to as its upstream.
|
|
382
|
+
* False refuses such a branch instead, because choosing a remote is a decision, not a default.
|
|
383
|
+
*/
|
|
384
|
+
readonly setUpstream: boolean;
|
|
385
|
+
}
|
|
386
|
+
/** A completed push, with the reading that follows it. */
|
|
387
|
+
export interface GitPushSuccess {
|
|
388
|
+
readonly ok: true;
|
|
389
|
+
/** Branch that was pushed. */
|
|
390
|
+
readonly branch: string;
|
|
391
|
+
/** Remote it went to. */
|
|
392
|
+
readonly remote: string;
|
|
393
|
+
/** True when this push is what gave the branch its upstream. */
|
|
394
|
+
readonly published: boolean;
|
|
395
|
+
/** The repository state after the push; its `ahead` is what proves the push landed. */
|
|
396
|
+
readonly status: GitStatusSuccess;
|
|
397
|
+
/** What git printed while succeeding — the ref update lines, and any remote advice. */
|
|
398
|
+
readonly notes: string;
|
|
399
|
+
}
|
|
400
|
+
/** Push outcome. */
|
|
401
|
+
export type GitPushResult = GitPushSuccess | GitFailure;
|
|
402
|
+
/** Ask a model to write a commit message for what is staged. */
|
|
403
|
+
export interface GitCommitMessageRequest {
|
|
404
|
+
/** Absolute Host workspace directory. */
|
|
405
|
+
readonly workspacePath: string;
|
|
406
|
+
/**
|
|
407
|
+
* Draft for an amend, which describes the previous commit's content as well as the index. False
|
|
408
|
+
* describes the index alone.
|
|
409
|
+
*/
|
|
410
|
+
readonly amend: boolean;
|
|
411
|
+
}
|
|
412
|
+
/** A drafted commit message. */
|
|
413
|
+
export interface GitCommitMessageSuccess {
|
|
414
|
+
readonly ok: true;
|
|
415
|
+
/** The message, ready to be edited before it is recorded. */
|
|
416
|
+
readonly message: string;
|
|
417
|
+
/** Provider route that wrote it, so the panel can say which model answered. */
|
|
418
|
+
readonly model: string;
|
|
419
|
+
/** True when the patch was cut at `commitMessageMaxBytes` before the model saw it. */
|
|
420
|
+
readonly truncated: boolean;
|
|
421
|
+
}
|
|
422
|
+
/** Draft outcome. */
|
|
423
|
+
export type GitCommitMessageResult = GitCommitMessageSuccess | GitFailure;
|
|
424
|
+
/** Open a panel terminal in one workspace. */
|
|
425
|
+
export interface TerminalOpenRequest {
|
|
426
|
+
/** Absolute Host directory to start in. */
|
|
427
|
+
readonly workspacePath: string;
|
|
428
|
+
/** Initial column count, measured from the rendered panel. */
|
|
429
|
+
readonly cols: number;
|
|
430
|
+
/** Initial row count, measured from the rendered panel. */
|
|
431
|
+
readonly rows: number;
|
|
432
|
+
}
|
|
433
|
+
/** An allocated panel terminal. */
|
|
434
|
+
export interface TerminalOpenSuccess {
|
|
435
|
+
readonly ok: true;
|
|
436
|
+
/** Handle repeated by every later read, write, and close. */
|
|
437
|
+
readonly terminalId: string;
|
|
438
|
+
/** Executable that was started. */
|
|
439
|
+
readonly shell: string;
|
|
440
|
+
/** Directory the shell started in. */
|
|
441
|
+
readonly cwd: string;
|
|
442
|
+
/** Top-level terminal process id. */
|
|
443
|
+
readonly pid: number;
|
|
444
|
+
}
|
|
445
|
+
/** Why a terminal operation failed. */
|
|
446
|
+
export type TerminalFailureCode =
|
|
447
|
+
/** No subprocess capability is mounted. */
|
|
448
|
+
'no-subprocess'
|
|
449
|
+
/** No filesystem capability is mounted, so the working directory could not be resolved. */
|
|
450
|
+
| 'no-filesystem'
|
|
451
|
+
/** The shell could not be started; the message carries the substrate error. */
|
|
452
|
+
| 'spawn-failed'
|
|
453
|
+
/** The handle names no terminal this plugin owns — usually one already closed. */
|
|
454
|
+
| 'unknown-terminal'
|
|
455
|
+
/** The requested directory left the workspace, or does not exist. */
|
|
456
|
+
| 'path-denied'
|
|
457
|
+
/** `maxTerminals` panel terminals are already open. */
|
|
458
|
+
| 'limit-reached'
|
|
459
|
+
/** The plugin is unloading, so no new terminal will be allocated. */
|
|
460
|
+
| 'closed';
|
|
461
|
+
/** A classified terminal failure, carried as a value. */
|
|
462
|
+
export interface TerminalFailure {
|
|
463
|
+
readonly ok: false;
|
|
464
|
+
readonly code: TerminalFailureCode;
|
|
465
|
+
readonly message: string;
|
|
466
|
+
}
|
|
467
|
+
/** Allocation outcome. */
|
|
468
|
+
export type TerminalOpenResult = TerminalOpenSuccess | TerminalFailure;
|
|
469
|
+
/** Read terminal output from a caller-owned byte offset. */
|
|
470
|
+
export interface TerminalReadRequest {
|
|
471
|
+
/** Handle from {@link TerminalOpenSuccess}. */
|
|
472
|
+
readonly terminalId: string;
|
|
473
|
+
/** Whole-stream character offset to resume from; `0` reads the retained scrollback. */
|
|
474
|
+
readonly fromOffset: number;
|
|
475
|
+
}
|
|
476
|
+
/** Terminal output plus the process state at read time. */
|
|
477
|
+
export interface TerminalReadSuccess {
|
|
478
|
+
readonly ok: true;
|
|
479
|
+
/** Echo of the handle. */
|
|
480
|
+
readonly terminalId: string;
|
|
481
|
+
/** Output text from the requested offset. */
|
|
482
|
+
readonly text: string;
|
|
483
|
+
/** Whole-stream character offset to resume from on the next read. */
|
|
484
|
+
readonly nextOffset: number;
|
|
485
|
+
/** True when the requested offset had already fallen out of the retained scrollback. */
|
|
486
|
+
readonly lossy: boolean;
|
|
487
|
+
/** True while the shell is alive. */
|
|
488
|
+
readonly running: boolean;
|
|
489
|
+
/** Exit code once the shell has closed; null when it died from a signal. */
|
|
490
|
+
readonly exitCode?: number | null;
|
|
491
|
+
/** Terminating signal once the shell has closed. */
|
|
492
|
+
readonly signal?: string | null;
|
|
493
|
+
}
|
|
494
|
+
/** Read outcome. */
|
|
495
|
+
export type TerminalReadResult = TerminalReadSuccess | TerminalFailure;
|
|
496
|
+
/** Send keystrokes to a terminal. */
|
|
497
|
+
export interface TerminalWriteRequest {
|
|
498
|
+
/** Handle from {@link TerminalOpenSuccess}. */
|
|
499
|
+
readonly terminalId: string;
|
|
500
|
+
/** Text delivered verbatim; the caller supplies its own newlines and control bytes. */
|
|
501
|
+
readonly data: string;
|
|
502
|
+
}
|
|
503
|
+
/** Deliver a signal to a terminal's foreground process group. */
|
|
504
|
+
export interface TerminalSignalRequest {
|
|
505
|
+
/** Handle from {@link TerminalOpenSuccess}. */
|
|
506
|
+
readonly terminalId: string;
|
|
507
|
+
/** Signal to deliver; the set the terminal primitive accepts. */
|
|
508
|
+
readonly signal: 'SIGINT' | 'SIGTERM' | 'SIGKILL' | 'SIGTSTP' | 'SIGHUP';
|
|
509
|
+
}
|
|
510
|
+
/** Close a terminal. */
|
|
511
|
+
export interface TerminalCloseRequest {
|
|
512
|
+
/** Handle from {@link TerminalOpenSuccess}. */
|
|
513
|
+
readonly terminalId: string;
|
|
514
|
+
}
|
|
515
|
+
/** Settlement of a write, signal, or close. */
|
|
516
|
+
export type TerminalAckResult = {
|
|
517
|
+
readonly ok: true;
|
|
518
|
+
} | TerminalFailure;
|
|
519
|
+
/** One child of a listed directory. */
|
|
520
|
+
export interface DirectoryEntryView {
|
|
521
|
+
/** Basename inside the listed directory. */
|
|
522
|
+
readonly name: string;
|
|
523
|
+
/** Absolute Host path — the panel never joins path segments itself. */
|
|
524
|
+
readonly path: string;
|
|
525
|
+
/** What the child is; `other` covers sockets, devices, and anything else not opened as text. */
|
|
526
|
+
readonly kind: 'file' | 'directory' | 'other';
|
|
527
|
+
/** Byte size of a regular file, when the backend reports one. */
|
|
528
|
+
readonly size?: number;
|
|
529
|
+
}
|
|
530
|
+
/** List one directory level inside a workspace. */
|
|
531
|
+
export interface ListEntriesRequest {
|
|
532
|
+
/** Absolute Host directory to list. */
|
|
533
|
+
readonly path: string;
|
|
534
|
+
/** Absolute workspace directory the listing must stay inside. */
|
|
535
|
+
readonly workspacePath: string;
|
|
536
|
+
}
|
|
537
|
+
/** One directory level. */
|
|
538
|
+
export interface ListEntriesSuccess {
|
|
539
|
+
readonly ok: true;
|
|
540
|
+
/** Absolute path of the listed directory. */
|
|
541
|
+
readonly path: string;
|
|
542
|
+
/** Absolute path of the parent, absent at the workspace root — the panel does not climb out. */
|
|
543
|
+
readonly parent?: string;
|
|
544
|
+
/** Children, directories first and then files, each group name-sorted. */
|
|
545
|
+
readonly entries: readonly DirectoryEntryView[];
|
|
546
|
+
/** True when the listing was cut at `filesMaxEntries`. */
|
|
547
|
+
readonly truncated: boolean;
|
|
548
|
+
}
|
|
549
|
+
/** Directory level, or a classified failure. */
|
|
550
|
+
export type ListEntriesResult = ListEntriesSuccess | ReadFileFailure;
|
|
551
|
+
/** Read one file for the Files panel preview. */
|
|
552
|
+
export interface ReadFileRequest {
|
|
553
|
+
/** Absolute Host path. */
|
|
554
|
+
readonly path: string;
|
|
555
|
+
/** Absolute workspace directory the path must stay inside. */
|
|
556
|
+
readonly workspacePath: string;
|
|
557
|
+
}
|
|
558
|
+
/** A file preview. */
|
|
559
|
+
export interface ReadFileSuccess {
|
|
560
|
+
readonly ok: true;
|
|
561
|
+
/** Echo of the requested path. */
|
|
562
|
+
readonly path: string;
|
|
563
|
+
/** Decoded text; empty when {@link binary} is true. */
|
|
564
|
+
readonly text: string;
|
|
565
|
+
/** True when the file's leading bytes contain a NUL, so it is not shown as text. */
|
|
566
|
+
readonly binary: boolean;
|
|
567
|
+
/** True when the read stopped at `filesMaxPreviewBytes`. */
|
|
568
|
+
readonly truncated: boolean;
|
|
569
|
+
/** Total size on disk in bytes. */
|
|
570
|
+
readonly bytes: number;
|
|
571
|
+
}
|
|
572
|
+
/** Why a preview could not be produced. */
|
|
573
|
+
export type ReadFileFailureCode =
|
|
574
|
+
/** No filesystem capability is mounted. */
|
|
575
|
+
'no-filesystem'
|
|
576
|
+
/** The path left the workspace directory. */
|
|
577
|
+
| 'path-denied'
|
|
578
|
+
/** Nothing is at the path, or it is not a regular file. */
|
|
579
|
+
| 'not-a-file'
|
|
580
|
+
/** The filesystem refused the read; the message carries its error. */
|
|
581
|
+
| 'read-failed';
|
|
582
|
+
/** A classified preview failure, carried as a value. */
|
|
583
|
+
export interface ReadFileFailure {
|
|
584
|
+
readonly ok: false;
|
|
585
|
+
readonly code: ReadFileFailureCode;
|
|
586
|
+
readonly message: string;
|
|
587
|
+
}
|
|
588
|
+
/** Preview outcome. */
|
|
589
|
+
export type ReadFileResult = ReadFileSuccess | ReadFileFailure;
|
|
590
|
+
/** Hand one path to an external application. */
|
|
591
|
+
export interface OpenInRequest {
|
|
592
|
+
/** Matches {@link OpenInTargetView.id}. */
|
|
593
|
+
readonly targetId: string;
|
|
594
|
+
/** Absolute Host path to open. */
|
|
595
|
+
readonly path: string;
|
|
596
|
+
}
|
|
597
|
+
/** Why an external open failed. */
|
|
598
|
+
export type OpenInFailureCode =
|
|
599
|
+
/** No configured target carries the requested id. */
|
|
600
|
+
'unknown-target'
|
|
601
|
+
/** The target's command does not resolve on this Host. */
|
|
602
|
+
| 'unavailable'
|
|
603
|
+
/** The command started and failed; the message carries its stderr. */
|
|
604
|
+
| 'launch-failed'
|
|
605
|
+
/** The path does not exist. */
|
|
606
|
+
| 'path-denied'
|
|
607
|
+
/** The launch exceeded its grace period. */
|
|
608
|
+
| 'timeout';
|
|
609
|
+
/** Settlement of an external open. */
|
|
610
|
+
export type OpenInResult = {
|
|
611
|
+
readonly ok: true;
|
|
612
|
+
} | {
|
|
613
|
+
readonly ok: false;
|
|
614
|
+
readonly code: OpenInFailureCode;
|
|
615
|
+
readonly message: string;
|
|
616
|
+
};
|
|
617
|
+
/** Stop one live background task. */
|
|
618
|
+
export interface TaskKillRequest {
|
|
619
|
+
/** Session that owns the task; the registry fences access on it. */
|
|
620
|
+
readonly sessionId: string;
|
|
621
|
+
/** Registry-issued job id. */
|
|
622
|
+
readonly taskId: string;
|
|
623
|
+
}
|
|
624
|
+
/** Why a task operation failed. */
|
|
625
|
+
export type TaskFailureCode =
|
|
626
|
+
/** No job registry is mounted. */
|
|
627
|
+
'no-registry'
|
|
628
|
+
/** The setting that gates this operation is off. */
|
|
629
|
+
| 'disabled'
|
|
630
|
+
/** No live agent answers for the session, so the registry would refuse the caller. */
|
|
631
|
+
| 'unknown-session'
|
|
632
|
+
/** The registry knows no such task for that owner. */
|
|
633
|
+
| 'unknown-task'
|
|
634
|
+
/** The registry refused; the message carries its error. */
|
|
635
|
+
| 'registry-refused';
|
|
636
|
+
/** A classified task failure, carried as a value. */
|
|
637
|
+
export interface TaskFailure {
|
|
638
|
+
readonly ok: false;
|
|
639
|
+
readonly code: TaskFailureCode;
|
|
640
|
+
readonly message: string;
|
|
641
|
+
}
|
|
642
|
+
/** Settlement of a stop request. */
|
|
643
|
+
export type TaskKillResult = {
|
|
644
|
+
readonly ok: true;
|
|
645
|
+
readonly outcome: 'requested' | 'already-finished';
|
|
646
|
+
} | TaskFailure;
|
|
647
|
+
/** Read one settled task's output. */
|
|
648
|
+
export interface TaskOutputRequest {
|
|
649
|
+
/** Session that owns the task. */
|
|
650
|
+
readonly sessionId: string;
|
|
651
|
+
/** Registry-issued job id. */
|
|
652
|
+
readonly taskId: string;
|
|
653
|
+
}
|
|
654
|
+
/** A task's output, or the reason it is withheld. */
|
|
655
|
+
export interface TaskOutputSuccess {
|
|
656
|
+
readonly ok: true;
|
|
657
|
+
/** Echo of the task id. */
|
|
658
|
+
readonly taskId: string;
|
|
659
|
+
/**
|
|
660
|
+
* Whether {@link text} carries the output.
|
|
661
|
+
*
|
|
662
|
+
* False while the registry has not marked the record reported: reading a job's stream CONSUMES
|
|
663
|
+
* the model's own delta, so a live task's output is withheld rather than stolen.
|
|
664
|
+
*/
|
|
665
|
+
readonly readable: boolean;
|
|
666
|
+
/** Accumulated output; empty while {@link readable} is false. */
|
|
667
|
+
readonly text: string;
|
|
668
|
+
/** Why the output is withheld; absent while {@link readable} is true. */
|
|
669
|
+
readonly reason?: string;
|
|
670
|
+
}
|
|
671
|
+
/** Output outcome. */
|
|
672
|
+
export type TaskOutputResult = TaskOutputSuccess | TaskFailure;
|
|
673
|
+
/** Delete one session. */
|
|
674
|
+
export interface DeleteSessionRequest {
|
|
675
|
+
/** Session to remove. */
|
|
676
|
+
readonly sessionId: string;
|
|
677
|
+
}
|
|
678
|
+
/** What Delete actually did. */
|
|
679
|
+
export interface DeleteSessionSuccess {
|
|
680
|
+
readonly ok: true;
|
|
681
|
+
/** True when the session was added to the registry-global archive set. */
|
|
682
|
+
readonly archived: boolean;
|
|
683
|
+
/** True when the persistence backend's per-session artifact was removed. */
|
|
684
|
+
readonly purged: boolean;
|
|
685
|
+
/** Absolute path of the removed artifact, when one was removed. */
|
|
686
|
+
readonly artifactPath?: string;
|
|
687
|
+
/** Why the artifact survived, when `deleteMode` was `purge` and it did. */
|
|
688
|
+
readonly purgeSkippedReason?: string;
|
|
689
|
+
}
|
|
690
|
+
/** Why a delete could not be committed. */
|
|
691
|
+
export type DeleteSessionFailureCode =
|
|
692
|
+
/** The Delete entry is switched off in settings. */
|
|
693
|
+
'disabled'
|
|
694
|
+
/** No workspace registry is mounted, so the session could not be hidden. */
|
|
695
|
+
| 'no-registry'
|
|
696
|
+
/** Neither the live store nor persistence knows the id. */
|
|
697
|
+
| 'unknown-session'
|
|
698
|
+
/** The registry refused the archive write; the message carries its error. */
|
|
699
|
+
| 'archive-failed'
|
|
700
|
+
/** The artifact was located but could not be removed; the message carries the filesystem error. */
|
|
701
|
+
| 'remove-failed';
|
|
702
|
+
/** Settlement of a delete. */
|
|
703
|
+
export type DeleteSessionResult = DeleteSessionSuccess | {
|
|
704
|
+
readonly ok: false;
|
|
705
|
+
readonly code: DeleteSessionFailureCode;
|
|
706
|
+
readonly message: string;
|
|
707
|
+
};
|
|
708
|
+
/**
|
|
709
|
+
* One launch configuration: how to start something and where to look at it.
|
|
710
|
+
*
|
|
711
|
+
* The field names are Claude Code's `.claude/launch.json` vocabulary on purpose. A repository that
|
|
712
|
+
* already carries that file gets a working Preview panel with no second configuration to write, and
|
|
713
|
+
* a repository that does not can put the same rows under `previews` in cordis.yml.
|
|
714
|
+
*/
|
|
715
|
+
export interface PreviewLaunch {
|
|
716
|
+
/** Unique name inside one workspace; the panel's picker shows it and every request repeats it. */
|
|
717
|
+
readonly name: string;
|
|
718
|
+
/** Executable to run. Absent makes the row attach-only: it opens {@link url} and starts nothing. */
|
|
719
|
+
readonly runtimeExecutable?: string;
|
|
720
|
+
/** Arguments for {@link runtimeExecutable}. */
|
|
721
|
+
readonly runtimeArgs?: readonly string[];
|
|
722
|
+
/** Port the server listens on; readiness is a TCP connect to it. */
|
|
723
|
+
readonly port?: number;
|
|
724
|
+
/** Where to point the frame. Absent with a port means `http://127.0.0.1:<port>`. */
|
|
725
|
+
readonly url?: string;
|
|
726
|
+
/** Directory to run in, relative to the workspace. Absent runs at the workspace root. */
|
|
727
|
+
readonly cwd?: string;
|
|
728
|
+
/** Extra environment entries for the child. */
|
|
729
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* A launch configuration as a `cordis.yml` row states it.
|
|
733
|
+
*
|
|
734
|
+
* Structurally {@link PreviewLaunch} with mutable members: a Schemastery `z.array`/`z.object` infers
|
|
735
|
+
* mutable source types, and a `readonly` member makes the whole section unassignable to its own
|
|
736
|
+
* schema. The Host reads both through {@link PreviewLaunch}, which this satisfies.
|
|
737
|
+
*/
|
|
738
|
+
export interface PreviewLaunchConfig {
|
|
739
|
+
/** Unique name inside one workspace. */
|
|
740
|
+
name: string;
|
|
741
|
+
/** Executable to run; empty makes the row attach-only. */
|
|
742
|
+
runtimeExecutable: string;
|
|
743
|
+
/** Arguments for the executable. */
|
|
744
|
+
runtimeArgs: string[];
|
|
745
|
+
/** Port readiness is probed on; `0` means the row has none. */
|
|
746
|
+
port: number;
|
|
747
|
+
/** Where to point the frame; empty derives it from the port. */
|
|
748
|
+
url: string;
|
|
749
|
+
/** Directory to run in, relative to the workspace; empty runs at the root. */
|
|
750
|
+
cwd: string;
|
|
751
|
+
}
|
|
752
|
+
/** Where one launch configuration came from, so the panel can say which file to edit. */
|
|
753
|
+
export type PreviewOrigin = 'launch-json' | 'settings';
|
|
754
|
+
/** Lifecycle of one preview server. */
|
|
755
|
+
export type PreviewState =
|
|
756
|
+
/** Nothing is running for this configuration. */
|
|
757
|
+
'stopped'
|
|
758
|
+
/** The process started; the port has not accepted a connection yet. */
|
|
759
|
+
| 'starting'
|
|
760
|
+
/** The port accepts connections, or the row is attach-only. */
|
|
761
|
+
| 'ready'
|
|
762
|
+
/** The process exited on its own. */
|
|
763
|
+
| 'exited'
|
|
764
|
+
/** The process could not be started, or readiness timed out. */
|
|
765
|
+
| 'failed';
|
|
766
|
+
/** One configuration as the panel should render it. */
|
|
767
|
+
export interface PreviewServerView {
|
|
768
|
+
/** Handle for every later request; absent while nothing has been started for this row. */
|
|
769
|
+
readonly serverId?: string;
|
|
770
|
+
/** Echo of {@link PreviewLaunch.name}. */
|
|
771
|
+
readonly name: string;
|
|
772
|
+
/** Which file the row came from. */
|
|
773
|
+
readonly origin: PreviewOrigin;
|
|
774
|
+
/** True when the row starts a process rather than only opening a URL. */
|
|
775
|
+
readonly startable: boolean;
|
|
776
|
+
/** Current lifecycle state. */
|
|
777
|
+
readonly state: PreviewState;
|
|
778
|
+
/** Where to point the frame, once it is known. */
|
|
779
|
+
readonly url?: string;
|
|
780
|
+
/** Port readiness is probed on. */
|
|
781
|
+
readonly port?: number;
|
|
782
|
+
/** Top-level process id while one is running. */
|
|
783
|
+
readonly pid?: number;
|
|
784
|
+
/** Exit code once the process has ended. */
|
|
785
|
+
readonly exitCode?: number | null;
|
|
786
|
+
/** Why the row is `failed`, or why it cannot be started. */
|
|
787
|
+
readonly detail?: string;
|
|
788
|
+
/** Epoch ms the process started. */
|
|
789
|
+
readonly startedAt?: number;
|
|
790
|
+
}
|
|
791
|
+
/** List the configurations one workspace offers. */
|
|
792
|
+
export interface PreviewListRequest {
|
|
793
|
+
/** Absolute Host workspace directory. */
|
|
794
|
+
readonly workspacePath: string;
|
|
795
|
+
}
|
|
796
|
+
/** Every configuration plus where they were read from. */
|
|
797
|
+
export interface PreviewListSuccess {
|
|
798
|
+
readonly ok: true;
|
|
799
|
+
/** Configurations in file order, settings rows after launch.json rows. */
|
|
800
|
+
readonly servers: readonly PreviewServerView[];
|
|
801
|
+
/** Absolute path of the launch file that was read, when one existed. */
|
|
802
|
+
readonly launchFile?: string;
|
|
803
|
+
/** Why the launch file was ignored, when one existed but could not be used. */
|
|
804
|
+
readonly launchFileError?: string;
|
|
805
|
+
}
|
|
806
|
+
/** Why a preview request failed. */
|
|
807
|
+
export type PreviewFailureCode =
|
|
808
|
+
/** No subprocess capability is mounted. */
|
|
809
|
+
'no-subprocess'
|
|
810
|
+
/** No filesystem capability is mounted. */
|
|
811
|
+
| 'no-filesystem'
|
|
812
|
+
/** The workspace path, or a configuration's `cwd`, left the workspace or does not exist. */
|
|
813
|
+
| 'path-denied'
|
|
814
|
+
/** No configuration carries the requested name. */
|
|
815
|
+
| 'unknown-server'
|
|
816
|
+
/** The row names no executable, so there is nothing to start. */
|
|
817
|
+
| 'not-startable'
|
|
818
|
+
/** The executable does not resolve on this Host. */
|
|
819
|
+
| 'unavailable'
|
|
820
|
+
/** The process could not be spawned; the message carries the substrate error. */
|
|
821
|
+
| 'spawn-failed'
|
|
822
|
+
/** `maxPreviews` servers are already running. */
|
|
823
|
+
| 'limit-reached'
|
|
824
|
+
/** The plugin is unloading, so no new server will be started. */
|
|
825
|
+
| 'closed';
|
|
826
|
+
/** A classified preview failure, carried as a value. */
|
|
827
|
+
export interface PreviewFailure {
|
|
828
|
+
readonly ok: false;
|
|
829
|
+
readonly code: PreviewFailureCode;
|
|
830
|
+
readonly message: string;
|
|
831
|
+
}
|
|
832
|
+
/** Configuration list, or a classified failure. */
|
|
833
|
+
export type PreviewListResult = PreviewListSuccess | PreviewFailure;
|
|
834
|
+
/** Start one configuration. */
|
|
835
|
+
export interface PreviewStartRequest {
|
|
836
|
+
/** Absolute Host workspace directory. */
|
|
837
|
+
readonly workspacePath: string;
|
|
838
|
+
/** Which configuration to start. */
|
|
839
|
+
readonly name: string;
|
|
840
|
+
}
|
|
841
|
+
/** Start outcome; the row is `starting` until its port accepts. */
|
|
842
|
+
export type PreviewStartResult = {
|
|
843
|
+
readonly ok: true;
|
|
844
|
+
readonly server: PreviewServerView;
|
|
845
|
+
} | PreviewFailure;
|
|
846
|
+
/** Stop one running server. */
|
|
847
|
+
export interface PreviewStopRequest {
|
|
848
|
+
/** Handle from {@link PreviewServerView.serverId}. */
|
|
849
|
+
readonly serverId: string;
|
|
850
|
+
}
|
|
851
|
+
/** Settlement of a stop. */
|
|
852
|
+
export type PreviewStopResult = {
|
|
853
|
+
readonly ok: true;
|
|
854
|
+
} | PreviewFailure;
|
|
855
|
+
/** Read one server's output from a caller-owned offset. */
|
|
856
|
+
export interface PreviewLogsRequest {
|
|
857
|
+
/** Handle from {@link PreviewServerView.serverId}. */
|
|
858
|
+
readonly serverId: string;
|
|
859
|
+
/** Whole-stream character offset to resume from; `0` reads the retained buffer. */
|
|
860
|
+
readonly fromOffset: number;
|
|
861
|
+
}
|
|
862
|
+
/** Output plus the state at read time, so the panel needs one poll rather than two. */
|
|
863
|
+
export interface PreviewLogsSuccess {
|
|
864
|
+
readonly ok: true;
|
|
865
|
+
/** Echo of the handle. */
|
|
866
|
+
readonly serverId: string;
|
|
867
|
+
/** Combined stdout and stderr, in arrival order, from the requested offset. */
|
|
868
|
+
readonly text: string;
|
|
869
|
+
/** Whole-stream character offset to resume from on the next read. */
|
|
870
|
+
readonly nextOffset: number;
|
|
871
|
+
/** True when the requested offset had already fallen out of the retained buffer. */
|
|
872
|
+
readonly lossy: boolean;
|
|
873
|
+
/** The server's state at read time. */
|
|
874
|
+
readonly server: PreviewServerView;
|
|
875
|
+
}
|
|
876
|
+
/** Log read, or a classified failure. */
|
|
877
|
+
export type PreviewLogsResult = PreviewLogsSuccess | PreviewFailure;
|