@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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/cordis.patch.yml +158 -0
  4. package/lib/client.js +24890 -0
  5. package/lib/client.js.map +1 -0
  6. package/lib/host.js +3156 -0
  7. package/lib/index.js +20 -0
  8. package/lib/remote.js +1994 -0
  9. package/lib/typert.host.js +2000 -0
  10. package/package.json +136 -0
  11. package/types/client/ActionMenu.d.ts +36 -0
  12. package/types/client/Glyphs.d.ts +49 -0
  13. package/types/client/PanelHost.d.ts +24 -0
  14. package/types/client/Seats.d.ts +16 -0
  15. package/types/client/SettingsCard.d.ts +22 -0
  16. package/types/client/contract.d.ts +358 -0
  17. package/types/client/controller.d.ts +224 -0
  18. package/types/client/cx.d.ts +16 -0
  19. package/types/client/index.d.ts +39 -0
  20. package/types/client/locales.d.ts +474 -0
  21. package/types/client/panels/ChangesPanel.d.ts +22 -0
  22. package/types/client/panels/FilesPanel.d.ts +16 -0
  23. package/types/client/panels/PreviewPanel.d.ts +27 -0
  24. package/types/client/panels/TasksPanel.d.ts +28 -0
  25. package/types/client/panels/TerminalPanel.d.ts +40 -0
  26. package/types/client/panels/shared.d.ts +65 -0
  27. package/types/client/target.d.ts +23 -0
  28. package/types/client/terminal-screen.d.ts +95 -0
  29. package/types/client/ui/Alert.d.ts +30 -0
  30. package/types/client/ui/Badge.d.ts +24 -0
  31. package/types/client/ui/Button.d.ts +28 -0
  32. package/types/client/ui/Calendar.d.ts +65 -0
  33. package/types/client/ui/DatePicker.d.ts +41 -0
  34. package/types/client/ui/Dialog.d.ts +61 -0
  35. package/types/client/ui/DropdownMenu.d.ts +98 -0
  36. package/types/client/ui/Input.d.ts +25 -0
  37. package/types/client/ui/Layer.d.ts +56 -0
  38. package/types/client/ui/Select.d.ts +49 -0
  39. package/types/client/ui/Separator.d.ts +15 -0
  40. package/types/client/ui/Tabs.d.ts +49 -0
  41. package/types/client/ui/Toggle.d.ts +57 -0
  42. package/types/client/ui/Tooltip.d.ts +22 -0
  43. package/types/client/ui/anchor.d.ts +92 -0
  44. package/types/client/ui/index.d.ts +42 -0
  45. package/types/client/use-capability.d.ts +27 -0
  46. package/types/host/deletion.d.ts +57 -0
  47. package/types/host/files.d.ts +43 -0
  48. package/types/host/git.d.ts +198 -0
  49. package/types/host/index.d.ts +210 -0
  50. package/types/host/open-in.d.ts +93 -0
  51. package/types/host/paths.d.ts +55 -0
  52. package/types/host/porcelain.d.ts +51 -0
  53. package/types/host/preview.d.ts +185 -0
  54. package/types/host/run.d.ts +72 -0
  55. package/types/host/tasks.d.ts +80 -0
  56. package/types/host/terminals.d.ts +86 -0
  57. package/types/host/types.d.ts +877 -0
  58. package/types/index.d.ts +17 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The one piece of state shared by this plugin's four slot registrations.
