@hachej/boring-workspace 0.1.23 → 0.1.26

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.
@@ -1,4 +1,5 @@
1
1
  type JSONSchema = Record<string, unknown>;
2
+ type ToolReadinessRequirement = 'workspace-fs' | 'sandbox-exec' | 'ui-bridge';
2
3
  interface ToolExecContext {
3
4
  abortSignal: AbortSignal;
4
5
  toolCallId: string;
@@ -23,6 +24,7 @@ interface AgentTool {
23
24
  name: string;
24
25
  description: string;
25
26
  promptSnippet?: string;
27
+ readinessRequirements?: ToolReadinessRequirement[];
26
28
  parameters: JSONSchema;
27
29
  execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
28
30
  }
@@ -1267,6 +1267,7 @@
1267
1267
  --leading-relaxed: 1.625;
1268
1268
  --radius-xs: 0.125rem;
1269
1269
  --radius-sm: var(--boring-radius-sm);
1270
+ --radius-2xl: 1rem;
1270
1271
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
1271
1272
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
1272
1273
  --animate-spin: spin 1s linear infinite;
@@ -1489,6 +1490,9 @@
1489
1490
  .top-2 {
1490
1491
  top: calc(var(--spacing) * 2);
1491
1492
  }
1493
+ .top-3 {
1494
+ top: calc(var(--spacing) * 3);
1495
+ }
1492
1496
  .-right-1\.5 {
1493
1497
  right: calc(var(--spacing) * -1.5);
1494
1498
  }
@@ -1501,6 +1505,9 @@
1501
1505
  .right-2 {
1502
1506
  right: calc(var(--spacing) * 2);
1503
1507
  }
1508
+ .right-3 {
1509
+ right: calc(var(--spacing) * 3);
1510
+ }
1504
1511
  .bottom-0 {
1505
1512
  bottom: calc(var(--spacing) * 0);
1506
1513
  }
@@ -1528,6 +1535,9 @@
1528
1535
  .z-50 {
1529
1536
  z-index: 50;
1530
1537
  }
1538
+ .z-\[1000\] {
1539
+ z-index: 1000;
1540
+ }
1531
1541
  .z-\[99999\] {
1532
1542
  z-index: 99999;
1533
1543
  }
@@ -1576,6 +1586,9 @@
1576
1586
  .mt-2 {
1577
1587
  margin-top: calc(var(--spacing) * 2);
1578
1588
  }
1589
+ .mt-3 {
1590
+ margin-top: calc(var(--spacing) * 3);
1591
+ }
1579
1592
  .mt-4 {
1580
1593
  margin-top: calc(var(--spacing) * 4);
1581
1594
  }
@@ -1591,6 +1604,9 @@
1591
1604
  .mb-1\.5 {
1592
1605
  margin-bottom: calc(var(--spacing) * 1.5);
1593
1606
  }
1607
+ .mb-3 {
1608
+ margin-bottom: calc(var(--spacing) * 3);
1609
+ }
1594
1610
  .ml-0\.5 {
1595
1611
  margin-left: calc(var(--spacing) * 0.5);
1596
1612
  }
@@ -1734,6 +1750,9 @@
1734
1750
  .w-5 {
1735
1751
  width: calc(var(--spacing) * 5);
1736
1752
  }
1753
+ .w-7 {
1754
+ width: calc(var(--spacing) * 7);
1755
+ }
1737
1756
  .w-9 {
1738
1757
  width: calc(var(--spacing) * 9);
1739
1758
  }
@@ -1764,6 +1783,9 @@
1764
1783
  .max-w-full {
1765
1784
  max-width: 100%;
1766
1785
  }
1786
+ .max-w-lg {
1787
+ max-width: var(--container-lg);
1788
+ }
1767
1789
  .max-w-md {
1768
1790
  max-width: var(--container-md);
1769
1791
  }
@@ -1934,6 +1956,9 @@
1934
1956
  .rounded {
1935
1957
  border-radius: 0.25rem;
1936
1958
  }
1959
+ .rounded-2xl {
1960
+ border-radius: var(--radius-2xl);
1961
+ }
1937
1962
  .rounded-full {
1938
1963
  border-radius: calc(infinity * 1px);
1939
1964
  }
@@ -2021,6 +2046,15 @@
2021
2046
  .border-current {
2022
2047
  border-color: currentcolor;
2023
2048
  }
2049
+ .border-muted-foreground\/20 {
2050
+ border-color: var(--boring-muted-foreground);
2051
+ @supports (color: color-mix(in lab, red, red)) {
2052
+ border-color: color-mix(in oklab, var(--boring-muted-foreground) 20%, transparent);
2053
+ }
2054
+ }
2055
+ .border-t-foreground {
2056
+ border-top-color: var(--boring-foreground);
2057
+ }
2024
2058
  .border-t-transparent {
2025
2059
  border-top-color: transparent;
2026
2060
  }
@@ -2042,6 +2076,12 @@
2042
2076
  .bg-background {
2043
2077
  background-color: var(--boring-background);
2044
2078
  }
2079
+ .bg-background\/80 {
2080
+ background-color: var(--boring-background);
2081
+ @supports (color: color-mix(in lab, red, red)) {
2082
+ background-color: color-mix(in oklab, var(--boring-background) 80%, transparent);
2083
+ }
2084
+ }
2045
2085
  .bg-background\/95 {
2046
2086
  background-color: var(--boring-background);
2047
2087
  @supports (color: color-mix(in lab, red, red)) {
@@ -2132,6 +2172,9 @@
2132
2172
  .p-4 {
2133
2173
  padding: calc(var(--spacing) * 4);
2134
2174
  }
2175
+ .p-5 {
2176
+ padding: calc(var(--spacing) * 5);
2177
+ }
2135
2178
  .p-6 {
2136
2179
  padding: calc(var(--spacing) * 6);
2137
2180
  }
@@ -2231,6 +2274,9 @@
2231
2274
  .text-center {
2232
2275
  text-align: center;
2233
2276
  }
2277
+ .text-left {
2278
+ text-align: left;
2279
+ }
2234
2280
  .align-baseline {
2235
2281
  vertical-align: baseline;
2236
2282
  }
@@ -2517,6 +2563,11 @@
2517
2563
  .filter {
2518
2564
  filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
2519
2565
  }
2566
+ .backdrop-blur {
2567
+ --tw-backdrop-blur: blur(8px);
2568
+ -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
2569
+ backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
2570
+ }
2520
2571
  .backdrop-blur-md {
2521
2572
  --tw-backdrop-blur: blur(var(--blur-md));
2522
2573
  -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
@@ -2607,6 +2658,14 @@
2607
2658
  }
2608
2659
  }
2609
2660
  }
2661
+ .hover\:-translate-y-0\.5 {
2662
+ &:hover {
2663
+ @media (hover: hover) {
2664
+ --tw-translate-y: calc(var(--spacing) * -0.5);
2665
+ translate: var(--tw-translate-x) var(--tw-translate-y);
2666
+ }
2667
+ }
2668
+ }
2610
2669
  .hover\:-translate-y-\[calc\(50\%\+1px\)\] {
2611
2670
  &:hover {
2612
2671
  @media (hover: hover) {
@@ -2625,6 +2684,13 @@
2625
2684
  }
2626
2685
  }
2627
2686
  }
2687
+ .hover\:bg-accent {
2688
+ &:hover {
2689
+ @media (hover: hover) {
2690
+ background-color: var(--boring-accent);
2691
+ }
2692
+ }
2693
+ }
2628
2694
  .hover\:bg-accent\/50 {
2629
2695
  &:hover {
2630
2696
  @media (hover: hover) {
@@ -2709,6 +2775,13 @@
2709
2775
  }
2710
2776
  }
2711
2777
  }
2778
+ .hover\:text-accent-foreground {
2779
+ &:hover {
2780
+ @media (hover: hover) {
2781
+ color: var(--boring-accent-foreground);
2782
+ }
2783
+ }
2784
+ }
2712
2785
  .hover\:text-destructive {
2713
2786
  &:hover {
2714
2787
  @media (hover: hover) {
@@ -39,6 +39,7 @@ export declare interface AgentTool {
39
39
  name: string;
40
40
  description: string;
41
41
  promptSnippet?: string;
42
+ readinessRequirements?: ToolReadinessRequirement[];
42
43
  parameters: JSONSchema;
43
44
  execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
44
45
  }
@@ -155,6 +156,7 @@ declare interface BoringFrontPanelRegistration<T = unknown> {
155
156
  essential?: boolean;
156
157
  lazy?: boolean;
157
158
  chromeless?: boolean;
159
+ supportsFullPage?: boolean;
158
160
  source?: string;
159
161
  }
160
162
 
@@ -230,6 +232,14 @@ export declare interface BridgeEventMap {
230
232
 
231
233
  export declare function buildChatLayout(props?: ChatLayoutProps): LayoutConfig;
232
234
 
235
+ export declare function buildFullPagePanelHref({ componentId, params, basePath }: BuildFullPagePanelHrefInput): string;
236
+
237
+ export declare interface BuildFullPagePanelHrefInput {
238
+ componentId: string;
239
+ params?: Record<string, unknown>;
240
+ basePath: string;
241
+ }
242
+
233
243
  export declare function buildIdeLayout(props?: IdeLayoutProps): LayoutConfig;
234
244
 
235
245
  declare interface CapturedBoringFrontRegistrations {
@@ -358,11 +368,13 @@ export declare interface ChatLayoutProps {
358
368
  centerParams?: Record<string, unknown>;
359
369
  surface?: string | null;
360
370
  surfaceParams?: Record<string, unknown>;
371
+ surfaceOverlay?: ReactNode;
361
372
  sidebar?: string | null;
362
373
  sidebarParams?: Record<string, unknown>;
363
374
  storageKey?: string;
364
375
  onOpenNav?: () => void;
365
376
  onOpenSurface?: () => void;
377
+ surfaceButtonBottomOffset?: number;
366
378
  onOpenSidebar?: () => void;
367
379
  className?: string;
368
380
  }
@@ -487,6 +499,15 @@ export declare interface CreateWorkspaceStoreOptions {
487
499
  onLayoutVersionMismatch?: () => void;
488
500
  }
489
501
 
502
+ declare interface DataProviderProps {
503
+ apiBaseUrl: string;
504
+ authHeaders?: Record<string, string>;
505
+ onAuthError?: (statusCode: number) => void;
506
+ timeout?: number;
507
+ client?: FetchClient;
508
+ children: ReactNode;
509
+ }
510
+
490
511
  /**
491
512
  * Identity helper for type-safe panel registration. Pure runtime
492
513
  * passthrough — the value of this is forcing TypeScript to verify that
@@ -518,6 +539,8 @@ export declare interface DispatchContext {
518
539
  isWorkbenchOpen: () => boolean;
519
540
  /** Toggle the workbench pane open. Must be a no-op when already open. */
520
541
  openWorkbench: () => void;
542
+ /** Open the workbench sources/file-tree pane. Must be a no-op when already open. */
543
+ openWorkbenchSources?: () => void;
521
544
  /** Close the workbench pane when a command opened it only for an ephemeral task. */
522
545
  closeWorkbench?: () => void;
523
546
  }
@@ -622,6 +645,93 @@ export declare const expandToFileSchema: z.ZodObject<{
622
645
  path: string;
623
646
  }>;
624
647
 
648
+ declare class FetchClient {
649
+ private baseUrl;
650
+ private headers;
651
+ private onAuthError?;
652
+ private onTimeout?;
653
+ private timeout;
654
+ private maxRetries;
655
+ private retryBaseMs;
656
+ constructor(opts: FetchClientOptions);
657
+ private request;
658
+ getTree(path: string, signal?: AbortSignal): Promise<FileEntry[]>;
659
+ getFile(path: string, signal?: AbortSignal): Promise<FileContent>;
660
+ /**
661
+ * Write file content. When `expectedMtimeMs` is supplied, the server
662
+ * runs an optimistic-concurrency check and returns 409 if the file
663
+ * has been modified since that mtime — surfaced here as a typed
664
+ * `FileConflictError` so the editor can ask the user to reload or
665
+ * force-overwrite. The returned `mtimeMs` is the server's stat
666
+ * after the write; callers use it as the OCC baseline for the
667
+ * next save.
668
+ */
669
+ writeFile(path: string, content: string, opts?: {
670
+ expectedMtimeMs?: number;
671
+ }): Promise<{
672
+ mtimeMs?: number;
673
+ }>;
674
+ deleteFile(path: string): Promise<void>;
675
+ stat(path: string, signal?: AbortSignal): Promise<FileStat>;
676
+ search(query: string, limit?: number, signal?: AbortSignal): Promise<string[]>;
677
+ createDir(path: string): Promise<void>;
678
+ moveFile(from: string, to: string): Promise<void>;
679
+ }
680
+
681
+ declare interface FetchClientOptions {
682
+ apiBaseUrl: string;
683
+ authHeaders?: Record<string, string>;
684
+ onAuthError?: (statusCode: number) => void;
685
+ onTimeout?: (route: string) => void;
686
+ timeout?: number;
687
+ maxRetries?: number;
688
+ retryBaseMs?: number;
689
+ }
690
+
691
+ declare class FetchError extends Error {
692
+ readonly status: number;
693
+ readonly body?: unknown | undefined;
694
+ constructor(status: number, message: string, body?: unknown | undefined);
695
+ }
696
+
697
+ /**
698
+ * Thrown by `writeFile` when the server returns 409 because the file
699
+ * has been modified since the client's last read. Carries the
700
+ * server's current mtime so the editor can show the user a
701
+ * Reload-vs-Overwrite choice with the actual conflict context.
702
+ */
703
+ declare class FileConflictError extends Error {
704
+ readonly path: string;
705
+ readonly currentMtimeMs: number | null;
706
+ readonly expectedMtimeMs: number | null;
707
+ constructor(path: string, currentMtimeMs: number | null, expectedMtimeMs: number | null);
708
+ static from(err: FetchError, path: string): FileConflictError;
709
+ }
710
+
711
+ declare interface FileContent {
712
+ content: string;
713
+ /**
714
+ * Server-stat'd modification time. Used as the OCC baseline for the
715
+ * next write — the client sends it back as `expectedMtimeMs` so the
716
+ * server can return 409 if the file changed underneath. Optional
717
+ * because not every workspace impl can stat cheaply (sandbox
718
+ * impl is best-effort).
719
+ */
720
+ mtimeMs?: number;
721
+ }
722
+
723
+ declare interface FileEntry {
724
+ name: string;
725
+ kind: "file" | "dir";
726
+ path: string;
727
+ }
728
+
729
+ declare interface FileStat {
730
+ size: number;
731
+ mtimeMs: number;
732
+ kind: "file" | "dir";
733
+ }
734
+
625
735
  declare const FILESYSTEM_FILE_CHANGED_EVENT = "filesystem:file.changed";
626
736
 
627
737
  declare const FILESYSTEM_FILE_CREATED_EVENT = "filesystem:file.created";
@@ -668,7 +778,7 @@ export declare const filesystemEvents: {
668
778
 
669
779
  export declare const filesystemPlugin: BoringFrontFactoryWithId;
670
780
 
671
- export declare function FileTree({ files, selectedPath, searchQuery, height, editing, revealPath, pendingPaths, onSelect, onExpand, onCollapse, onContextMenu, onSubmitEdit, onCancelEdit, onDragDrop, className, }: FileTreeProps): JSX.Element;
781
+ export declare function FileTree({ files, selectedPath, searchQuery, height, editing, revealPath, pendingPaths, onSelect, onExpand, onCollapse, onContextMenu, onSubmitEdit, onCancelEdit, onRevealHandled, onDragDrop, className, }: FileTreeProps): JSX.Element;
672
782
 
673
783
  declare interface FileTreeEditState {
674
784
  /** Path of the row currently being edited (rename target or draft path). */
@@ -705,6 +815,10 @@ declare interface FileTreePaneParams extends LeftTabParams {
705
815
  query?: string;
706
816
  bridge?: unknown;
707
817
  chromeless?: boolean;
818
+ revealFileTreeRequest?: {
819
+ path: string;
820
+ seq: number;
821
+ } | null;
708
822
  }
709
823
 
710
824
  export declare interface FileTreePaneProps extends Partial<PaneProps<FileTreePaneParams>> {
@@ -732,6 +846,8 @@ export declare interface FileTreeProps {
732
846
  onCollapse?: (path: string) => void;
733
847
  onContextMenu?: (event: React.MouseEvent, node: FileTreeNode) => void;
734
848
  onDragDrop?: (sourcePath: string, targetDirPath: string) => void;
849
+ /** Called after a reveal request has opened parents and scheduled scrolling. */
850
+ onRevealHandled?: (path: string) => void;
735
851
  /** Called when the user presses Enter on an inline-edit input. */
736
852
  onSubmitEdit?: (path: string, value: string) => void;
737
853
  /** Called when the user presses Esc or blurs without submitting. */
@@ -750,13 +866,17 @@ export declare interface FileTreeProps {
750
866
  * want a "Files" panel; `WorkbenchLeftPane` uses this primitive directly to
751
867
  * share its search input with the Data tab.
752
868
  */
753
- export declare function FileTreeView({ rootDir, searchQuery, bridge, ignoreNames, className, }: FileTreeViewProps): JSX.Element;
869
+ export declare function FileTreeView({ rootDir, searchQuery, bridge, revealFileTreeRequest, ignoreNames, className, }: FileTreeViewProps): JSX.Element;
754
870
 
755
871
  export declare interface FileTreeViewProps {
756
872
  rootDir?: string;
757
873
  /** Already-debounced query. Empty/undefined means no filter. */
758
874
  searchQuery?: string;
759
- bridge?: Pick<WorkspaceBridge, "openFile" | "getActiveFile" | "select">;
875
+ bridge?: Pick<WorkspaceBridge, "openFile" | "getActiveFile" | "select"> & Partial<Pick<WorkspaceBridge, "subscribe">>;
876
+ revealFileTreeRequest?: {
877
+ path: string;
878
+ seq: number;
879
+ } | null;
760
880
  /**
761
881
  * Names (or regex patterns) to hide from the tree. Defaults to
762
882
  * `DEFAULT_TREE_IGNORE` (node_modules, .git, dist, …). Pass `[]` to
@@ -818,6 +938,10 @@ export declare interface LeftTabParams {
818
938
  searchQuery?: string;
819
939
  bridge?: unknown;
820
940
  chromeless?: boolean;
941
+ revealFileTreeRequest?: {
942
+ path: string;
943
+ seq: number;
944
+ } | null;
821
945
  }
822
946
 
823
947
  export declare function MarkdownEditor({ content, onChange, readOnly, placeholder, className, documentPath, }: MarkdownEditorProps): JSX.Element;
@@ -965,6 +1089,7 @@ export declare interface PanelConfig<T = any> {
965
1089
  requiresCapabilities?: string[];
966
1090
  essential?: boolean;
967
1091
  chromeless?: boolean;
1092
+ supportsFullPage?: boolean;
968
1093
  /** Source: "builtin" | "app" */
969
1094
  source?: string;
970
1095
  pluginId?: string;
@@ -1050,6 +1175,8 @@ export declare interface PanelRegistryLike {
1050
1175
  register(id: string, config: PanelRegistration): void;
1051
1176
  }
1052
1177
 
1178
+ export declare type PanelRenderMode = "dock" | "full-page";
1179
+
1053
1180
  export declare interface PanelState {
1054
1181
  id: string;
1055
1182
  component: string;
@@ -1280,7 +1407,7 @@ export declare interface SurfaceResolverRegistryLike {
1280
1407
  register(id: string, config: SurfaceResolverRegistration): void;
1281
1408
  }
1282
1409
 
1283
- export declare function SurfaceShell({ rootDir, sidebarDefaultWidth, sidebarMinWidth, sidebarMaxWidth, storageKey, onReady, onChange, onClose, extraPanels, defaultLeftTab, className, }: SurfaceShellProps): JSX.Element;
1410
+ export declare function SurfaceShell({ rootDir, sidebarDefaultWidth, sidebarMinWidth, sidebarMaxWidth, storageKey, onReady, onChange, onClose, extraPanels, defaultLeftTab, initialPanels, className, }: SurfaceShellProps): JSX.Element;
1284
1411
 
1285
1412
  export declare interface SurfaceShellApi {
1286
1413
  /** Open a file in the workbench. Idempotent — re-activates an existing pane for the same path. */
@@ -1296,6 +1423,8 @@ export declare interface SurfaceShellApi {
1296
1423
  openPanel: (config: OpenPanelConfig) => void;
1297
1424
  /** Hide the workbench's left sources/files pane while leaving the workbench open. */
1298
1425
  closeWorkbenchLeftPane: () => void;
1426
+ /** Reveal/select a file-tree path without opening an editor pane. */
1427
+ expandToFile: (path: string) => void;
1299
1428
  /** Current snapshot of open tabs + active tab. */
1300
1429
  getSnapshot: () => SurfaceShellSnapshot;
1301
1430
  }
@@ -1325,6 +1454,12 @@ export declare interface SurfaceShellProps {
1325
1454
  */
1326
1455
  extraPanels?: string[];
1327
1456
  defaultLeftTab?: string;
1457
+ initialPanels?: Array<{
1458
+ id: string;
1459
+ component: string;
1460
+ title?: string;
1461
+ params?: Record<string, unknown>;
1462
+ }>;
1328
1463
  className?: string;
1329
1464
  }
1330
1465
 
@@ -1369,6 +1504,8 @@ export declare interface ToolExecContext {
1369
1504
  sessionId?: string;
1370
1505
  }
1371
1506
 
1507
+ declare type ToolReadinessRequirement = 'workspace-fs' | 'sandbox-exec' | 'ui-bridge';
1508
+
1372
1509
  export declare interface ToolResult {
1373
1510
  content: Array<{
1374
1511
  type: "text";
@@ -1423,6 +1560,8 @@ export declare function useActivePanel(): string | null;
1423
1560
 
1424
1561
  export declare function useActivePanels(): readonly PanelConfig[];
1425
1562
 
1563
+ export declare function useApiBaseUrl(): string;
1564
+
1426
1565
  export declare function useArtifactPanels(surfaceApi: DockviewShellApi | null): UseArtifactPanelsReturn;
1427
1566
 
1428
1567
  export declare interface UseArtifactPanelsReturn {
@@ -1483,6 +1622,7 @@ export declare interface UseEditorLifecycleReturn {
1483
1622
  isSaving: boolean;
1484
1623
  lastSavedAt: number | null;
1485
1624
  markDirty: () => void;
1625
+ markClean: () => void;
1486
1626
  flushSave: () => Promise<void>;
1487
1627
  shouldSync: boolean;
1488
1628
  ackSync: () => void;
@@ -1500,8 +1640,74 @@ export declare interface UseEditorLifecycleReturn {
1500
1640
  */
1501
1641
  export declare function useEvent<K extends keyof WorkspaceEventMap>(name: K, handler: (payload: WorkspaceEventMap[K]) => void): void;
1502
1642
 
1643
+ /**
1644
+ * Shared hook for file-based panes (code editor, markdown editor, etc.).
1645
+ *
1646
+ * Handles:
1647
+ * - File loading via React Query
1648
+ * - Local content state with dirty tracking
1649
+ * - Optimistic concurrency control (OCC) via mtime
1650
+ * - External file change detection
1651
+ * - Conflict resolution (reload vs overwrite)
1652
+ * - Panel title updates with dirty indicator
1653
+ *
1654
+ * @example
1655
+ * ```typescript
1656
+ * function MyEditorPane({ params, api }) {
1657
+ * const { content, setContent, isLoading, error, conflict, ... } = useFilePane({
1658
+ * path: params.path,
1659
+ * panelId: api.id,
1660
+ * })
1661
+ *
1662
+ * if (!params.path) return <NoFileSelected />
1663
+ * if (error) return <ErrorBanner error={error} />
1664
+ *
1665
+ * return (
1666
+ * <>
1667
+ * {conflict && <ConflictBanner onReload={onReloadFromServer} onOverwrite={onOverwrite} />}
1668
+ * <MyEditor content={content} onChange={setContent} />
1669
+ * </>
1670
+ * )
1671
+ * }
1672
+ * ```
1673
+ */
1674
+ export declare function useFilePane(options: UseFilePaneOptions): UseFilePaneReturn;
1675
+
1676
+ export declare interface UseFilePaneOptions {
1677
+ /** The file path to load/edit. If empty/undefined, pane shows "no file selected". */
1678
+ path: string;
1679
+ /** Unique panel ID for lifecycle tracking. Omit to use a stable per-pane fallback ID. */
1680
+ panelId?: string;
1681
+ /** Initial content (optional, for draft/unsaved files). */
1682
+ initialContent?: string;
1683
+ }
1684
+
1685
+ export declare interface UseFilePaneReturn {
1686
+ isLoading: boolean;
1687
+ error: Error | null;
1688
+ content: string | null;
1689
+ isDirty: boolean;
1690
+ conflict: FileConflictError | null;
1691
+ onReloadFromServer: () => Promise<void>;
1692
+ onOverwrite: () => Promise<void>;
1693
+ setContent: (content: string) => void;
1694
+ save: () => Promise<void>;
1695
+ flushSave: () => Promise<void>;
1696
+ fileName: string;
1697
+ tabTitle: string;
1698
+ }
1699
+
1700
+ export declare function useFullPagePanelHref(input: {
1701
+ componentId: string;
1702
+ params?: Record<string, unknown>;
1703
+ }): string | null;
1704
+
1705
+ export declare function useHasWorkspaceFilesProvider(): boolean;
1706
+
1503
1707
  export declare function useHydrationComplete(): boolean;
1504
1708
 
1709
+ export declare function useIsFullPagePanel(): boolean;
1710
+
1505
1711
  export declare function useKeyboardShortcuts({ shortcuts, enabled }: UseKeyboardShortcutsOptions): void;
1506
1712
 
1507
1713
  export declare interface UseKeyboardShortcutsOptions {
@@ -1511,6 +1717,8 @@ export declare interface UseKeyboardShortcutsOptions {
1511
1717
 
1512
1718
  export declare function useOpenPanels(): PanelState[];
1513
1719
 
1720
+ export declare function usePanelRenderMode(): PanelRenderMode;
1721
+
1514
1722
  export declare function usePluginErrors(): PluginErrorContextValue;
1515
1723
 
1516
1724
  export declare function useRegistry(): PanelRegistry;
@@ -1557,12 +1765,18 @@ export declare function useWorkspaceContext(): WorkspaceContextValue;
1557
1765
 
1558
1766
  export declare function useWorkspaceContextOptional(): WorkspaceContextValue | null;
1559
1767
 
1560
- export declare function WorkbenchLeftPane({ rootDir, bridge, defaultTab, onCollapse, className, }: WorkbenchLeftPaneProps): JSX.Element;
1768
+ export declare function useWorkspaceRequestId(): string | null;
1769
+
1770
+ export declare function WorkbenchLeftPane({ rootDir, bridge, defaultTab, revealFileTreeRequest, onCollapse, className, }: WorkbenchLeftPaneProps): JSX.Element;
1561
1771
 
1562
1772
  export declare interface WorkbenchLeftPaneProps {
1563
1773
  rootDir?: string;
1564
1774
  bridge?: WorkspaceBridge;
1565
1775
  defaultTab?: WorkbenchLeftTabId;
1776
+ revealFileTreeRequest?: {
1777
+ path: string;
1778
+ seq: number;
1779
+ } | null;
1566
1780
  onCollapse?: () => void;
1567
1781
  className?: string;
1568
1782
  }
@@ -1662,6 +1876,8 @@ export declare interface WorkspaceChatPanelProps {
1662
1876
  isWorkbenchOpen?: () => boolean;
1663
1877
  /** Opens the visible workbench surface before dispatching a command. */
1664
1878
  openWorkbench?: () => void;
1879
+ /** Opens the visible workbench sources/file-tree pane before dispatching a reveal. */
1880
+ openWorkbenchSources?: () => void;
1665
1881
  /** Closes the visible workbench surface after an ephemeral command finishes. */
1666
1882
  closeWorkbench?: () => void;
1667
1883
  /** Generic workspace blockers that should prevent submitting new chat turns. */
@@ -1685,6 +1901,8 @@ export declare interface WorkspaceEventMap extends WorkspaceHostEventMap, Worksp
1685
1901
  /** Names that share a prefix can be filtered with `startsWith`. */
1686
1902
  export declare type WorkspaceEventName = keyof WorkspaceEventMap;
1687
1903
 
1904
+ export declare function WorkspaceFilesProvider({ apiBaseUrl, authHeaders, onAuthError, timeout, client: providedClient, children, }: DataProviderProps): JSX.Element;
1905
+
1688
1906
  declare interface WorkspaceHostEventMap {
1689
1907
  /** Shared UI manipulation contract used by the agent stream and plugin bindings. */
1690
1908
  [WORKSPACE_UI_COMMAND_EVENT]: EventMeta & {
@@ -1732,6 +1950,9 @@ declare type WorkspacePanelMatch = {
1732
1950
  } | {
1733
1951
  param: string;
1734
1952
  value: unknown;
1953
+ } | {
1954
+ paramPrefix: string;
1955
+ value: string;
1735
1956
  };
1736
1957
 
1737
1958
  /**
@@ -1761,7 +1982,7 @@ export declare interface WorkspacePluginEventMap {
1761
1982
  };
1762
1983
  }
1763
1984
 
1764
- export declare function WorkspaceProvider({ children, chatPanel, plugins, excludeDefaults, panels, commands, catalogs, capabilities, apiBaseUrl, authHeaders, apiTimeout, defaultTheme, onThemeChange, workspaceId, storageKey, persistenceEnabled, bridgeEndpoint, onAuthError, onOpenFile, debug, frontPluginHotReload, }: WorkspaceProviderProps): JSX.Element;
1985
+ export declare function WorkspaceProvider({ children, chatPanel, plugins, excludeDefaults, panels, commands, catalogs, capabilities, apiBaseUrl, authHeaders, apiTimeout, defaultTheme, onThemeChange, workspaceId, storageKey, persistenceEnabled, bridgeEndpoint, onAuthError, onOpenFile, debug, frontPluginHotReload, fullPageBasePath, }: WorkspaceProviderProps): JSX.Element;
1765
1986
 
1766
1987
  export declare interface WorkspaceProviderProps {
1767
1988
  children: ReactNode;
@@ -1796,6 +2017,7 @@ export declare interface WorkspaceProviderProps {
1796
2017
  * own module asset endpoint.
1797
2018
  */
1798
2019
  frontPluginHotReload?: FrontPluginHotReloadMode;
2020
+ fullPageBasePath?: string;
1799
2021
  }
1800
2022
 
1801
2023
  export declare interface WorkspaceState {