@keith9681/dsh-sidebar 0.15.2
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 +0 -0
- package/README_EN.md +0 -0
- package/cordis.patch.yml +49 -0
- package/lib/client-editor.js +34651 -0
- package/lib/client-mermaid.js +200629 -0
- package/lib/client-registry.js +13388 -0
- package/lib/client-terminal.js +8904 -0
- package/lib/client.js +13388 -0
- package/lib/index.js +3959 -0
- package/lib/invariant.js +22 -0
- package/lib/types/agent-pty.d.ts +226 -0
- package/lib/types/browser-probe.d.ts +15 -0
- package/lib/types/bundle-route.d.ts +12 -0
- package/lib/types/client/BrowserView.d.ts +22 -0
- package/lib/types/client/DiffTab.d.ts +6 -0
- package/lib/types/client/DiffView.d.ts +51 -0
- package/lib/types/client/EditorHost.d.ts +12 -0
- package/lib/types/client/FileTree.d.ts +36 -0
- package/lib/types/client/GitView.d.ts +8 -0
- package/lib/types/client/OrphanedTab.d.ts +11 -0
- package/lib/types/client/PdfView.d.ts +6 -0
- package/lib/types/client/RenderBoundary.d.ts +32 -0
- package/lib/types/client/SandboxStatusBar.d.ts +10 -0
- package/lib/types/client/SideCardSection.d.ts +74 -0
- package/lib/types/client/SideChatView.d.ts +16 -0
- package/lib/types/client/Sidebar.d.ts +6 -0
- package/lib/types/client/SubagentView.d.ts +16 -0
- package/lib/types/client/TabBar.d.ts +43 -0
- package/lib/types/client/TerminalView.d.ts +24 -0
- package/lib/types/client/TextEditor.d.ts +10 -0
- package/lib/types/client/TreePanel.d.ts +23 -0
- package/lib/types/client/UploadOverlay.d.ts +20 -0
- package/lib/types/client/add-plugin-modal.d.ts +15 -0
- package/lib/types/client/api.d.ts +268 -0
- package/lib/types/client/binary-download.d.ts +12 -0
- package/lib/types/client/breakpoints.d.ts +12 -0
- package/lib/types/client/browser.d.ts +50 -0
- package/lib/types/client/builtins/index.d.ts +18 -0
- package/lib/types/client/builtins/tabs.d.ts +11 -0
- package/lib/types/client/builtins/viewers.d.ts +3 -0
- package/lib/types/client/chunk-loader.d.ts +124 -0
- package/lib/types/client/chunks/editor.d.ts +9 -0
- package/lib/types/client/chunks/mermaid.d.ts +10 -0
- package/lib/types/client/chunks/terminal.d.ts +9 -0
- package/lib/types/client/cm-themes.d.ts +24 -0
- package/lib/types/client/conversation-draft.d.ts +14 -0
- package/lib/types/client/desktop-env.d.ts +35 -0
- package/lib/types/client/editable-state.d.ts +27 -0
- package/lib/types/client/editor-load.d.ts +66 -0
- package/lib/types/client/frame-batcher.d.ts +24 -0
- package/lib/types/client/icons.d.ts +57 -0
- package/lib/types/client/image-types.d.ts +3 -0
- package/lib/types/client/ime-guard.d.ts +36 -0
- package/lib/types/client/index.d.ts +19 -0
- package/lib/types/client/intercept.d.ts +33 -0
- package/lib/types/client/lang.d.ts +12 -0
- package/lib/types/client/lazy-chunk.d.ts +25 -0
- package/lib/types/client/link-intercept.d.ts +42 -0
- package/lib/types/client/locales.d.ts +366 -0
- package/lib/types/client/mermaid-blocks.d.ts +41 -0
- package/lib/types/client/mermaid-sanitize.d.ts +2 -0
- package/lib/types/client/mermaid.d.ts +12 -0
- package/lib/types/client/open-when-sized.d.ts +20 -0
- package/lib/types/client/open-with-settings.d.ts +4 -0
- package/lib/types/client/open-with.d.ts +87 -0
- package/lib/types/client/openpath-intercept.d.ts +41 -0
- package/lib/types/client/paths.d.ts +35 -0
- package/lib/types/client/pdf-types.d.ts +2 -0
- package/lib/types/client/plugin-settings.d.ts +8 -0
- package/lib/types/client/plugins-shared.d.ts +27 -0
- package/lib/types/client/plugins-tabs.d.ts +3 -0
- package/lib/types/client/plugins-viewers.d.ts +3 -0
- package/lib/types/client/prefs.d.ts +41 -0
- package/lib/types/client/produced-files.d.ts +23 -0
- package/lib/types/client/selection-payload.d.ts +27 -0
- package/lib/types/client/service.d.ts +440 -0
- package/lib/types/client/settings-nav-icon.d.ts +19 -0
- package/lib/types/client/shell-presets.d.ts +48 -0
- package/lib/types/client/sidechat-transcript.d.ts +103 -0
- package/lib/types/client/split-pane.d.ts +30 -0
- package/lib/types/client/state.d.ts +359 -0
- package/lib/types/client/subagent-detect.d.ts +54 -0
- package/lib/types/client/subagent-jobs.d.ts +63 -0
- package/lib/types/client/tab-content-memo.d.ts +33 -0
- package/lib/types/client/terminal-font.d.ts +20 -0
- package/lib/types/client/theme.d.ts +45 -0
- package/lib/types/client/titlebar-strip.d.ts +23 -0
- package/lib/types/client/upload.d.ts +69 -0
- package/lib/types/client/wco.d.ts +47 -0
- package/lib/types/config.d.ts +64 -0
- package/lib/types/context-types.d.ts +603 -0
- package/lib/types/fs-operations.d.ts +28 -0
- package/lib/types/fs-search.d.ts +24 -0
- package/lib/types/fs-tree.d.ts +51 -0
- package/lib/types/git.d.ts +82 -0
- package/lib/types/html-route.d.ts +59 -0
- package/lib/types/index.d.ts +47 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/jobs-routes.d.ts +45 -0
- package/lib/types/open-external.d.ts +24 -0
- package/lib/types/prefs-shared.d.ts +225 -0
- package/lib/types/pty-deps.d.ts +78 -0
- package/lib/types/pty-manager.d.ts +168 -0
- package/lib/types/sidechat-core.d.ts +172 -0
- package/lib/types/sidechat-routes.d.ts +30 -0
- package/lib/types/subagent-activity.d.ts +44 -0
- package/lib/types/subagent-live-route.d.ts +44 -0
- package/lib/types/tools.d.ts +31 -0
- package/lib/types/trust-fence.d.ts +24 -0
- package/lib/types/wire.d.ts +38 -0
- package/package.json +173 -0
- package/scripts/install.ps1 +289 -0
- package/scripts/install.sh +287 -0
- package/src/agent-pty.ts +527 -0
- package/src/browser-probe.ts +26 -0
- package/src/bundle-route.ts +129 -0
- package/src/client/BrowserView.tsx +253 -0
- package/src/client/DiffTab.tsx +110 -0
- package/src/client/DiffView.tsx +305 -0
- package/src/client/EditorHost.tsx +525 -0
- package/src/client/FileTree.tsx +653 -0
- package/src/client/GitView.tsx +558 -0
- package/src/client/OrphanedTab.tsx +27 -0
- package/src/client/PdfView.tsx +110 -0
- package/src/client/RenderBoundary.tsx +49 -0
- package/src/client/SandboxStatusBar.tsx +60 -0
- package/src/client/SideCardSection.module.css +960 -0
- package/src/client/SideCardSection.tsx +1152 -0
- package/src/client/SideChatView.module.css +437 -0
- package/src/client/SideChatView.tsx +644 -0
- package/src/client/Sidebar.tsx +1148 -0
- package/src/client/SubagentView.module.css +547 -0
- package/src/client/SubagentView.tsx +883 -0
- package/src/client/TabBar.tsx +305 -0
- package/src/client/TerminalView.tsx +383 -0
- package/src/client/TextEditor.tsx +500 -0
- package/src/client/TreePanel.tsx +273 -0
- package/src/client/UploadOverlay.tsx +62 -0
- package/src/client/add-plugin-modal.tsx +199 -0
- package/src/client/api.ts +335 -0
- package/src/client/binary-download.tsx +23 -0
- package/src/client/breakpoints.ts +51 -0
- package/src/client/browser.ts +119 -0
- package/src/client/builtins/index.ts +37 -0
- package/src/client/builtins/tabs.tsx +331 -0
- package/src/client/builtins/viewers.tsx +125 -0
- package/src/client/chunk-loader.ts +351 -0
- package/src/client/chunks/editor.tsx +9 -0
- package/src/client/chunks/mermaid.tsx +10 -0
- package/src/client/chunks/terminal.tsx +9 -0
- package/src/client/cm-themes.ts +129 -0
- package/src/client/conversation-draft.ts +29 -0
- package/src/client/css-modules.d.ts +5 -0
- package/src/client/desktop-env.ts +72 -0
- package/src/client/editable-state.ts +70 -0
- package/src/client/editor-load.ts +92 -0
- package/src/client/frame-batcher.ts +56 -0
- package/src/client/icons.tsx +161 -0
- package/src/client/image-types.ts +8 -0
- package/src/client/ime-guard.ts +47 -0
- package/src/client/index.tsx +369 -0
- package/src/client/intercept.tsx +110 -0
- package/src/client/lang.ts +103 -0
- package/src/client/layout.css +94 -0
- package/src/client/lazy-chunk.tsx +89 -0
- package/src/client/link-intercept.ts +73 -0
- package/src/client/locales.ts +734 -0
- package/src/client/mermaid-blocks.ts +110 -0
- package/src/client/mermaid-sanitize.ts +93 -0
- package/src/client/mermaid.tsx +401 -0
- package/src/client/open-when-sized.ts +43 -0
- package/src/client/open-with-settings.tsx +135 -0
- package/src/client/open-with.ts +221 -0
- package/src/client/openpath-intercept.ts +62 -0
- package/src/client/paths.ts +47 -0
- package/src/client/pdf-types.ts +4 -0
- package/src/client/plugin-settings.ts +43 -0
- package/src/client/plugins-shared.ts +29 -0
- package/src/client/plugins-tabs.ts +87 -0
- package/src/client/plugins-viewers.ts +30 -0
- package/src/client/prefs.ts +207 -0
- package/src/client/produced-files.ts +91 -0
- package/src/client/selection-payload.ts +86 -0
- package/src/client/service.ts +838 -0
- package/src/client/settings-nav-icon.ts +45 -0
- package/src/client/shell-presets.ts +83 -0
- package/src/client/sidebar.module.css +2577 -0
- package/src/client/sidechat-transcript.ts +321 -0
- package/src/client/split-pane.tsx +322 -0
- package/src/client/state.ts +1175 -0
- package/src/client/subagent-detect.ts +137 -0
- package/src/client/subagent-jobs.ts +161 -0
- package/src/client/tab-content-memo.ts +46 -0
- package/src/client/terminal-font.ts +28 -0
- package/src/client/theme.ts +110 -0
- package/src/client/titlebar-strip.ts +37 -0
- package/src/client/upload.ts +187 -0
- package/src/client/wco.ts +120 -0
- package/src/config.ts +155 -0
- package/src/context-types.ts +610 -0
- package/src/fs-operations.ts +99 -0
- package/src/fs-search.ts +86 -0
- package/src/fs-tree.ts +158 -0
- package/src/git.ts +244 -0
- package/src/html-route.ts +106 -0
- package/src/index.ts +1132 -0
- package/src/invariant.ts +32 -0
- package/src/jobs-routes.ts +257 -0
- package/src/open-external.ts +90 -0
- package/src/prefs-shared.ts +268 -0
- package/src/pty-deps.ts +240 -0
- package/src/pty-manager.ts +376 -0
- package/src/sidechat-core.ts +468 -0
- package/src/sidechat-routes.ts +344 -0
- package/src/subagent-activity.ts +91 -0
- package/src/subagent-live-route.ts +93 -0
- package/src/tools.ts +479 -0
- package/src/trust-fence.ts +77 -0
- package/src/wire.ts +100 -0
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/invariant.ts
|
|
2
|
+
const PACKAGE_NAME = "dsh-better-sidebar";
|
|
3
|
+
/** Cordis companion plugin name. */
|
|
4
|
+
const name = "dsh-better-sidebar-invariant";
|
|
5
|
+
/** Service required before the companion can reserve package ownership. */
|
|
6
|
+
const inject = ["invariants"];
|
|
7
|
+
/**
|
|
8
|
+
* No runtime invariant: the sidebar owns no service state or event protocol
|
|
9
|
+
* of its own — every route is mounted under the host's webServer fence, the
|
|
10
|
+
* pty lifecycle is exercised by the smoke spec, and the panel's store is a
|
|
11
|
+
* plain snapshot registry asserted by the behavior specs. The route fence,
|
|
12
|
+
* pty quota, and store semantics are each observed through their seams.
|
|
13
|
+
*/
|
|
14
|
+
const install = () => {};
|
|
15
|
+
/**
|
|
16
|
+
* Register this package's invariant companion.
|
|
17
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
18
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
19
|
+
*/
|
|
20
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
21
|
+
//#endregion
|
|
22
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import type { IPty } from 'node-pty';
|
|
2
|
+
import { type NodePtyModule } from './pty-deps.ts';
|
|
3
|
+
/** POSIX signals the registry forwards to a live pty. */
|
|
4
|
+
export declare const ALLOWED_SIGNALS: readonly ["SIGINT", "SIGTERM", "SIGKILL", "SIGHUP", "SIGTSTP"];
|
|
5
|
+
/** Signal name accepted by `signal()`. */
|
|
6
|
+
export type AgentTerminalSignal = (typeof ALLOWED_SIGNALS)[number];
|
|
7
|
+
/** Default read page size (lines) when the caller omits `count`. */
|
|
8
|
+
export declare const DEFAULT_READ_COUNT = 500;
|
|
9
|
+
/** Smallest pty dimension the registry accepts (mirrors the tool contract). */
|
|
10
|
+
export declare const TERMINAL_DIM_MIN = 2;
|
|
11
|
+
/** Largest pty dimension the registry accepts (mirrors the tool contract). */
|
|
12
|
+
export declare const TERMINAL_DIM_MAX = 1024;
|
|
13
|
+
/** Clamp one cols×rows pair into the supported pty range (flooring decimals). */
|
|
14
|
+
export declare function clampDims(cols: number, rows: number): {
|
|
15
|
+
cols: number;
|
|
16
|
+
rows: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Serializable snapshot of one agent terminal — the shape the model sees
|
|
20
|
+
* through `terminal_list` and the sidebar sees through the push endpoint.
|
|
21
|
+
* Carries no pty reference and no transcript (those are reached through
|
|
22
|
+
* dedicated read/attach paths), and no sessionId: ownership is registry
|
|
23
|
+
* internals, scoped by the caller (list filters by session, the push
|
|
24
|
+
* endpoint scopes by its query param), never part of the serialized view.
|
|
25
|
+
*/
|
|
26
|
+
export interface AgentTerminalSnapshot {
|
|
27
|
+
/** Stable opaque handle the model passes back to other terminal_* tools. */
|
|
28
|
+
uuid: string;
|
|
29
|
+
/** Display title the model chose at create time. */
|
|
30
|
+
title: string;
|
|
31
|
+
/** The command the model asked to run at create time (verbatim). */
|
|
32
|
+
command: string;
|
|
33
|
+
/** Whether the top-level process has exited. */
|
|
34
|
+
exited: boolean;
|
|
35
|
+
/** Exit code if exited normally; absent until the process exits. */
|
|
36
|
+
exitCode?: number | null;
|
|
37
|
+
/** Exit signal name if the process was killed by a signal; null otherwise. */
|
|
38
|
+
exitSignal?: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** One live agent terminal. */
|
|
41
|
+
export interface AgentTerminalHandle {
|
|
42
|
+
/** Stable opaque handle. */
|
|
43
|
+
uuid: string;
|
|
44
|
+
/** Owning conversation id. */
|
|
45
|
+
sessionId: string;
|
|
46
|
+
/** Display title. */
|
|
47
|
+
title: string;
|
|
48
|
+
/** The command written to stdin right after spawn. */
|
|
49
|
+
command: string;
|
|
50
|
+
/** The working directory the process was spawned with. */
|
|
51
|
+
cwd: string;
|
|
52
|
+
/** The live pty process. */
|
|
53
|
+
pty: IPty;
|
|
54
|
+
/** Output accumulated since spawn (bounded; head dropped when over the limit). */
|
|
55
|
+
transcript: string;
|
|
56
|
+
/** Whether the top-level process exited (transcript stays replayable). */
|
|
57
|
+
exited: boolean;
|
|
58
|
+
/** Exit code once known. */
|
|
59
|
+
exitCode?: number | null;
|
|
60
|
+
/** Exit signal number once known (POSIX only; undefined on Windows). */
|
|
61
|
+
exitSignal?: number | null;
|
|
62
|
+
}
|
|
63
|
+
/** Read result shape (mirrors the official tool-pty terminal_read contract). */
|
|
64
|
+
export interface AgentTerminalReadResult {
|
|
65
|
+
/** The slice of transcript text for the requested page. */
|
|
66
|
+
text: string;
|
|
67
|
+
/** Total lines in the retained transcript (the page may be a subset). */
|
|
68
|
+
totalLines: number;
|
|
69
|
+
/** 0-based index of the first line in `text` (inclusive). */
|
|
70
|
+
lineBegin: number;
|
|
71
|
+
/** 0-based index of the last line in `text` (exclusive). */
|
|
72
|
+
lineEnd: number;
|
|
73
|
+
}
|
|
74
|
+
/** Outcome of {@link AgentPtyRegistry.waitFor}. */
|
|
75
|
+
export type AgentTerminalWaitResult = {
|
|
76
|
+
/** The needle was found in the transcript. */
|
|
77
|
+
kind: 'found';
|
|
78
|
+
/** The matched substring. */
|
|
79
|
+
needle: string;
|
|
80
|
+
/** 0-based line index (in the retained transcript) where the needle first appeared. */
|
|
81
|
+
line: number;
|
|
82
|
+
/** 0-based column index within that line where the match starts. */
|
|
83
|
+
column: number;
|
|
84
|
+
/** Elapsed wall-clock milliseconds from the wait start to the match. */
|
|
85
|
+
elapsedMs: number;
|
|
86
|
+
} | {
|
|
87
|
+
/** The needle did not appear before the timeout. */
|
|
88
|
+
kind: 'timeout';
|
|
89
|
+
/** The needle that was awaited. */
|
|
90
|
+
needle: string;
|
|
91
|
+
/** The configured timeout in milliseconds. */
|
|
92
|
+
timeoutMs: number;
|
|
93
|
+
/** Total lines retained when the timeout fired (call terminal_read to inspect). */
|
|
94
|
+
totalLines: number;
|
|
95
|
+
} | {
|
|
96
|
+
/** The terminal exited before the needle appeared. */
|
|
97
|
+
kind: 'exited';
|
|
98
|
+
/** The needle that was awaited. */
|
|
99
|
+
needle: string;
|
|
100
|
+
/** The exit code, if known. */
|
|
101
|
+
exitCode?: number | null;
|
|
102
|
+
/** The exit signal name, if the process was killed by a signal. */
|
|
103
|
+
exitSignal?: string | null;
|
|
104
|
+
};
|
|
105
|
+
/** Snapshot projection of a handle (drops the pty reference and transcript). */
|
|
106
|
+
export declare function snapshotOf(handle: AgentTerminalHandle): AgentTerminalSnapshot;
|
|
107
|
+
/**
|
|
108
|
+
* The agent terminal registry. The constructor takes the resolved shell
|
|
109
|
+
* binary (the same `defaultShell()` the UI-tab registry uses) and runs the
|
|
110
|
+
* spawn-helper chmod fix once at construction so the first agent terminal
|
|
111
|
+
* does not race a lazy fixer.
|
|
112
|
+
*/
|
|
113
|
+
export declare class AgentPtyRegistry {
|
|
114
|
+
private readonly shell;
|
|
115
|
+
private readonly shellArgs;
|
|
116
|
+
/** The loaded node-pty module (injected so a broken install degrades instead of crashing the plugin). */
|
|
117
|
+
private readonly nodePty;
|
|
118
|
+
private readonly sessions;
|
|
119
|
+
private readonly changeListeners;
|
|
120
|
+
constructor(shell: string, shellArgs?: string[],
|
|
121
|
+
/** The loaded node-pty module (injected so a broken install degrades instead of crashing the plugin). */
|
|
122
|
+
nodePty?: NodePtyModule);
|
|
123
|
+
/**
|
|
124
|
+
* Spawn one agent terminal: start the shell in `cwd`, then write
|
|
125
|
+
* `command + '\n'` to stdin so the command runs in the fresh shell. The
|
|
126
|
+
* terminal stays alive after the command exits — the model can send more
|
|
127
|
+
* input through `terminal_send` until it calls `terminal_close` or the
|
|
128
|
+
* user closes the sidebar tab. An empty `command` spawns a bare shell.
|
|
129
|
+
* @returns the new handle's uuid (the model-facing opaque id).
|
|
130
|
+
*/
|
|
131
|
+
create(sessionId: string, title: string, command: string, cwd: string, cols?: number, rows?: number, shell?: string, shellArgs?: string[]): string;
|
|
132
|
+
/** All live agent terminals belonging to one conversation. */
|
|
133
|
+
list(sessionId: string): AgentTerminalSnapshot[];
|
|
134
|
+
/** Resolve a live handle by uuid, or throw `not-found`. */
|
|
135
|
+
private expect;
|
|
136
|
+
/**
|
|
137
|
+
* Resolve a live handle that belongs to `sessionId`, or throw `not-found`.
|
|
138
|
+
* The model-facing tools call this before every uuid-keyed operation: a
|
|
139
|
+
* uuid from another session is indistinguishable from an unknown one, so a
|
|
140
|
+
* model can never reach (or probe) a terminal it does not own.
|
|
141
|
+
*/
|
|
142
|
+
assertOwned(uuid: string, sessionId: string): AgentTerminalHandle;
|
|
143
|
+
/** Resolve a handle's snapshot, or undefined if it does not exist. */
|
|
144
|
+
snapshot(uuid: string): AgentTerminalSnapshot | undefined;
|
|
145
|
+
/** Write raw text to a terminal's stdin (tmux `send-keys` semantics). */
|
|
146
|
+
send(uuid: string, text: string): void;
|
|
147
|
+
/**
|
|
148
|
+
* Read one bounded page of the retained transcript. `offset` is a 0-based
|
|
149
|
+
* line index from the start of the retained transcript (default 0);
|
|
150
|
+
* `count` caps the page size (default 500). A negative `offset` reads
|
|
151
|
+
* from the end (e.g. -50 reads the last 50 lines). Returns `totalLines`
|
|
152
|
+
* so the model can paginate.
|
|
153
|
+
*/
|
|
154
|
+
read(uuid: string, offset?: number, count?: number): AgentTerminalReadResult;
|
|
155
|
+
/**
|
|
156
|
+
* Resize a terminal's pty, clamped to the 2..1024 sane range.
|
|
157
|
+
* @returns the dimensions actually applied (the caller echoes these, so the
|
|
158
|
+
* reported value always matches the pty).
|
|
159
|
+
*/
|
|
160
|
+
resize(uuid: string, cols: number, rows: number): {
|
|
161
|
+
cols: number;
|
|
162
|
+
rows: number;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Wait for `needle` to appear in a terminal's transcript, or for the
|
|
166
|
+
* terminal to exit, or for the timeout to elapse — whichever happens
|
|
167
|
+
* first. The wait polls the live transcript every ~50ms and short-circuits
|
|
168
|
+
* on `signal` abort (re-thrown as the abort reason so the tool layer
|
|
169
|
+
* surfaces cancellation).
|
|
170
|
+
*
|
|
171
|
+
* The match scans the FULL retained transcript on each poll, not just the
|
|
172
|
+
* delta since the last poll — a needle that scrolled past the most recent
|
|
173
|
+
* chunk but is still within the ~1 MiB bound is still a match. The
|
|
174
|
+
* returned line/column locate the FIRST occurrence (oldest), which is what
|
|
175
|
+
* a user watching the terminal would have seen first.
|
|
176
|
+
*
|
|
177
|
+
* The implementation uses polling (not pty onData subscription) because
|
|
178
|
+
* node-pty's onData fires before the registry's own onData listener
|
|
179
|
+
* updates the transcript (listener order is not guaranteed), and on
|
|
180
|
+
* Windows ConPTY output can arrive in bursts with batching delays that
|
|
181
|
+
* make event-driven wakeups unreliable. A 50ms poll is fast enough for
|
|
182
|
+
* interactive use and simple enough to be obviously correct.
|
|
183
|
+
* @param uuid - terminal to watch.
|
|
184
|
+
* @param needle - substring to search for (case-sensitive, verbatim).
|
|
185
|
+
* @param timeoutMs - max wait; default 10000 (10s). Clamped to ≥100ms.
|
|
186
|
+
* @param signal - caller-owned cancellation; aborts the wait re-throwing.
|
|
187
|
+
* @returns one of `found` / `timeout` / `exited`.
|
|
188
|
+
*/
|
|
189
|
+
waitFor(uuid: string, needle: string, timeoutMs?: number, signal?: AbortSignal): Promise<AgentTerminalWaitResult>;
|
|
190
|
+
/**
|
|
191
|
+
* Send a POSIX signal to a terminal's foreground process.
|
|
192
|
+
*
|
|
193
|
+
* Two delivery paths, by signal kind:
|
|
194
|
+
* - **Interactive control signals** (SIGINT, SIGTSTP) are delivered by
|
|
195
|
+
* writing the corresponding control character to the pty stdin. This is
|
|
196
|
+
* how a real terminal sends Ctrl+C / Ctrl+Z: the byte hits the kernel
|
|
197
|
+
* line discipline (POSIX ISIG mode) or the ConPTY input pipeline
|
|
198
|
+
* (Windows), which translates it into a SIGINT/SIGTSTP for the
|
|
199
|
+
* foreground process group. This works on every platform — calling
|
|
200
|
+
* `node-pty.kill('SIGINT')` throws on Windows and is fragile on POSIX,
|
|
201
|
+
* but writing `\x03` is universally correct.
|
|
202
|
+
* - **Termination signals** (SIGKILL, SIGTERM, SIGHUP) use `pty.kill()`,
|
|
203
|
+
* which maps to the platform's process-termination path (POSIX
|
|
204
|
+
* `kill(2)`, Windows `TerminateProcess`). These cannot be faked with
|
|
205
|
+
* control characters.
|
|
206
|
+
*/
|
|
207
|
+
signal(uuid: string, signal: AgentTerminalSignal): void;
|
|
208
|
+
/**
|
|
209
|
+
* Close a terminal and drop its state. Idempotent: a second close of the
|
|
210
|
+
* same uuid is a no-op. Returns true iff a live handle was actually
|
|
211
|
+
* dropped.
|
|
212
|
+
*/
|
|
213
|
+
close(uuid: string): boolean;
|
|
214
|
+
/** Resolve a live handle by uuid (for the WS attach path). */
|
|
215
|
+
get(uuid: string): AgentTerminalHandle | undefined;
|
|
216
|
+
/**
|
|
217
|
+
* Subscribe to registry changes (create / close / exit). The sidebar push
|
|
218
|
+
* endpoint uses this to forward snapshots to the connected view. Returns
|
|
219
|
+
* the unsubscribe function.
|
|
220
|
+
*/
|
|
221
|
+
subscribe(listener: () => void): () => void;
|
|
222
|
+
/** Close every agent terminal (plugin teardown). */
|
|
223
|
+
disposeAll(): void;
|
|
224
|
+
/** Fire every change listener (callers wrap in try/catch if needed). */
|
|
225
|
+
private notify;
|
|
226
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for the `browser.probe` route (sidebar browser): the host
|
|
3
|
+
* fetches the response HEADERS of a URL the user is browsing and the client
|
|
4
|
+
* decides whether the target site forbids being embedded (X-Frame-Options /
|
|
5
|
+
* CSP frame-ancestors are exactly the signals the browser enforces when it
|
|
6
|
+
* refuses an iframe load). Kept dependency-free so the parser is
|
|
7
|
+
* unit-testable.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Extract the `frame-ancestors` source list of a Content-Security-Policy
|
|
11
|
+
* header, or undefined when the directive is absent (or empty). The
|
|
12
|
+
* directive is the only one with a source list; sources are space-separated
|
|
13
|
+
* tokens (`'none'`, `'self'`, `*`, or origins).
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractFrameAncestors(csp: string | null): string[] | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Context, SidebarHttpRequest, SidebarHttpResponse } from './context-types.ts';
|
|
2
|
+
/** The chunk names the client may request (mirror of src/client/chunk-loader.ts). */
|
|
3
|
+
export declare const CHUNK_NAMES: readonly ["terminal", "editor", "mermaid"];
|
|
4
|
+
export type ChunkName = (typeof CHUNK_NAMES)[number];
|
|
5
|
+
/**
|
|
6
|
+
* Build the /sidebar/bundle route handler. `fence` is the shared browser-
|
|
7
|
+
* trust check every /sidebar route applies; `chunkDir` is the directory the
|
|
8
|
+
* chunk scripts live in (overridable for tests).
|
|
9
|
+
*/
|
|
10
|
+
export declare function createBundleRouteHandler(fence: (req: SidebarHttpRequest) => boolean, chunkDir?: string): (req: SidebarHttpRequest, res: SidebarHttpResponse) => Promise<void>;
|
|
11
|
+
/** Register the /sidebar/bundle route (disposed with the fiber). */
|
|
12
|
+
export declare function registerBundleRoute(ctx: Context, fence: (req: SidebarHttpRequest) => boolean): () => void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TabComponentProps } from './service.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The browser iframe sandbox tokens. NO allow-same-origin (opaque origin —
|
|
4
|
+
* no GUI storage/API access), NO allow-top-navigation (a browsed page must
|
|
5
|
+
* not hijack the GUI). allow-forms/allow-popups/allow-downloads/allow-modals
|
|
6
|
+
* keep login flows working; allow-popups-to-escape-sandbox lets OAuth
|
|
7
|
+
* popups open as normal tabs (they are cross-origin to the GUI either way).
|
|
8
|
+
*/
|
|
9
|
+
export declare const BROWSER_IFRAME_SANDBOX = "allow-scripts allow-forms allow-popups allow-downloads allow-modals allow-popups-to-escape-sandbox";
|
|
10
|
+
export declare function BrowserView(props: TabComponentProps): import("react").JSX.Element;
|
|
11
|
+
/**
|
|
12
|
+
* The embed-refusal panel: shown when the probed site forbids being
|
|
13
|
+
* displayed inside other pages (X-Frame-Options / frame-ancestors) — the
|
|
14
|
+
* iframe would only show the browser's "refused to connect" blank. Explains
|
|
15
|
+
* the reason and offers the real-browser open plus a load-anyway escape.
|
|
16
|
+
* Exported so the copy and the actions are testable without a DOM.
|
|
17
|
+
*/
|
|
18
|
+
export declare function BrowserEmbedBlocked(props: {
|
|
19
|
+
url: string;
|
|
20
|
+
onOpenInBrowser: () => void;
|
|
21
|
+
onLoadAnyway: () => void;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** One rendered diff line. */
|
|
2
|
+
export interface DiffLine {
|
|
3
|
+
kind: 'ctx' | 'del' | 'add' | 'meta';
|
|
4
|
+
/** The line content without its diff marker ('' for the no-newline marker). */
|
|
5
|
+
text: string;
|
|
6
|
+
/** Old-side line number (null for pure additions / metadata). */
|
|
7
|
+
oldNum: number | null;
|
|
8
|
+
/** New-side line number (null for pure deletions / metadata). */
|
|
9
|
+
newNum: number | null;
|
|
10
|
+
}
|
|
11
|
+
/** One parsed hunk. */
|
|
12
|
+
export interface DiffHunk {
|
|
13
|
+
/** The old-side start line (`-a[,b]`). */
|
|
14
|
+
oldStart: number;
|
|
15
|
+
/** The new-side start line (`+c[,d]`). */
|
|
16
|
+
newStart: number;
|
|
17
|
+
/** The section text after the trailing `@@` (may be empty). */
|
|
18
|
+
header: string;
|
|
19
|
+
lines: DiffLine[];
|
|
20
|
+
}
|
|
21
|
+
/** One parsed file section of a unified diff. */
|
|
22
|
+
export interface DiffFile {
|
|
23
|
+
/** The `---` path verbatim ('/dev/null' for a new file). */
|
|
24
|
+
oldPath: string;
|
|
25
|
+
/** The `+++` path verbatim ('/dev/null' for a deleted file). */
|
|
26
|
+
newPath: string;
|
|
27
|
+
/** The file changed with binary content: no hunks to draw. */
|
|
28
|
+
binary: boolean;
|
|
29
|
+
hunks: DiffHunk[];
|
|
30
|
+
}
|
|
31
|
+
/** The parsed unified diff. */
|
|
32
|
+
export interface ParsedDiff {
|
|
33
|
+
files: DiffFile[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parse `git diff --no-color` output into file sections and hunks. Rows
|
|
37
|
+
* outside a file section (leading noise) and metadata rows between the
|
|
38
|
+
* `diff --git`/`---`/`+++` headers and the first hunk (index lines, mode
|
|
39
|
+
* changes, rename/similarity lines) are skipped; a section that never
|
|
40
|
+
* reaches a hunk (a mode/rename-only change) stays hunkless so the caller
|
|
41
|
+
* can still draw its path.
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseUnifiedDiff(text: string): ParsedDiff;
|
|
44
|
+
export interface DiffViewProps {
|
|
45
|
+
/** Unified diff text (`git.diff` or `git.commit-diff` payloads). */
|
|
46
|
+
diff: string;
|
|
47
|
+
/** Untracked-file content: when present, renders as a full-file addition instead of parsing. */
|
|
48
|
+
untrackedPath?: string;
|
|
49
|
+
untrackedContent?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare function DiffView({ diff, untrackedPath, untrackedContent }: DiffViewProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Context } from '../context-types.ts';
|
|
2
|
+
import { type SessionScope } from './api.ts';
|
|
3
|
+
import { type SidebarStore, type SidebarTab } from './state.ts';
|
|
4
|
+
export declare function EditorHost(props: {
|
|
5
|
+
ctx: Context;
|
|
6
|
+
store: SidebarStore;
|
|
7
|
+
scope: SessionScope;
|
|
8
|
+
tab: SidebarTab;
|
|
9
|
+
expanded: string[];
|
|
10
|
+
onToggleDir: (path: string) => void;
|
|
11
|
+
onReferenceFile: (path: string) => void;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { OpenWithTarget } from './open-with.ts';
|
|
2
|
+
import { type UploadItem } from './upload.ts';
|
|
3
|
+
/** Root label: the last path segment (mirror of the host rootLabel). */
|
|
4
|
+
export declare function baseName(path: string): string;
|
|
5
|
+
export declare function FileTree(props: {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
cwd: string | undefined;
|
|
8
|
+
expanded: string[];
|
|
9
|
+
onToggle: (path: string) => void;
|
|
10
|
+
onOpenFile: (path: string) => void;
|
|
11
|
+
/** Context-menu "open in a new tab" (file rows; absent → no entry). */
|
|
12
|
+
onOpenFileNewTab?: (path: string) => void;
|
|
13
|
+
/** Context-menu "open to the side" (file rows; absent → no entry). */
|
|
14
|
+
onOpenFileSide?: (path: string) => void;
|
|
15
|
+
/**
|
|
16
|
+
* The "open with" menu: resolved external targets (already SSH-filtered
|
|
17
|
+
* and in menu order). Absent → the whole section is hidden.
|
|
18
|
+
*/
|
|
19
|
+
openWithTargets?: OpenWithTarget[];
|
|
20
|
+
/** Ids of targets pinned to the menu's top level (subset of the ids). */
|
|
21
|
+
openWithPinned?: string[];
|
|
22
|
+
/** Whether the workspace is remote (appends the SSH hint to target labels). */
|
|
23
|
+
openWithSsh?: boolean;
|
|
24
|
+
/** Open one target externally (reveal or URL — the caller decides). */
|
|
25
|
+
onOpenWith?: (targetId: string, path: string) => void;
|
|
26
|
+
/** Toggle one target's pinned state (the submenu row's pushpin). */
|
|
27
|
+
onToggleOpenWithPin?: (targetId: string) => void;
|
|
28
|
+
/** Insert `@<relative path>` into the composer draft. */
|
|
29
|
+
onReferenceFile: (path: string) => void;
|
|
30
|
+
/** Bump to wipe the level cache and reload the visible set. */
|
|
31
|
+
refreshTick: number;
|
|
32
|
+
/** Upload into `dir` (absolute, inside the workspace); runs in the caller. */
|
|
33
|
+
onUploadRequest: (dir: string, items: UploadItem[]) => void;
|
|
34
|
+
/** True while an upload is in flight (drops are ignored). */
|
|
35
|
+
busy: boolean;
|
|
36
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SessionScope } from './api.ts';
|
|
2
|
+
import type { SidebarTab } from './state.ts';
|
|
3
|
+
export declare function GitView(props: {
|
|
4
|
+
scope: SessionScope;
|
|
5
|
+
onOpenFile: (path: string) => void;
|
|
6
|
+
/** Open a diff tab (the shell places it below the git pane on first use). */
|
|
7
|
+
onOpenDiff: (tab: SidebarTab) => void;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placeholder shown when a persisted tab's type is not registered (the
|
|
3
|
+
* contributing plugin is not installed / not yet loaded). The tab is kept
|
|
4
|
+
* in state so it can recover if the plugin loads later; the user can close
|
|
5
|
+
* it through the tab bar's X button as usual. This is the graceful-
|
|
6
|
+
* degradation path for the open tab-type set: {@link Sidebar} renders this
|
|
7
|
+
* instead of crashing on an unknown type.
|
|
8
|
+
*/
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
|
+
import type { TabComponentProps } from './service.ts';
|
|
11
|
+
export declare function OrphanedTab(props: TabComponentProps): ReactNode;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generic render error boundary for the sidebar tree: a render error in
|
|
3
|
+
* the wrapped subtree shows a dismissible error strip (retry re-renders the
|
|
4
|
+
* children) instead of blanking the shell. Used at two scopes:
|
|
5
|
+
*
|
|
6
|
+
* - ROOT (index.tsx, `css.boundaryError`): last-resort containment for
|
|
7
|
+
* errors in the sidebar shell itself (Workbench, drag layout, …) — a full
|
|
8
|
+
* swap keeps the page alive.
|
|
9
|
+
* - PER-TAB (Sidebar.tsx TabContent, `css.tabBoundaryError`): a crashing
|
|
10
|
+
* viewer/editor shows a strip inside ITS OWN pane; the toggle cluster, the
|
|
11
|
+
* other tabs, and the panel itself stay alive (issue #31 — a tab crash
|
|
12
|
+
* must never take down the whole sidebar).
|
|
13
|
+
*
|
|
14
|
+
* The className prop selects the strip's geometry: the root's full-height
|
|
15
|
+
* fixed rail vs. the tab's pane-filling block.
|
|
16
|
+
*/
|
|
17
|
+
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
|
18
|
+
export declare class RenderBoundary extends Component<{
|
|
19
|
+
children?: ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
}, {
|
|
22
|
+
error: string | null;
|
|
23
|
+
}> {
|
|
24
|
+
state: {
|
|
25
|
+
error: string | null;
|
|
26
|
+
};
|
|
27
|
+
static getDerivedStateFromError(error: unknown): {
|
|
28
|
+
error: string;
|
|
29
|
+
};
|
|
30
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
31
|
+
render(): ReactNode;
|
|
32
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function SandboxStatusBar(props: {
|
|
2
|
+
/** The effective sandbox state (global pref OR the local temporary unlock). */
|
|
3
|
+
sandboxed: boolean;
|
|
4
|
+
/** Whether the sandbox is off due to the LOCAL temporary unlock (shows the restore action). */
|
|
5
|
+
local: boolean;
|
|
6
|
+
/** The red-state explanation (e.g. "the page runs with full GUI privileges"). */
|
|
7
|
+
dangerCopy: string;
|
|
8
|
+
onUnlock: () => void;
|
|
9
|
+
onRestore: () => void;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import { type SidebarPrefs } from '../prefs-shared.ts';
|
|
3
|
+
import type { SidebarStore } from './state.ts';
|
|
4
|
+
import type { BetterSidebarService, FileViewerDescriptor, SidebarSettingToggle, TabDescriptor } from './service.ts';
|
|
5
|
+
/** Injected business face: the shared store (prefs cache) + the sidebar service (registries). */
|
|
6
|
+
export interface SideCardSectionInjected {
|
|
7
|
+
store: SidebarStore;
|
|
8
|
+
service: BetterSidebarService;
|
|
9
|
+
}
|
|
10
|
+
/** Full section props: the runtime share plus the injected face. */
|
|
11
|
+
export type SideCardSectionProps = PropsRuntime<'settings.section'> & SideCardSectionInjected;
|
|
12
|
+
/**
|
|
13
|
+
* Merge one plugin-owned setting into a pluginSettings map (pure, v0.12.0+).
|
|
14
|
+
* Sequential merges are additive: each call spreads the map it was GIVEN,
|
|
15
|
+
* so building from the latest optimistic map keeps earlier keys intact
|
|
16
|
+
* (two same-tick writes must not drop each other).
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergePluginSetting(pluginSettings: Record<string, Record<string, unknown>>, descriptorId: string, key: string, value: unknown): Record<string, Record<string, unknown>>;
|
|
19
|
+
/**
|
|
20
|
+
* The body of a feature's secondary settings popup: one row (title/desc +
|
|
21
|
+
* control) per declared setting. Switches render the custom switch; text and
|
|
22
|
+
* number rows render a free-form / numeric input committed on blur/Enter
|
|
23
|
+
* (clamped to the declared min/max). Extracted so the rows are testable
|
|
24
|
+
* without opening the Modal (the Modal portal renders only while open).
|
|
25
|
+
*/
|
|
26
|
+
export declare function FeatureSettingsRows(props: {
|
|
27
|
+
toggles: readonly SidebarSettingToggle[];
|
|
28
|
+
prefs: SidebarPrefs;
|
|
29
|
+
onToggle: (toggle: SidebarSettingToggle, next: boolean) => void;
|
|
30
|
+
/** Commit one text/number row; returns the canonical value the row should
|
|
31
|
+
* display (clamped for numbers, the current pref when the input is
|
|
32
|
+
* invalid). Optional: rows with no handler keep their draft. */
|
|
33
|
+
onCommit?: (toggle: SidebarSettingToggle, raw: string) => string;
|
|
34
|
+
/** Commit one select row: the picked option's value (single) or the array
|
|
35
|
+
* of picked values (`multi: true`). Optional: rows with no handler are
|
|
36
|
+
* display-only. */
|
|
37
|
+
onSelectValue?: (toggle: SidebarSettingToggle, next: unknown) => void;
|
|
38
|
+
/** Explicit value source (v0.12.0+): when given, rows read their values
|
|
39
|
+
* from it instead of the `prefs` face — plugin-owned rows read their
|
|
40
|
+
* own blob, so a plugin key can never collide with (or silently read)
|
|
41
|
+
* a host pref of the same name. (Named `valueSource`, not `valueOf`:
|
|
42
|
+
* the latter collides with the inherited Object.prototype.valueOf.) */
|
|
43
|
+
valueSource?: (key: string) => unknown;
|
|
44
|
+
}): import("react").JSX.Element;
|
|
45
|
+
/**
|
|
46
|
+
* The secondary settings popup body of one feature (tab or viewer):
|
|
47
|
+
* - the host-prefs `toggles` rows, then the plugin-owned `pluginToggles`
|
|
48
|
+
* rows (their values live in `pluginSettings[feature.id]`, projected onto
|
|
49
|
+
* the prefs face so the shared row renderer reads them);
|
|
50
|
+
* - `settings.render` (custom panel) AFTER those rows when declared — the
|
|
51
|
+
* custom panel is an extension of the row list, not a replacement, so a
|
|
52
|
+
* feature can keep its declarative rows (e.g. the editor's
|
|
53
|
+
* open-behavior picker) and still ship a custom configuration area.
|
|
54
|
+
*/
|
|
55
|
+
export declare function SettingsBody(props: {
|
|
56
|
+
feature: TabDescriptor | FileViewerDescriptor;
|
|
57
|
+
prefs: SidebarPrefs;
|
|
58
|
+
store: SidebarStore;
|
|
59
|
+
service: BetterSidebarService;
|
|
60
|
+
onToggle: (toggle: SidebarSettingToggle, next: boolean) => void;
|
|
61
|
+
onCommit: (toggle: SidebarSettingToggle, raw: string) => string;
|
|
62
|
+
onSelectValue: (toggle: SidebarSettingToggle, next: unknown) => void;
|
|
63
|
+
onPluginToggle: (toggle: SidebarSettingToggle, next: boolean) => void;
|
|
64
|
+
onPluginCommit: (toggle: SidebarSettingToggle, raw: string) => string;
|
|
65
|
+
onPluginSelectValue: (toggle: SidebarSettingToggle, next: unknown) => void;
|
|
66
|
+
onPluginWrite: (key: string, value: unknown) => void;
|
|
67
|
+
onClose: () => void;
|
|
68
|
+
}): import("react").JSX.Element | null;
|
|
69
|
+
/**
|
|
70
|
+
* Render the Side card preferences section.
|
|
71
|
+
* @param props - composed slot props (runtime share + injected store/service).
|
|
72
|
+
* @returns the section element tree.
|
|
73
|
+
*/
|
|
74
|
+
export declare function SideCardSection({ store, service }: SideCardSectionProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context } from '../context-types.ts';
|
|
2
|
+
import type { SessionScope } from './api.ts';
|
|
3
|
+
import type { SidebarTab } from './state.ts';
|
|
4
|
+
/** The thread a tab is bound to (durable in tab.meta across refreshes). */
|
|
5
|
+
export declare function sidechatThreadIdOf(tab: SidebarTab): string | undefined;
|
|
6
|
+
/** Park a thread id for the NEXT sidechat openTab to reattach. */
|
|
7
|
+
export declare function parkSidechatReopen(threadId: string): void;
|
|
8
|
+
/** Consume the parked reopen target (undefined = mint a fresh thread tab). */
|
|
9
|
+
export declare function consumeSidechatSeed(): string | undefined;
|
|
10
|
+
/** One side conversation tab (one thread per tab, Codex-style). */
|
|
11
|
+
export declare function SideChatView(props: {
|
|
12
|
+
ctx: Context;
|
|
13
|
+
scope: SessionScope;
|
|
14
|
+
tab: SidebarTab;
|
|
15
|
+
visible: boolean;
|
|
16
|
+
}): React.ReactNode;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context, SidebarSubagentAddress } from '../context-types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The sidebar's Subagent topology page.
|
|
4
|
+
* @param props - current session id, whether the page is actually visible
|
|
5
|
+
* (active tab + open panel), the client context, and an optional
|
|
6
|
+
* jump-notify hook fired right before `openSubagent` (lets the sidebar
|
|
7
|
+
* shell re-open the Subagent page after the conversation switch lands on
|
|
8
|
+
* the child session).
|
|
9
|
+
* @returns the main agent's topology tree, or the empty/error/loading states.
|
|
10
|
+
*/
|
|
11
|
+
export declare function SubagentView(props: {
|
|
12
|
+
sessionId: string;
|
|
13
|
+
active: boolean;
|
|
14
|
+
ctx: Context;
|
|
15
|
+
onOpenChild?: (address: SidebarSubagentAddress) => void;
|
|
16
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tab strip of one pane: tabs capped at TAB_MAX_WIDTH (ellipsized),
|
|
3
|
+
* overflow scrolls horizontally, a close button per tab, a four-way split
|
|
4
|
+
* button cluster, and the + menu that opens new tabs (explorer / git /
|
|
5
|
+
* terminal). Tabs are draggable; dropping onto another tab inserts before it,
|
|
6
|
+
* dropping on the strip background appends to this pane. Right-clicking a
|
|
7
|
+
* tab opens the tab context menu (close / close others / close to the left /
|
|
8
|
+
* close to the right, all scoped to this pane).
|
|
9
|
+
*/
|
|
10
|
+
import { type ReactNode } from 'react';
|
|
11
|
+
import type { SidebarTab } from './state.ts';
|
|
12
|
+
/** One + menu option. */
|
|
13
|
+
export interface NewTabOption {
|
|
14
|
+
id: string;
|
|
15
|
+
label: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** Leading icon (Menu row). */
|
|
18
|
+
icon?: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
/** Drag payload for tab moves (HTML5 DnD dataTransfer). */
|
|
21
|
+
export declare const TAB_DRAG_TYPE = "application/x-dsh-tab";
|
|
22
|
+
export interface TabDragPayload {
|
|
23
|
+
tabId: string;
|
|
24
|
+
paneId: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function serializeDrag(payload: TabDragPayload): string;
|
|
27
|
+
export declare function parseDrag(raw: string): TabDragPayload | null;
|
|
28
|
+
export declare function TabBar(props: {
|
|
29
|
+
paneId: string;
|
|
30
|
+
tabs: SidebarTab[];
|
|
31
|
+
active: string | null;
|
|
32
|
+
onActivate: (tabId: string) => void;
|
|
33
|
+
onClose: (tabId: string) => void;
|
|
34
|
+
onNewTab: (optionId: string) => void;
|
|
35
|
+
newTabOptions: NewTabOption[];
|
|
36
|
+
/** Drop of a tab from any pane: (payload, insertBeforeTabId | null). */
|
|
37
|
+
onDropTab: (payload: TabDragPayload, before: string | null) => void;
|
|
38
|
+
/** Icon resolver for tab labels (reads from the tab descriptor registry). */
|
|
39
|
+
getTabIcon?: (tab: SidebarTab) => ReactNode;
|
|
40
|
+
/** Badge resolver for tab labels (reads the descriptor's `badge`; the
|
|
41
|
+
* resolver returns the rendered pill or null). */
|
|
42
|
+
getTabBadge?: (tab: SidebarTab) => ReactNode;
|
|
43
|
+
}): import("react").JSX.Element;
|