3
+ *
4
+ * The menu trigger, the dock, and the confirmation dialog are separate slot entries with no common
5
+ * React ancestor, so the panel a person opened cannot live in a component. It lives here, in
6
+ * a `HostObservable` the registrations hand down through their inject faces' reserved `hooks`
7
+ * compartment; the renderer binds each source into a `use<Name>` selector hook, so a component
8
+ * re-renders for the slice it selected and nothing else.
9
+ * @module @achasoft/dsh-advanced-sidebar/client/controller
10
+ */
11
+ import type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots';
12
+ /** Which panel is showing in the dock. */
13
+ export type PanelKind = 'changes' | 'terminal' | 'files' | 'tasks' | 'preview';
14
+ /** The session an operation acts on, resolved once at the moment the menu is opened. */
15
+ export interface OperationTarget {
16
+ /** Session the operation acts on. */
17
+ readonly sessionId: string;
18
+ /** Human label for dialogs and the dock header. */
19
+ readonly title: string;
20
+ /**
21
+ * Absolute Host directory the panels work in: the session's own cwd, or its workspace path when
22
+ * the session has none. Absent leaves every Host-backed entry disabled, because there is nothing
23
+ * for git, a terminal, or a file listing to be relative to.
24
+ */
25
+ readonly directory: string | undefined;
26
+ }
27
+ /** The open panel, if any. */
28
+ export interface PanelState {
29
+ /** Which panel is showing; undefined while the dock is closed. */
30
+ readonly panel: PanelKind | undefined;
31
+ /** What the panel acts on. */
32
+ readonly target: OperationTarget | undefined;
33
+ }
34
+ /** One shell the Terminal panel holds open. */
35
+ export interface TerminalTab {
36
+ /** Identifies the tab for its whole life, including while its shell is still being allocated. */
37
+ readonly tabId: string;
38
+ /** The Host handle; absent while the allocation is in flight or after it failed. */
39
+ readonly terminalId: string | undefined;
40
+ /** Which shell answered. */
41
+ readonly shell: string | undefined;
42
+ /** Why the allocation failed. */
43
+ readonly error: string | undefined;
44
+ }
45
+ /** Every shell one target's Terminal panel holds, and which of them is showing. */
46
+ export interface TerminalGroup {
47
+ /** The tabs, in the order they were opened. */
48
+ readonly tabs: readonly TerminalTab[];
49
+ /** The tab whose screen is showing; absent only while the group is empty. */
50
+ readonly activeId: string | undefined;
51
+ }
52
+ /** A pending Delete waiting for confirmation. */
53
+ export interface ConfirmState {
54
+ /** What Delete would act on. */
55
+ readonly target: OperationTarget;
56
+ /** What the Host says Delete would actually do, so the dialog cannot promise a removal twice. */
57
+ readonly purges: boolean;
58
+ /** True while the request is in flight; the dialog's buttons are disabled. */
59
+ readonly busy: boolean;
60
+ }
61
+ /** A short-lived message shown under the dock, for outcomes that have no surface of their own. */
62
+ export interface NoticeState {
63
+ /** Monotonic id, so an identical repeated message still restarts the dismissal timer. */
64
+ readonly id: number;
65
+ /** Whether the message reports a failure. */
66
+ readonly tone: 'info' | 'error';
67
+ /** The message. */
68
+ readonly text: string;
69
+ }
70
+ /** Everything the surfaces read. */
71
+ export interface SidebarState {
72
+ /** The open panel. */
73
+ readonly panel: PanelState;
74
+ /** The pending Delete confirmation. */
75
+ readonly confirm: ConfirmState | undefined;
76
+ /** The current notice. */
77
+ readonly notice: NoticeState | undefined;
78
+ /**
79
+ * The dock's width in pixels after a resize, which outranks the settings value for this browser
80
+ * session. Undefined leaves the settings section in charge.
81
+ */
82
+ readonly dockWidth: number | undefined;
83
+ /**
84
+ * Terminal groups by {@link terminalKey}. Held here rather than in the panel so a shell survives
85
+ * switching to another panel or closing the dock, exactly as a terminal in an editor does; the
86
+ * Host retains its scrollback, so a reopened tab replays rather than restarts.
87
+ */
88
+ readonly terminals: Readonly<Record<string, TerminalGroup>>;
89
+ }
90
+ /**
91
+ * The key one target's terminal group is held under.
92
+ *
93
+ * The directory is part of it: a session whose working directory changed is a different place to
94
+ * have a shell in, and reusing the group would leave a tab labelled with a path its shell is not in.
95
+ * @param target - the session and directory the panel acts on.
96
+ * @returns the group key.
97
+ */
98
+ export declare function terminalKey(target: OperationTarget): string;
99
+ /**
100
+ * Holds the plugin's cross-registration state and notifies its subscribers.
101
+ *
102
+ * It is a plain observable rather than a cordis service: nothing outside this package reads it, and
103
+ * a service key would be a public name for something private to four registrations.
104
+ */
105
+ export declare class PanelController implements HostObservable<SidebarState> {
106
+ private state;
107
+ private readonly listeners;
108
+ private nextNoticeId;
109
+ /**
110
+ * Current state.
111
+ * @returns the snapshot; identity changes only when something actually moved.
112
+ */
113
+ getSnapshot(): SidebarState;
114
+ /**
115
+ * Subscribe to state changes.
116
+ * @param listener - called after every commit.
117
+ * @returns the unsubscribe.
118
+ */
119
+ subscribe(listener: () => void): () => void;
120
+ /**
121
+ * Show one panel in the dock. Choosing the panel that is already open on the same session closes
122
+ * the dock, which is what makes the menu entry read as a toggle.
123
+ * @param panel - which panel.
124
+ * @param target - what it acts on.
125
+ */
126
+ open(panel: PanelKind, target: OperationTarget): void;
127
+ /** Close the dock. */
128
+ close(): void;
129
+ /**
130
+ * Ask for confirmation before Delete commits.
131
+ * @param target - what Delete would act on.
132
+ * @param purges - whether the Host would also remove the durable log.
133
+ */
134
+ askDelete(target: OperationTarget, purges: boolean): void;
135
+ /** Mark the pending Delete as in flight. */
136
+ markDeleting(): void;
137
+ /** Dismiss the Delete confirmation without acting. */
138
+ dismissDelete(): void;
139
+ /**
140
+ * Show one message.
141
+ * @param tone - whether the message reports a failure.
142
+ * @param text - the message.
143
+ */
144
+ notify(tone: NoticeState['tone'], text: string): void;
145
+ /**
146
+ * Dismiss one message, ignoring a request for a message that has already been replaced.
147
+ * @param id - the notice to dismiss.
148
+ */
149
+ dismissNotice(id: number): void;
150
+ /**
151
+ * Withdraw everything a session owned, because that session is gone.
152
+ * @param sessionId - the session that disappeared.
153
+ */
154
+ forget(sessionId: string): void;
155
+ /**
156
+ * Store the dock width a resize settled on.
157
+ *
158
+ * Kept here as well as written to the settings section: the section is read-only on every remote
159
+ * Web Client, and a drag that cannot be persisted must still resize the dock.
160
+ * @param width - the width in pixels.
161
+ */
162
+ setDockWidth(width: number): void;
163
+ /**
164
+ * The terminal group one target holds.
165
+ * @param key - the group key from {@link terminalKey}.
166
+ * @returns the group; the empty group when nothing has been opened yet.
167
+ */
168
+ terminals(key: string): TerminalGroup;
169
+ /**
170
+ * Add one tab, in the state a tab has before its shell has been allocated, and show it.
171
+ * @param key - the group key.
172
+ * @param tabId - the caller-generated tab id, so the caller can allocate against it immediately.
173
+ */
174
+ addTerminal(key: string, tabId: string): void;
175
+ /**
176
+ * Record what a tab's allocation answered.
177
+ * @param key - the group key.
178
+ * @param tabId - the tab the allocation was for.
179
+ * @param outcome - the handle and the shell, or the failure.
180
+ */
181
+ settleTerminal(key: string, tabId: string, outcome: {
182
+ terminalId: string;
183
+ shell: string;
184
+ } | {
185
+ error: string;
186
+ }): void;
187
+ /**
188
+ * Show one tab's screen.
189
+ * @param key - the group key.
190
+ * @param tabId - the tab to show.
191
+ */
192
+ activateTerminal(key: string, tabId: string): void;
193
+ /**
194
+ * Drop one tab and show its neighbour.
195
+ * @param key - the group key.
196
+ * @param tabId - the tab to drop.
197
+ * @returns the Host handle the caller must now close, when the tab had one.
198
+ */
199
+ removeTerminal(key: string, tabId: string): string | undefined;
200
+ /**
201
+ * Drop every terminal one session owns, whatever directory it had them in.
202
+ * @param sessionId - the session.
203
+ * @returns the Host handles the caller must now close.
204
+ */
205
+ dropTerminals(sessionId: string): readonly string[];
206
+ /**
207
+ * Every open handle, for the teardown that must close them.
208
+ * @returns the Host handles this browser half still holds.
209
+ */
210
+ allTerminals(): readonly string[];
211
+ /** Close everything. Called from the plugin's teardown effect. */
212
+ reset(): void;
213
+ /**
214
+ * Replace one target's terminal group.
215
+ * @param key - the group key.
216
+ * @param group - the group after the change; an empty one is dropped rather than stored.
217
+ */
218
+ private putTerminals;
219
+ /**
220
+ * Store one state and notify.
221
+ * @param next - the committed state.
222
+ */
223
+ private commit;
224
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Class-name joining.
3
+ *
4
+ * `clsx` is what the harness's own components use, but it is not a module-table specifier, so an
5
+ * out-of-tree browser half would have to bundle a private copy of it into every plugin. Three lines
6
+ * cover everything this package needs.
7
+ * @module @achasoft/dsh-advanced-sidebar/client/cx
8
+ */
9
+ /** One class-name argument: a name, or a falsy value to skip. */
10
+ export type ClassValue = string | false | null | undefined;
11
+ /**
12
+ * Join class names, dropping the falsy ones.
13
+ * @param values - names and conditional names.
14
+ * @returns the joined class attribute, empty when nothing applied.
15
+ */
16
+ export declare function cx(...values: readonly ClassValue[]): string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Advanced sidebar plugin, browser half: three registrations over one Host endpoint and one shared
3
+ * piece of state.
4
+ *
5
+ * - `conversation.session.header.utilities` — the menu on the open session.
6
+ * - `shell.overlay` — the resizable dock holding whichever panel is open, plus the Delete
7
+ * confirmation.
8
+ * - `settings.plugin.item` — the card on the plugin-configuration tab, keyed by the namespace.
9
+ *
10
+ * There was a fourth, at the sidebar foot; it was withdrawn, so the column has no action of this
11
+ * plugin's in it and the menu acts only on the session it sits in.
12
+ *
13
+ * The seats have no common React ancestor, so what a person opened lives in a {@link PanelController}
14
+ * this module owns and hands to each registration through its inject face. Archiving and directory
15
+ * navigation go through the Web Client's own `ctx.workspaces`; everything a browser structurally
16
+ * cannot do goes through this plugin's own Remote namespace.
17
+ * @module @achasoft/dsh-advanced-sidebar/client
18
+ */
19
+ import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
20
+ export type { AdvancedSidebarKey } from './locales.ts';
21
+ export type { HeaderMenuProps, MenuInjected, PanelHostInjected, PanelHostProps, SettingsCardInjected, SettingsCardProps, Translate, } from './contract.ts';
22
+ export type { OperationTarget, PanelKind, SidebarState, TerminalGroup, TerminalTab, } from './controller.ts';
23
+ /**
24
+ * Required services of the OUTER plugin: locale and the Remote mount point.
25
+ *
26
+ * Deliberately NOT `remote.advancedSidebar`. This plugin's apply creates that namespace by mounting
27
+ * its own contribution, so it cannot also wait for it — and Cordis refuses to read a service the
28
+ * fiber did not inject. Both halves of that bind are resolved by the child plugin below, which
29
+ * injects `remote.advancedSidebar` after the parent has provided it.
30
+ */
31
+ export declare const inject: string[];
32
+ /**
33
+ * Client plugin body: mount this plugin's Remote namespace, register the dictionaries, then hand
34
+ * the surface to a child fiber that can inject the namespace its parent just provided.
35
+ * @param ctx - client root context.
36
+ * @returns after the `advancedSidebar` namespace is callable; its methods are withdrawn when this
37
+ * fiber unloads.
38
+ */
39
+ export declare function apply(ctx: ClientContext): Promise<void>;