dsh-coding-sidebar 1.0.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 +524 -0
- package/cordis.patch.yml +49 -0
- package/lib/client-editor.js +48229 -0
- package/lib/client-mermaid.js +200745 -0
- package/lib/client-registry.js +21867 -0
- package/lib/client-terminal.js +9361 -0
- package/lib/client.js +21867 -0
- package/lib/index.js +4556 -0
- package/lib/invariant.js +22 -0
- package/lib/types/agent-opens.d.ts +65 -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 +39 -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 +13 -0
- package/lib/types/client/FileTree.d.ts +38 -0
- package/lib/types/client/FreeWindow.d.ts +29 -0
- package/lib/types/client/GitView.d.ts +10 -0
- package/lib/types/client/MarkdownHtml.d.ts +32 -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 +54 -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 +24 -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 +275 -0
- package/lib/types/client/binary-download.d.ts +12 -0
- package/lib/types/client/breakpoints.d.ts +17 -0
- package/lib/types/client/browser.d.ts +60 -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 +131 -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/editor-load.d.ts +66 -0
- package/lib/types/client/frame-batcher.d.ts +24 -0
- package/lib/types/client/icons.d.ts +59 -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 +25 -0
- package/lib/types/client/intercept.d.ts +46 -0
- package/lib/types/client/lang.d.ts +14 -0
- package/lib/types/client/layout-push.d.ts +15 -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-ar.d.ts +18 -0
- package/lib/types/client/locales-de.d.ts +4 -0
- package/lib/types/client/locales-fr.d.ts +10 -0
- package/lib/types/client/locales-hi.d.ts +17 -0
- package/lib/types/client/locales-id.d.ts +15 -0
- package/lib/types/client/locales-it.d.ts +8 -0
- package/lib/types/client/locales-ja.d.ts +17 -0
- package/lib/types/client/locales-ko.d.ts +9 -0
- package/lib/types/client/locales-nl.d.ts +16 -0
- package/lib/types/client/locales-pl.d.ts +19 -0
- package/lib/types/client/locales-pt.d.ts +1 -0
- package/lib/types/client/locales-ru.d.ts +13 -0
- package/lib/types/client/locales-sv.d.ts +1 -0
- package/lib/types/client/locales-th.d.ts +17 -0
- package/lib/types/client/locales-tr.d.ts +17 -0
- package/lib/types/client/locales-vi.d.ts +17 -0
- package/lib/types/client/locales-zh-HK.d.ts +32 -0
- package/lib/types/client/locales-zh-MO.d.ts +32 -0
- package/lib/types/client/locales-zh-TW.d.ts +32 -0
- package/lib/types/client/locales.d.ts +452 -0
- package/lib/types/client/markdown-html.d.ts +96 -0
- package/lib/types/client/markdown-images.d.ts +45 -0
- package/lib/types/client/markdown-labels.d.ts +38 -0
- package/lib/types/client/md-toc.d.ts +4 -0
- package/lib/types/client/mermaid-blocks.d.ts +47 -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 +85 -0
- package/lib/types/client/paths.d.ts +43 -0
- package/lib/types/client/pdf-types.d.ts +2 -0
- package/lib/types/client/pinned.d.ts +86 -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 +29 -0
- package/lib/types/client/selection-payload.d.ts +27 -0
- package/lib/types/client/service.d.ts +439 -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 +36 -0
- package/lib/types/client/state.d.ts +432 -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 +40 -0
- package/lib/types/client/terminal-font.d.ts +78 -0
- package/lib/types/client/terminal-links.d.ts +119 -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 +605 -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 +124 -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/path-security.d.ts +20 -0
- package/lib/types/prefs-shared.d.ts +236 -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 +34 -0
- package/lib/types/trust-fence.d.ts +24 -0
- package/lib/types/wire.d.ts +38 -0
- package/package.json +172 -0
- package/scripts/install.ps1 +306 -0
- package/scripts/install.sh +287 -0
- package/src/agent-opens.ts +265 -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 +289 -0
- package/src/client/DiffTab.tsx +114 -0
- package/src/client/DiffView.tsx +305 -0
- package/src/client/EditorHost.tsx +558 -0
- package/src/client/FileTree.tsx +669 -0
- package/src/client/FreeWindow.tsx +337 -0
- package/src/client/GitView.tsx +717 -0
- package/src/client/MarkdownHtml.tsx +296 -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 +1163 -0
- package/src/client/SideChatView.module.css +437 -0
- package/src/client/SideChatView.tsx +645 -0
- package/src/client/Sidebar.tsx +1370 -0
- package/src/client/SubagentView.module.css +547 -0
- package/src/client/SubagentView.tsx +883 -0
- package/src/client/TabBar.tsx +365 -0
- package/src/client/TerminalView.tsx +424 -0
- package/src/client/TextEditor.tsx +468 -0
- package/src/client/TreePanel.tsx +275 -0
- package/src/client/UploadOverlay.tsx +62 -0
- package/src/client/add-plugin-modal.tsx +199 -0
- package/src/client/api.ts +357 -0
- package/src/client/binary-download.tsx +23 -0
- package/src/client/breakpoints.ts +61 -0
- package/src/client/browser.ts +167 -0
- package/src/client/builtins/index.ts +37 -0
- package/src/client/builtins/tabs.tsx +340 -0
- package/src/client/builtins/viewers.tsx +125 -0
- package/src/client/chunk-loader.ts +358 -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/editor-load.ts +92 -0
- package/src/client/frame-batcher.ts +56 -0
- package/src/client/icons.tsx +152 -0
- package/src/client/image-types.ts +8 -0
- package/src/client/ime-guard.ts +47 -0
- package/src/client/index.tsx +427 -0
- package/src/client/intercept.tsx +188 -0
- package/src/client/lang.ts +225 -0
- package/src/client/layout-push.ts +24 -0
- package/src/client/layout.css +90 -0
- package/src/client/lazy-chunk.tsx +89 -0
- package/src/client/link-intercept.ts +73 -0
- package/src/client/locales-ar.ts +368 -0
- package/src/client/locales-de.ts +353 -0
- package/src/client/locales-fr.ts +360 -0
- package/src/client/locales-hi.ts +367 -0
- package/src/client/locales-id.ts +365 -0
- package/src/client/locales-it.ts +358 -0
- package/src/client/locales-ja.ts +367 -0
- package/src/client/locales-ko.ts +359 -0
- package/src/client/locales-nl.ts +365 -0
- package/src/client/locales-pl.ts +369 -0
- package/src/client/locales-pt.ts +350 -0
- package/src/client/locales-ru.ts +365 -0
- package/src/client/locales-sv.ts +350 -0
- package/src/client/locales-th.ts +367 -0
- package/src/client/locales-tr.ts +367 -0
- package/src/client/locales-vi.ts +367 -0
- package/src/client/locales-zh-HK.ts +382 -0
- package/src/client/locales-zh-MO.ts +382 -0
- package/src/client/locales-zh-TW.ts +382 -0
- package/src/client/locales.ts +894 -0
- package/src/client/markdown-html.ts +331 -0
- package/src/client/markdown-images.ts +137 -0
- package/src/client/markdown-labels.tsx +52 -0
- package/src/client/md-toc.tsx +127 -0
- package/src/client/mermaid-blocks.ts +110 -0
- package/src/client/mermaid-sanitize.ts +93 -0
- package/src/client/mermaid.tsx +406 -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 +143 -0
- package/src/client/paths.ts +63 -0
- package/src/client/pdf-types.ts +4 -0
- package/src/client/pinned.ts +183 -0
- package/src/client/plugin-settings.ts +43 -0
- package/src/client/plugins-shared.ts +29 -0
- package/src/client/plugins-tabs.ts +96 -0
- package/src/client/plugins-viewers.ts +30 -0
- package/src/client/prefs.ts +210 -0
- package/src/client/produced-files.ts +120 -0
- package/src/client/selection-payload.ts +86 -0
- package/src/client/service.ts +859 -0
- package/src/client/settings-nav-icon.ts +45 -0
- package/src/client/shell-presets.ts +83 -0
- package/src/client/sidebar.module.css +2788 -0
- package/src/client/sidechat-transcript.ts +321 -0
- package/src/client/split-pane.tsx +331 -0
- package/src/client/state.ts +1497 -0
- package/src/client/subagent-detect.ts +137 -0
- package/src/client/subagent-jobs.ts +161 -0
- package/src/client/tab-content-memo.ts +55 -0
- package/src/client/terminal-font.ts +224 -0
- package/src/client/terminal-links.ts +194 -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 +154 -0
- package/src/context-types.ts +611 -0
- package/src/fs-operations.ts +95 -0
- package/src/fs-search.ts +113 -0
- package/src/fs-tree.ts +158 -0
- package/src/git.ts +446 -0
- package/src/html-route.ts +106 -0
- package/src/index.ts +1291 -0
- package/src/invariant.ts +32 -0
- package/src/jobs-routes.ts +257 -0
- package/src/open-external.ts +90 -0
- package/src/path-security.ts +75 -0
- package/src/prefs-shared.ts +280 -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 +482 -0
- package/src/trust-fence.ts +84 -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-coding-sidebar";
|
|
3
|
+
/** Cordis companion plugin name. */
|
|
4
|
+
const name = "dsh-coding-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,65 @@
|
|
|
1
|
+
import type { Context } from './context-types.ts';
|
|
2
|
+
import type { SidebarPrefs } from './prefs-shared.ts';
|
|
3
|
+
/** What the model asked to open. */
|
|
4
|
+
export type AgentOpenKind = 'file' | 'folder' | 'url';
|
|
5
|
+
/** One pending/broadcast open request (the wire face over the push socket). */
|
|
6
|
+
export interface AgentOpenRequest {
|
|
7
|
+
/** Opaque id (host-generated; the client ignores it beyond dedupe/debug). */
|
|
8
|
+
id: string;
|
|
9
|
+
/** The session whose sidebar the open is targeted at. */
|
|
10
|
+
sessionId: string;
|
|
11
|
+
kind: AgentOpenKind;
|
|
12
|
+
/** Absolute local path (file/folder) or http(s) URL. */
|
|
13
|
+
target: string;
|
|
14
|
+
/** Tab title the client should use (basename / hostname / caller-supplied). */
|
|
15
|
+
title: string;
|
|
16
|
+
}
|
|
17
|
+
/** One subscribed sidebar view's sender. */
|
|
18
|
+
type Sender = (request: AgentOpenRequest) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Per-session queue of open requests plus the connected sidebar views.
|
|
21
|
+
*
|
|
22
|
+
* Lifecycle: `enqueue` adds a request and — when at least one view for the
|
|
23
|
+
* session is attached — pushes it immediately and removes it from the queue
|
|
24
|
+
* (consume-on-send: a reconnect must never replay an open the client already
|
|
25
|
+
* applied, and the browser tab type has no per-URL dedupe, so replaying
|
|
26
|
+
* would mint duplicate tabs). With no attached view the request stays queued
|
|
27
|
+
* and `attach` replays it on connect. `drainAll` drops every queued request
|
|
28
|
+
* (the feature was turned off); `dispose` also drops every subscriber.
|
|
29
|
+
*/
|
|
30
|
+
export declare class AgentOpenRegistry {
|
|
31
|
+
private pending;
|
|
32
|
+
private subscribers;
|
|
33
|
+
/** Queue one open and deliver it immediately when a view is attached.
|
|
34
|
+
* @returns the request id and whether a connected view received it now. */
|
|
35
|
+
enqueue(sessionId: string, kind: AgentOpenKind, target: string, title: string): {
|
|
36
|
+
id: string;
|
|
37
|
+
delivered: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** Attach one sidebar view (replays queued requests; consume-on-send).
|
|
40
|
+
* @returns the disposer detaching the view. */
|
|
41
|
+
attach(sessionId: string, send: Sender): () => void;
|
|
42
|
+
/** Drop every queued request (the feature was turned off mid-session). */
|
|
43
|
+
drainAll(): void;
|
|
44
|
+
/** Drop the queue and every subscriber (plugin teardown). */
|
|
45
|
+
dispose(): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Register the `sidebar_open` tool against the host tool registry. The tool
|
|
49
|
+
* is gated by the side-card setting `agentOpenTools` (the caller registers
|
|
50
|
+
* and unregisters it); `readPrefs` supplies the live prefs so a disabled
|
|
51
|
+
* target tab type (editor/browser) is reported to the model instead of
|
|
52
|
+
* silently no-oping on the client. `resolveCwd` threads the calling
|
|
53
|
+
* session's live cwd so relative paths resolve the same way the sidebar's
|
|
54
|
+
* own routes do.
|
|
55
|
+
* @param ctx - host plugin context (carries the tools service).
|
|
56
|
+
* @param registry - the open-request registry (per-session queue + views).
|
|
57
|
+
* @param resolveCwd - async cwd resolver for one session id. Resolves through
|
|
58
|
+
* the session header, the client-supplied cwd, and the persistence index
|
|
59
|
+
* before falling back to the host process cwd (production always provides
|
|
60
|
+
* persistence, so the fallback is reached only in tests / stripped-down hosts).
|
|
61
|
+
* @param readPrefs - live resolved side card prefs (for tab enable gates).
|
|
62
|
+
* @returns a disposer that unregisters the tool.
|
|
63
|
+
*/
|
|
64
|
+
export declare function registerOpenTool(ctx: Context, registry: AgentOpenRegistry, resolveCwd: (sessionId: string) => Promise<string>, readPrefs: () => SidebarPrefs): () => void;
|
|
65
|
+
export {};
|
|
@@ -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,39 @@
|
|
|
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
|
+
/**
|
|
11
|
+
* The sandbox tokens for one URL: allowlisted loopback addresses (local dev
|
|
12
|
+
* servers the user explicitly trusts) additionally get `allow-same-origin`
|
|
13
|
+
* so Vite/module/HMR pipelines that need a real origin work; every other
|
|
14
|
+
* site keeps the opaque-origin sandbox. `allow-same-origin` does NOT give
|
|
15
|
+
* the page access to the GUI — it stays cross-origin to it and to every
|
|
16
|
+
* other site — but it does give it its OWN origin privileges (localStorage,
|
|
17
|
+
* fetch without CORS), so it is only granted for the explicit allowlist.
|
|
18
|
+
*
|
|
19
|
+
* The GUI itself is the one hard exception: even when its own host is
|
|
20
|
+
* allowlisted (a bare-host entry covers every port, so the GUI origin
|
|
21
|
+
* matches), a page at the GUI's exact origin must never get
|
|
22
|
+
* `allow-same-origin` — that would make it same-origin with its parent and
|
|
23
|
+
* hand it the GUI's storage/API (and the ability to shed the sandbox). The
|
|
24
|
+
* GUI keeps the opaque-origin sandbox no matter what the allowlist says.
|
|
25
|
+
*/
|
|
26
|
+
export declare function iframeSandboxFor(url: string | undefined, allowedLoopback: string, selfOrigin?: string): string | undefined;
|
|
27
|
+
export declare function BrowserView(props: TabComponentProps): import("react").JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* The embed-refusal panel: shown when the probed site forbids being
|
|
30
|
+
* displayed inside other pages (X-Frame-Options / frame-ancestors) — the
|
|
31
|
+
* iframe would only show the browser's "refused to connect" blank. Explains
|
|
32
|
+
* the reason and offers the real-browser open plus a load-anyway escape.
|
|
33
|
+
* Exported so the copy and the actions are testable without a DOM.
|
|
34
|
+
*/
|
|
35
|
+
export declare function BrowserEmbedBlocked(props: {
|
|
36
|
+
url: string;
|
|
37
|
+
onOpenInBrowser: () => void;
|
|
38
|
+
onLoadAnyway: () => void;
|
|
39
|
+
}): 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,13 @@
|
|
|
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
|
+
revealed: string[];
|
|
11
|
+
onToggleDir: (path: string) => void;
|
|
12
|
+
onReferenceFile: (path: string) => void;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
/** Files highlighted by a "Show in folder" reveal (absolute paths). */
|
|
10
|
+
revealed: string[];
|
|
11
|
+
onToggle: (path: string) => void;
|
|
12
|
+
onOpenFile: (path: string) => void;
|
|
13
|
+
/** Context-menu "open in a new tab" (file rows; absent → no entry). */
|
|
14
|
+
onOpenFileNewTab?: (path: string) => void;
|
|
15
|
+
/** Context-menu "open to the side" (file rows; absent → no entry). */
|
|
16
|
+
onOpenFileSide?: (path: string) => void;
|
|
17
|
+
/**
|
|
18
|
+
* The "open with" menu: resolved external targets (already SSH-filtered
|
|
19
|
+
* and in menu order). Absent → the whole section is hidden.
|
|
20
|
+
*/
|
|
21
|
+
openWithTargets?: OpenWithTarget[];
|
|
22
|
+
/** Ids of targets pinned to the menu's top level (subset of the ids). */
|
|
23
|
+
openWithPinned?: string[];
|
|
24
|
+
/** Whether the workspace is remote (appends the SSH hint to target labels). */
|
|
25
|
+
openWithSsh?: boolean;
|
|
26
|
+
/** Open one target externally (reveal or URL — the caller decides). */
|
|
27
|
+
onOpenWith?: (targetId: string, path: string) => void;
|
|
28
|
+
/** Toggle one target's pinned state (the submenu row's pushpin). */
|
|
29
|
+
onToggleOpenWithPin?: (targetId: string) => void;
|
|
30
|
+
/** Insert `@<relative path>` into the composer draft. */
|
|
31
|
+
onReferenceFile: (path: string) => void;
|
|
32
|
+
/** Bump to wipe the level cache and reload the visible set. */
|
|
33
|
+
refreshTick: number;
|
|
34
|
+
/** Upload into `dir` (absolute, inside the workspace); runs in the caller. */
|
|
35
|
+
onUploadRequest: (dir: string, items: UploadItem[]) => void;
|
|
36
|
+
/** True while an upload is in flight (drops are ignored). */
|
|
37
|
+
busy: boolean;
|
|
38
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One free window: a tab dragged out of the workbench floating over the
|
|
3
|
+
* conversation area at viewport coordinates (rendered inside the panel host,
|
|
4
|
+
* so desktop-shell transforms can never hijack its fixed containing block).
|
|
5
|
+
*
|
|
6
|
+
* The header drags the window with the panel-resize pattern — pointer
|
|
7
|
+
* capture + per-frame direct DOM writes + a store commit on release — and
|
|
8
|
+
* doubling as the DOCK-BACK gesture: while the pointer is over a workbench
|
|
9
|
+
* pane ([data-dsh-pane], either panel), that pane highlights live and
|
|
10
|
+
* releasing docks the tab into it (center merge); releasing anywhere else
|
|
11
|
+
* just moves the window. The SE corner resizes, any press raises (the
|
|
12
|
+
* floats array's order is the stacking order), the header right-click menu
|
|
13
|
+
* and the X button dock / close. The tab content reuses the regular tab
|
|
14
|
+
* renderer, so every tab type (terminal, editor, plugin tabs) floats
|
|
15
|
+
* unchanged.
|
|
16
|
+
*/
|
|
17
|
+
import { type ReactNode } from 'react';
|
|
18
|
+
import type { FloatWindow, SidebarTab } from './state.ts';
|
|
19
|
+
export declare function FreeWindow(props: {
|
|
20
|
+
float: FloatWindow;
|
|
21
|
+
renderTab: (tab: SidebarTab, active: boolean, paneId: string) => ReactNode;
|
|
22
|
+
getTabIcon?: (tab: SidebarTab) => ReactNode;
|
|
23
|
+
onRaise: () => void;
|
|
24
|
+
onMove: (x: number, y: number) => void;
|
|
25
|
+
onResize: (w: number, h: number) => void;
|
|
26
|
+
/** Dock the tab back; the pane id, or null for the active pane. */
|
|
27
|
+
onDock: (paneId: string | null) => void;
|
|
28
|
+
onClose: () => void;
|
|
29
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
/** Poll only while the tab is actually visible. */
|
|
9
|
+
visible: boolean;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AnalyzedMarkdownHtml } from './markdown-html.ts';
|
|
3
|
+
import { type MermaidMarkdownProps } from './mermaid-blocks.ts';
|
|
4
|
+
import type { SessionScope } from './api.ts';
|
|
5
|
+
/** The chunk-resident markdown renderer (mermaid lazy chunk), shared with the
|
|
6
|
+
* legacy no-HTML preview path in TextEditor. */
|
|
7
|
+
export declare const LazyMermaidMarkdown: (props: MermaidMarkdownProps) => ReactNode;
|
|
8
|
+
/** Everything the sanitizers need to resolve local media + scope the route. */
|
|
9
|
+
export interface MarkdownHtmlMedia {
|
|
10
|
+
scope: SessionScope;
|
|
11
|
+
path: string;
|
|
12
|
+
origin: string;
|
|
13
|
+
}
|
|
14
|
+
interface MarkdownDocumentProps {
|
|
15
|
+
info: AnalyzedMarkdownHtml;
|
|
16
|
+
media: MarkdownHtmlMedia;
|
|
17
|
+
codeLabels: {
|
|
18
|
+
copyLabel: string;
|
|
19
|
+
copiedLabel: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The split-document renderer: markdown runs render through MarkdownSegment,
|
|
24
|
+
* HTML runs render as sanitized leaves, and unclosed block elements lower the
|
|
25
|
+
* following runs into themselves until their close part pops the frame (the
|
|
26
|
+
* renderer's frame stack persists across segments). Stray closes at the top
|
|
27
|
+
* level render nothing (the sanitizer/parser would drop them anyway), and
|
|
28
|
+
* frames still open at the end of the document are closed like a browser
|
|
29
|
+
* parser would. Sanitization runs once per prepared change, in a memo.
|
|
30
|
+
*/
|
|
31
|
+
export declare function MarkdownDocument({ info, media, codeLabels }: MarkdownDocumentProps): ReactNode;
|
|
32
|
+
export {};
|
|
@@ -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;
|