@hachej/boring-workspace 0.1.61 → 0.1.63

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,12 +1,13 @@
1
1
  import { PiPackageSource, PiExtensionFactory, CreateAgentAppOptions, ProvisionWorkspaceRuntimeOptions } from '@hachej/boring-agent/server';
2
2
  export { PiPackageSource as WorkspacePiPackageSource } from '@hachej/boring-agent/server';
3
3
  import { FastifyInstance } from 'fastify';
4
- import { W as WorkspaceServerPlugin, S as ServerBootstrapOptions, a as WorkspaceBridgeRegistry, B as BridgeAuthPolicy, b as WorkspaceBridgeHandler, c as WorkspaceBridgeRuntimeEnvOptions, d as BoringPluginSourceInput, e as BoringPluginFrontTargetResolver, f as WorkspaceProvisioningContribution, g as WorkspaceRouteContribution, h as createInMemoryBridge } from './runtimeEnv-XVFZ1OkV.js';
5
- export { i as ServerWorkspaceRuntimeProvisioningInput } from './runtimeEnv-XVFZ1OkV.js';
4
+ import { W as WorkspaceServerPlugin, S as ServerBootstrapOptions, a as WorkspaceBridgeRegistry, B as BridgeAuthPolicy, b as WorkspaceBridgeHandler, c as WorkspaceBridgeRuntimeEnvOptions, d as BoringPluginSourceInput, e as BoringPluginFrontTargetResolver, f as createInMemoryBridge, g as WorkspaceProvisioningContribution, h as WorkspaceRouteContribution } from './runtimeEnv-HolIkcoB.js';
5
+ export { i as ServerWorkspaceRuntimeProvisioningInput } from './runtimeEnv-HolIkcoB.js';
6
6
  import { W as WorkspaceBridgeOperationDefinition } from './workspace-bridge-rpc-A98RA5o6.js';
7
7
  import './manifest-C2vVgH_e.js';
8
8
  import './agent-tool-CB0RQyx9.js';
9
- import './ui-bridge-BbuUZ5iC.js';
9
+ import './ui-bridge-D2eO3epD.js';
10
+ import './filesystem-vhLA0ERd.js';
10
11
 
11
12
  /**
12
13
  * Directory-source entry: `{ dir, options?, hotReload? }`. Resolved via
@@ -176,6 +177,7 @@ interface WorkspaceAgentServerPluginCollection {
176
177
  routeContributions: WorkspaceRouteContribution[];
177
178
  workspaceBridgeHandlers: WorkspaceServerPlugin["workspaceBridgeHandlers"];
178
179
  preservedUiStateKeys: string[];
180
+ defaultPluginPackagePaths: string[];
179
181
  agentOptions: Pick<WorkspaceAgentCreateOptions, "extraTools" | "systemPromptAppend" | "pi">;
180
182
  }
181
183
  interface CollectWorkspaceAgentServerPluginsOptions extends Pick<ServerBootstrapOptions, "plugins" | "defaults" | "excludeDefaults"> {
@@ -185,10 +187,18 @@ interface CollectWorkspaceAgentServerPluginsOptions extends Pick<ServerBootstrap
185
187
  /** Whether to include built-in boring plugin-authoring provisioning/prompt resources. */
186
188
  installPluginAuthoring?: boolean;
187
189
  }
190
+ interface ResolveWorkspaceAgentServerPluginCollectionOptions extends Omit<CollectWorkspaceAgentServerPluginsOptions, "plugins"> {
191
+ workspaceRoot: string;
192
+ bridge: ReturnType<typeof createInMemoryBridge>;
193
+ defaultPluginPackages?: string[];
194
+ appRoot?: string;
195
+ plugins?: WorkspacePluginEntry[];
196
+ }
188
197
  declare function buildWorkspaceContextPrompt(options?: {
189
198
  pluginAuthoringEnabled?: boolean;
190
199
  }): string;
191
200
  declare function collectWorkspaceAgentServerPlugins(opts?: CollectWorkspaceAgentServerPluginsOptions): WorkspaceAgentServerPluginCollection;
201
+ declare function resolveWorkspaceAgentServerPluginCollection(opts: ResolveWorkspaceAgentServerPluginCollectionOptions): Promise<WorkspaceAgentServerPluginCollection>;
192
202
  declare function provisionWorkspaceAgentServer(opts: {
193
203
  workspaceRoot: string;
194
204
  provisioningContributions?: WorkspaceProvisioningContribution[];
@@ -230,4 +240,4 @@ interface ResolveDefaultWorkspacePluginPackagePathsOptions {
230
240
  */
231
241
  declare function resolveDefaultWorkspacePluginPackagePaths({ workspaceRoot, defaultPluginPackages, anchorDir, }?: ResolveDefaultWorkspacePluginPackagePathsOptions): string[];
232
242
 
233
- export { type CollectWorkspaceAgentServerPluginsOptions, type CreateWorkspaceAgentServerOptions, type DirPluginEntry, PLUGIN_AUTHORING_PROVISIONING_IDS, type PluginResolveContext, type ResolveDefaultWorkspacePluginPackagePathsOptions, type WorkspaceAgentPiOptions, type WorkspaceAgentServerPluginCollection, type WorkspaceAgentServerPluginContext, type WorkspacePluginEntry, type WorkspacePluginPackagePiSnapshot, WorkspaceProvisioningContribution, WorkspaceRouteContribution, type WorkspaceRuntimeProvisioningInput, assertWorkspaceBridgeHandlersTrusted, buildWorkspaceContextPrompt, collectWorkspaceAgentServerPlugins, createWorkspaceAgentServer, hasDirServerPlugin, isTrustedWorkspaceBridgeHandlerEntry, omitPluginAuthoringProvisioning, provisionWorkspaceAgentServer, readWorkspacePluginPackagePiSnapshot, readWorkspacePluginPackageRuntimePlugins, resolveDefaultWorkspacePluginPackagePaths, resolveOnePluginEntry };
243
+ export { type CollectWorkspaceAgentServerPluginsOptions, type CreateWorkspaceAgentServerOptions, type DirPluginEntry, PLUGIN_AUTHORING_PROVISIONING_IDS, type PluginResolveContext, type ResolveDefaultWorkspacePluginPackagePathsOptions, type ResolveWorkspaceAgentServerPluginCollectionOptions, type WorkspaceAgentPiOptions, type WorkspaceAgentServerPluginCollection, type WorkspaceAgentServerPluginContext, type WorkspacePluginEntry, type WorkspacePluginPackagePiSnapshot, WorkspaceProvisioningContribution, WorkspaceRouteContribution, type WorkspaceRuntimeProvisioningInput, assertWorkspaceBridgeHandlersTrusted, buildWorkspaceContextPrompt, collectWorkspaceAgentServerPlugins, createWorkspaceAgentServer, hasDirServerPlugin, isTrustedWorkspaceBridgeHandlerEntry, omitPluginAuthoringProvisioning, provisionWorkspaceAgentServer, readWorkspacePluginPackagePiSnapshot, readWorkspacePluginPackageRuntimePlugins, resolveDefaultWorkspacePluginPackagePaths, resolveOnePluginEntry, resolveWorkspaceAgentServerPluginCollection };
@@ -2457,6 +2457,14 @@ function registerWorkspaceUiBridge(bridge) {
2457
2457
  // src/server/ui-control/tools/uiTools.ts
2458
2458
  import { stat } from "fs/promises";
2459
2459
  import { resolve as resolve6, isAbsolute as isAbsolute4, relative as relative3, win32 } from "path";
2460
+
2461
+ // src/shared/types/filesystem.ts
2462
+ var USER_FILESYSTEM_ID = "user";
2463
+ function normalizeUiFilesystem(filesystem) {
2464
+ return filesystem && filesystem.length > 0 ? filesystem : USER_FILESYSTEM_ID;
2465
+ }
2466
+
2467
+ // src/server/ui-control/tools/uiTools.ts
2460
2468
  function makeError(message) {
2461
2469
  return {
2462
2470
  content: [{ type: "text", text: message }],
@@ -2474,9 +2482,9 @@ function isPathAbsolute(filePath) {
2474
2482
  function isOutsideWorkspaceRel(rel) {
2475
2483
  return rel === ".." || rel.startsWith("../") || rel.startsWith("..\\") || isPathAbsolute(rel);
2476
2484
  }
2477
- function validatePathSyntax(relPath, workspaceRoot) {
2485
+ function validatePathSyntax(relPath, workspaceRoot, opts = {}) {
2478
2486
  const rootHint = workspaceRoot ? ` (${workspaceRoot})` : "";
2479
- if (isPathAbsolute(relPath)) {
2487
+ if (!opts.allowAbsolute && isPathAbsolute(relPath)) {
2480
2488
  return {
2481
2489
  ok: false,
2482
2490
  reason: `path "${relPath}" is absolute \u2014 pass a path relative to the workspace root${rootHint}.`
@@ -2558,7 +2566,10 @@ function isVerified(kind, params, state) {
2558
2566
  const tabs = state.openTabs ?? [];
2559
2567
  if (kind === "openFile") {
2560
2568
  const path = typeof params.path === "string" ? params.path : null;
2561
- return path !== null && tabs.some((t) => t.params?.path === path);
2569
+ const filesystem = normalizeUiFilesystem(typeof params.filesystem === "string" ? params.filesystem : void 0);
2570
+ return path !== null && tabs.some(
2571
+ (t) => t.params?.path === path && normalizeUiFilesystem(typeof t.params?.filesystem === "string" ? t.params.filesystem : void 0) === filesystem
2572
+ );
2562
2573
  }
2563
2574
  if (kind === "openPanel") {
2564
2575
  const id = typeof params.id === "string" ? params.id : null;
@@ -2598,7 +2609,7 @@ function createExecUiTool(workspaceBridge, opts = {}) {
2598
2609
  "",
2599
2610
  "Supported `kind` values:",
2600
2611
  "",
2601
- " openFile params: { path: string, mode?: 'view'|'edit'|'diff' }",
2612
+ " openFile params: { path: string, mode?: 'view'|'edit'|'diff', filesystem?: 'user'|'company_context' }",
2602
2613
  " \u2014 Open a file in the workbench. The workbench pane",
2603
2614
  " auto-opens if collapsed. Path must be relative to the",
2604
2615
  " workspace root (e.g. `src/foo.ts`, not `foo.ts` if it",
@@ -2613,6 +2624,8 @@ function createExecUiTool(workspaceBridge, opts = {}) {
2613
2624
  " is found.",
2614
2625
  " If the path is a folder, openFile reveals/selects it in",
2615
2626
  " the file tree instead of opening an editor tab.",
2627
+ " Omit filesystem for normal workspace files (defaults to user). Use filesystem:'company_context' only when a company_context binding is advertised.",
2628
+ " Path prefixes such as company_context:/x do not switch filesystem identity.",
2616
2629
  " Example: {kind:'openFile', params:{path:'README.md'}}",
2617
2630
  "",
2618
2631
  " openPanel params: { id: string, component: string,",
@@ -2627,11 +2640,15 @@ function createExecUiTool(workspaceBridge, opts = {}) {
2627
2640
  " component:'chart-canvas',",
2628
2641
  " params:{seriesId:'GDPC1'}}}",
2629
2642
  "",
2630
- " openSurface params: { kind: string, target: string, meta?: object }",
2643
+ " openSurface params: { kind: string, target: string, filesystem?: 'user'|'company_context', meta?: object }",
2631
2644
  " \u2014 Open an app-owned target through the workspace",
2632
2645
  " surface resolver registry. Use this when the app",
2633
2646
  " defines the mapping from domain target to panel",
2634
2647
  " component, for example a catalog row.",
2648
+ " For kind:'workspace.open.path', filesystem follows the",
2649
+ " same rules as openFile: omit for user files; pass",
2650
+ " filesystem:'company_context' only for advertised company",
2651
+ " context bindings; path prefixes do not switch identity.",
2635
2652
  " Example: {kind:'openSurface', params:{",
2636
2653
  " kind:'catalog.open-row',",
2637
2654
  " target:'orders_daily',",
@@ -2705,29 +2722,32 @@ function createExecUiTool(workspaceBridge, opts = {}) {
2705
2722
  `${kind}: ${kind === "navigateToLine" ? "file" : "path"} param is required`
2706
2723
  );
2707
2724
  }
2708
- const syntax = validatePathSyntax(relPath, workspaceRoot);
2725
+ const filesystem = kind === "openFile" ? normalizeUiFilesystem(typeof cmdParams.filesystem === "string" ? cmdParams.filesystem : void 0) : USER_FILESYSTEM_ID;
2726
+ const syntax = validatePathSyntax(relPath, workspaceRoot, { allowAbsolute: filesystem !== USER_FILESYSTEM_ID });
2709
2727
  if (!syntax.ok) return makeError(syntax.reason);
2710
- if (workspaceRoot) {
2711
- const check = await validateExistingPath(workspaceRoot, relPath);
2712
- if (!check.ok) {
2713
- return makeError(check.reason);
2714
- }
2715
- if (kind === "openFile" && check.kind === "dir") {
2716
- effectiveKind = "expandToFile";
2717
- }
2718
- } else if (resolvePathKind) {
2719
- const pathKind = await resolvePathKind(relPath);
2720
- if (!pathKind) {
2721
- return makeError(`file not found at "${relPath}". Try find or grep to locate the file before retrying openFile.`);
2722
- }
2723
- if (kind === "openFile" && pathKind === "dir") {
2724
- effectiveKind = "expandToFile";
2728
+ if (filesystem === USER_FILESYSTEM_ID) {
2729
+ if (workspaceRoot) {
2730
+ const check = await validateExistingPath(workspaceRoot, relPath);
2731
+ if (!check.ok) {
2732
+ return makeError(check.reason);
2733
+ }
2734
+ if (kind === "openFile" && check.kind === "dir") {
2735
+ effectiveKind = "expandToFile";
2736
+ }
2737
+ } else if (resolvePathKind) {
2738
+ const pathKind = await resolvePathKind(relPath);
2739
+ if (!pathKind) {
2740
+ return makeError(`file not found at "${relPath}". Try find or grep to locate the file before retrying openFile.`);
2741
+ }
2742
+ if (kind === "openFile" && pathKind === "dir") {
2743
+ effectiveKind = "expandToFile";
2744
+ }
2725
2745
  }
2726
2746
  }
2727
2747
  }
2728
2748
  try {
2729
2749
  const command = { kind: effectiveKind, params: cmdParams };
2730
- const result = await workspaceBridge.emitUiEffect(command);
2750
+ const result = await workspaceBridge.postCommand(command);
2731
2751
  if (result.status === "error") {
2732
2752
  return {
2733
2753
  content: [{ type: "text", text: JSON.stringify(result) }],
@@ -2979,8 +2999,9 @@ function uiRoutes(app, opts, done) {
2979
2999
  const body = request.body;
2980
3000
  const bridge = await resolveBridge(request);
2981
3001
  const current = await bridge.getState() ?? {};
3002
+ const preserveStateKeys = opts.getPreserveStateKeys ? await opts.getPreserveStateKeys(request) : opts.preserveStateKeys ?? [];
2982
3003
  const preserved = Object.fromEntries(
2983
- (opts.preserveStateKeys ?? []).filter((key) => !(key in body.state) && key in current).map((key) => [key, current[key]])
3004
+ preserveStateKeys.filter((key) => !(key in body.state) && key in current).map((key) => [key, current[key]])
2984
3005
  );
2985
3006
  await bridge.setState({ ...body.state, ...preserved });
2986
3007
  return reply.code(204).send();
@@ -3928,6 +3949,7 @@ function collectWorkspaceAgentServerPlugins(opts = {}) {
3928
3949
  routeContributions: result.routeContributions,
3929
3950
  workspaceBridgeHandlers: result.workspaceBridgeHandlers,
3930
3951
  preservedUiStateKeys: result.preservedUiStateKeys,
3952
+ defaultPluginPackagePaths: [],
3931
3953
  agentOptions: {
3932
3954
  extraTools: result.agentTools,
3933
3955
  systemPromptAppend: [opts.systemPromptAppend, result.systemPromptAppend].filter(Boolean).join("\n\n") || void 0,
@@ -3944,6 +3966,31 @@ function collectWorkspaceAgentServerPlugins(opts = {}) {
3944
3966
  }
3945
3967
  };
3946
3968
  }
3969
+ async function resolveWorkspaceAgentServerPluginCollection(opts) {
3970
+ const ctx = { workspaceRoot: opts.workspaceRoot, bridge: opts.bridge };
3971
+ const defaultPluginPackagePaths = resolveDefaultWorkspacePluginPackagePaths({
3972
+ workspaceRoot: opts.workspaceRoot,
3973
+ defaultPluginPackages: opts.defaultPluginPackages,
3974
+ anchorDir: opts.appRoot
3975
+ });
3976
+ const defaultPluginDirEntries = defaultPluginPackagePaths.map((dir) => ({ dir, hotReload: true, trust: "internal" })).filter((entry) => hasDirServerPlugin(entry));
3977
+ const allPluginEntries = [
3978
+ ...defaultPluginDirEntries,
3979
+ ...opts.plugins ?? []
3980
+ ];
3981
+ const resolvedPlugins = await Promise.all(
3982
+ allPluginEntries.map(async (entry) => {
3983
+ const plugin = await resolveOnePluginEntry(entry, ctx);
3984
+ assertWorkspaceBridgeHandlersTrusted(plugin, entry);
3985
+ return plugin;
3986
+ })
3987
+ );
3988
+ const collection = collectWorkspaceAgentServerPlugins({
3989
+ ...opts,
3990
+ plugins: resolvedPlugins
3991
+ });
3992
+ return { ...collection, defaultPluginPackagePaths };
3993
+ }
3947
3994
  async function provisionWorkspaceAgentServer(opts) {
3948
3995
  if (!opts.provisioningContributions?.length) return;
3949
3996
  await provisionRuntimeWorkspace({
@@ -4117,30 +4164,19 @@ async function createWorkspaceAgentServer(opts = {}) {
4117
4164
  const uiTools = createWorkspaceUiTools(bridge, {
4118
4165
  workspaceRoot: validateUiPaths ? workspaceRoot : void 0
4119
4166
  });
4120
- const ctx = { workspaceRoot, bridge };
4121
- const defaultPluginPackagePaths = resolveDefaultWorkspacePluginPackagePaths({
4167
+ const pluginAuthoringEnabled = externalPluginsEnabled && (opts.installPluginAuthoring ?? workspaceFsCapability === "strong") && !(opts.excludeDefaults ?? []).includes("boring-ui-plugin-cli-package");
4168
+ const pluginCollection = await resolveWorkspaceAgentServerPluginCollection({
4169
+ ...opts,
4122
4170
  workspaceRoot,
4123
- defaultPluginPackages: opts.defaultPluginPackages,
4124
- anchorDir: opts.appRoot
4171
+ bridge,
4172
+ installPluginAuthoring: pluginAuthoringEnabled
4125
4173
  });
4126
- const defaultPluginDirEntries = defaultPluginPackagePaths.map((dir) => ({ dir, hotReload: true, trust: "internal" })).filter((entry) => hasDirServerPlugin(entry));
4174
+ const defaultPluginPackagePaths = pluginCollection.defaultPluginPackagePaths;
4175
+ const ctx = { workspaceRoot, bridge };
4127
4176
  const allPluginEntries = [
4128
- ...defaultPluginDirEntries,
4177
+ ...defaultPluginPackagePaths.map((dir) => ({ dir, hotReload: true, trust: "internal" })).filter((entry) => hasDirServerPlugin(entry)),
4129
4178
  ...opts.plugins ?? []
4130
4179
  ];
4131
- const resolvedPlugins = await Promise.all(
4132
- allPluginEntries.map(async (entry) => {
4133
- const plugin = await resolveOnePluginEntry(entry, ctx);
4134
- assertWorkspaceBridgeHandlersTrusted(plugin, entry);
4135
- return plugin;
4136
- })
4137
- );
4138
- const pluginAuthoringEnabled = externalPluginsEnabled && (opts.installPluginAuthoring ?? workspaceFsCapability === "strong") && !(opts.excludeDefaults ?? []).includes("boring-ui-plugin-cli-package");
4139
- const pluginCollection = collectWorkspaceAgentServerPlugins({
4140
- ...opts,
4141
- plugins: resolvedPlugins,
4142
- installPluginAuthoring: pluginAuthoringEnabled
4143
- });
4144
4180
  const { registry: workspaceBridgeRegistry } = createWorkspaceBridgeRuntimeCore({
4145
4181
  registry: opts.workspaceBridge?.registry,
4146
4182
  ownerWorkspaceId: "default",
@@ -4364,5 +4400,6 @@ export {
4364
4400
  readWorkspacePluginPackagePiSnapshot,
4365
4401
  readWorkspacePluginPackageRuntimePlugins,
4366
4402
  resolveDefaultWorkspacePluginPackagePaths,
4367
- resolveOnePluginEntry
4403
+ resolveOnePluginEntry,
4404
+ resolveWorkspaceAgentServerPluginCollection
4368
4405
  };
package/dist/events.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { F as FilesystemId } from './filesystem-vhLA0ERd.js';
2
+
1
3
  /**
2
4
  * Tiny typed event bus. ~30 lines, no runtime deps.
3
5
  *
@@ -58,9 +60,12 @@ type WorkspacePanelMatch = {
58
60
  } | {
59
61
  param: string;
60
62
  value: unknown;
63
+ } | {
64
+ params: Record<string, unknown>;
61
65
  } | {
62
66
  paramPrefix: string;
63
67
  value: string;
68
+ params?: Record<string, unknown>;
64
69
  };
65
70
  /**
66
71
  * Discriminated origin metadata. Encoded as a union (rather than a
@@ -148,17 +153,21 @@ interface WorkspaceHostEventMap {
148
153
  */
149
154
  interface WorkspacePluginEventMap {
150
155
  "filesystem:file.changed": EventMeta & {
156
+ filesystem?: FilesystemId;
151
157
  path: string;
152
158
  };
153
159
  "filesystem:file.created": EventMeta & {
160
+ filesystem?: FilesystemId;
154
161
  path: string;
155
162
  kind: "file" | "dir";
156
163
  };
157
164
  "filesystem:file.moved": EventMeta & {
165
+ filesystem?: FilesystemId;
158
166
  from: string;
159
167
  to: string;
160
168
  };
161
169
  "filesystem:file.deleted": EventMeta & {
170
+ filesystem?: FilesystemId;
162
171
  path: string;
163
172
  };
164
173
  }
@@ -0,0 +1,17 @@
1
+ type FilesystemId = "user" | "company_context" | (string & {});
2
+ declare const USER_FILESYSTEM_ID = "user";
3
+ declare const COMPANY_CONTEXT_FILESYSTEM_ID = "company_context";
4
+ interface UiFileResource {
5
+ readonly filesystem: FilesystemId;
6
+ readonly path: string;
7
+ }
8
+ type UiFileResourceInput = string | {
9
+ readonly filesystem?: FilesystemId | null;
10
+ readonly path: string;
11
+ };
12
+ declare function normalizeUiFilesystem(filesystem: FilesystemId | null | undefined): FilesystemId;
13
+ declare function normalizeUiFileResource(input: UiFileResourceInput): UiFileResource;
14
+ declare function uiFileResourceKey(resource: UiFileResourceInput): string;
15
+ declare function withUiFileResource<T extends Record<string, unknown>>(value: T, fallbackFilesystem?: FilesystemId | null): T & UiFileResource;
16
+
17
+ export { COMPANY_CONTEXT_FILESYSTEM_ID as C, type FilesystemId as F, USER_FILESYSTEM_ID as U, type UiFileResource as a, type UiFileResourceInput as b, normalizeUiFilesystem as c, normalizeUiFileResource as n, uiFileResourceKey as u, withUiFileResource as w };
package/dist/plugin.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { ComponentType, ReactNode } from 'react';
2
- import { P as PaneProps, a as PanelConfig, g as WorkspaceSourceProps, h as SurfaceResolverExample, S as SurfaceOpenRequest, c as SurfacePanelResolution } from './surface-CDklwi48.js';
3
- export { W as WORKSPACE_OPEN_PATH_SURFACE_KIND, i as WorkspaceSourceOpenPanelConfig } from './surface-CDklwi48.js';
2
+ import { P as PaneProps, a as PanelConfig, g as WorkspaceSourceProps, h as SurfaceResolverExample, S as SurfaceOpenRequest, c as SurfacePanelResolution } from './surface-aLQ_Hryw.js';
3
+ export { W as WORKSPACE_OPEN_PATH_SURFACE_KIND, i as WorkspaceSourceOpenPanelConfig } from './surface-aLQ_Hryw.js';
4
4
  export { B as BoringPackageBoringField, a as BoringPackagePiField, b as BoringPackagePiSource, c as BoringPackagePiSourceObject, d as BoringPluginManifestErrorCode, e as BoringPluginManifestIssue, f as BoringPluginManifestValidationResult, g as BoringPluginPackageJson, i as isSafePluginRelativePath, h as isValidBoringPluginId, v as validateBoringPluginManifest } from './manifest-C2vVgH_e.js';
5
- import { a as UiCommand, C as CommandResult, U as UiBridge } from './ui-bridge-BbuUZ5iC.js';
5
+ import { a as UiCommand, C as CommandResult, U as UiBridge } from './ui-bridge-D2eO3epD.js';
6
6
  import 'dockview-react';
7
+ import './filesystem-vhLA0ERd.js';
7
8
 
8
9
  type CatalogBadge = {
9
10
  /** 1–4 char mono code rendered as a chip. */
@@ -3,7 +3,7 @@ import { PiPackageSource, PluginSkillSource, ProvisionWorkspaceRuntimeOptions, R
3
3
  import { FastifyPluginAsync } from 'fastify';
4
4
  import { A as AgentTool } from './agent-tool-CB0RQyx9.js';
5
5
  import { B as BridgeAuthContext, W as WorkspaceBridgeOperationDefinition, a as WorkspaceBridgeCallRequest, b as WorkspaceBridgeCallResponse, d as BridgeCallerClass } from './workspace-bridge-rpc-A98RA5o6.js';
6
- import { a as UiCommand, C as CommandResult, W as WorkspaceBridge } from './ui-bridge-BbuUZ5iC.js';
6
+ import { a as UiCommand, C as CommandResult, W as WorkspaceBridge } from './ui-bridge-D2eO3epD.js';
7
7
 
8
8
  type BoringPluginNativeFrontTargetTrust$1 = "local-trusted-native";
9
9
  /**
@@ -350,4 +350,4 @@ declare function createWorkspaceBridgeRuntimeEnvContribution(options: CreateWork
350
350
  declare function resolveBridgeCallUrl(value: string | undefined): string | undefined;
351
351
  declare function resolveBridgeTokenUrl(value: string | undefined): string | undefined;
352
352
 
353
- export { type WorkspaceBridgeCallContext as A, type BridgeAuthPolicy as B, type CreateWorkspaceBridgeRuntimeEnvContributionOptions as C, type WorkspaceBridgeHandlerArgs as D, type WorkspaceBridgeHandlerContribution as E, type WorkspaceBridgeRegistryCallOptions as F, type WorkspaceBridgeRegistryLogger as G, type WorkspaceBridgeRegistryOptions as H, type WorkspaceBridgeRuntimeEnvDisabledReason as I, type WorkspaceBridgeRuntimePlacement as J, bootstrapServer as K, type LocalCliBridgeAuthPolicyOptions as L, createBrowserBridgeAuthPolicy as M, createLocalCliBridgeAuthPolicy as N, createWorkspaceBridgeRegistry as O, type PluginRestartSurface as P, createWorkspaceBridgeRuntimeEnvContribution as Q, type RegisterWorkspaceBridgeHandlerOptions as R, type ServerBootstrapOptions as S, defineServerPlugin as T, resolveBridgeCallUrl as U, resolveBridgeTokenUrl as V, type WorkspaceServerPlugin as W, validateServerPlugin as X, validateWorkspaceBridgeOperationDefinition as Y, WorkspaceBridgeRegistry as a, type WorkspaceBridgeHandler as b, type WorkspaceBridgeRuntimeEnvOptions as c, type BoringPluginSourceInput as d, type BoringPluginFrontTargetResolver as e, type WorkspaceProvisioningContribution as f, type WorkspaceRouteContribution as g, createInMemoryBridge as h, type WorkspaceRuntimeProvisioningInput as i, type WorkspaceServerPluginAsset as j, type BoringServerPluginManifest as k, type BoringPluginListEntry as l, type BoringPluginFrontTarget as m, type BoringPluginSource as n, type BoringPluginEvent as o, type BoringPluginFrontTargetResolverContext as p, type BoringPluginNativeFrontTarget as q, type BoringPluginNativeFrontTargetTrust as r, type BoringPluginSourceKind as s, type BridgeAuthPolicyInput as t, type BridgeAuthPolicyRequestLike as u, type BridgeAuthResolution as v, type BridgePrincipal as w, type BridgeWorkspaceGrant as x, type BrowserBridgeAuthPolicyOptions as y, type ServerBootstrapResult as z };
353
+ export { type WorkspaceBridgeCallContext as A, type BridgeAuthPolicy as B, type CreateWorkspaceBridgeRuntimeEnvContributionOptions as C, type WorkspaceBridgeHandlerArgs as D, type WorkspaceBridgeHandlerContribution as E, type WorkspaceBridgeRegistryCallOptions as F, type WorkspaceBridgeRegistryLogger as G, type WorkspaceBridgeRegistryOptions as H, type WorkspaceBridgeRuntimeEnvDisabledReason as I, type WorkspaceBridgeRuntimePlacement as J, bootstrapServer as K, type LocalCliBridgeAuthPolicyOptions as L, createBrowserBridgeAuthPolicy as M, createLocalCliBridgeAuthPolicy as N, createWorkspaceBridgeRegistry as O, type PluginRestartSurface as P, createWorkspaceBridgeRuntimeEnvContribution as Q, type RegisterWorkspaceBridgeHandlerOptions as R, type ServerBootstrapOptions as S, defineServerPlugin as T, resolveBridgeCallUrl as U, resolveBridgeTokenUrl as V, type WorkspaceServerPlugin as W, validateServerPlugin as X, validateWorkspaceBridgeOperationDefinition as Y, WorkspaceBridgeRegistry as a, type WorkspaceBridgeHandler as b, type WorkspaceBridgeRuntimeEnvOptions as c, type BoringPluginSourceInput as d, type BoringPluginFrontTargetResolver as e, createInMemoryBridge as f, type WorkspaceProvisioningContribution as g, type WorkspaceRouteContribution as h, type WorkspaceRuntimeProvisioningInput as i, type WorkspaceServerPluginAsset as j, type BoringServerPluginManifest as k, type BoringPluginListEntry as l, type BoringPluginFrontTarget as m, type BoringPluginSource as n, type BoringPluginEvent as o, type BoringPluginFrontTargetResolverContext as p, type BoringPluginNativeFrontTarget as q, type BoringPluginNativeFrontTargetTrust as r, type BoringPluginSourceKind as s, type BridgeAuthPolicyInput as t, type BridgeAuthPolicyRequestLike as u, type BridgeAuthResolution as v, type BridgePrincipal as w, type BridgeWorkspaceGrant as x, type BrowserBridgeAuthPolicyOptions as y, type ServerBootstrapResult as z };
package/dist/server.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { j as WorkspaceServerPluginAsset, a as WorkspaceBridgeRegistry, B as BridgeAuthPolicy, b as WorkspaceBridgeHandler, k as BoringServerPluginManifest, d as BoringPluginSourceInput, e as BoringPluginFrontTargetResolver, l as BoringPluginListEntry, m as BoringPluginFrontTarget, n as BoringPluginSource, o as BoringPluginEvent, P as PluginRestartSurface } from './runtimeEnv-XVFZ1OkV.js';
2
- export { p as BoringPluginFrontTargetResolverContext, q as BoringPluginNativeFrontTarget, r as BoringPluginNativeFrontTargetTrust, s as BoringPluginSourceKind, t as BridgeAuthPolicyInput, u as BridgeAuthPolicyRequestLike, v as BridgeAuthResolution, w as BridgePrincipal, x as BridgeWorkspaceGrant, y as BrowserBridgeAuthPolicyOptions, C as CreateWorkspaceBridgeRuntimeEnvContributionOptions, L as LocalCliBridgeAuthPolicyOptions, R as RegisterWorkspaceBridgeHandlerOptions, S as ServerBootstrapOptions, z as ServerBootstrapResult, A as WorkspaceBridgeCallContext, D as WorkspaceBridgeHandlerArgs, E as WorkspaceBridgeHandlerContribution, F as WorkspaceBridgeRegistryCallOptions, G as WorkspaceBridgeRegistryLogger, H as WorkspaceBridgeRegistryOptions, I as WorkspaceBridgeRuntimeEnvDisabledReason, c as WorkspaceBridgeRuntimeEnvOptions, J as WorkspaceBridgeRuntimePlacement, f as WorkspaceProvisioningContribution, g as WorkspaceRouteContribution, W as WorkspaceServerPlugin, K as bootstrapServer, M as createBrowserBridgeAuthPolicy, h as createInMemoryBridge, N as createLocalCliBridgeAuthPolicy, O as createWorkspaceBridgeRegistry, Q as createWorkspaceBridgeRuntimeEnvContribution, T as defineServerPlugin, U as resolveBridgeCallUrl, V as resolveBridgeTokenUrl, X as validateServerPlugin, Y as validateWorkspaceBridgeOperationDefinition } from './runtimeEnv-XVFZ1OkV.js';
1
+ import { j as WorkspaceServerPluginAsset, a as WorkspaceBridgeRegistry, B as BridgeAuthPolicy, b as WorkspaceBridgeHandler, k as BoringServerPluginManifest, d as BoringPluginSourceInput, e as BoringPluginFrontTargetResolver, l as BoringPluginListEntry, m as BoringPluginFrontTarget, n as BoringPluginSource, o as BoringPluginEvent, P as PluginRestartSurface } from './runtimeEnv-HolIkcoB.js';
2
+ export { p as BoringPluginFrontTargetResolverContext, q as BoringPluginNativeFrontTarget, r as BoringPluginNativeFrontTargetTrust, s as BoringPluginSourceKind, t as BridgeAuthPolicyInput, u as BridgeAuthPolicyRequestLike, v as BridgeAuthResolution, w as BridgePrincipal, x as BridgeWorkspaceGrant, y as BrowserBridgeAuthPolicyOptions, C as CreateWorkspaceBridgeRuntimeEnvContributionOptions, L as LocalCliBridgeAuthPolicyOptions, R as RegisterWorkspaceBridgeHandlerOptions, S as ServerBootstrapOptions, z as ServerBootstrapResult, A as WorkspaceBridgeCallContext, D as WorkspaceBridgeHandlerArgs, E as WorkspaceBridgeHandlerContribution, F as WorkspaceBridgeRegistryCallOptions, G as WorkspaceBridgeRegistryLogger, H as WorkspaceBridgeRegistryOptions, I as WorkspaceBridgeRuntimeEnvDisabledReason, c as WorkspaceBridgeRuntimeEnvOptions, J as WorkspaceBridgeRuntimePlacement, g as WorkspaceProvisioningContribution, h as WorkspaceRouteContribution, W as WorkspaceServerPlugin, K as bootstrapServer, M as createBrowserBridgeAuthPolicy, f as createInMemoryBridge, N as createLocalCliBridgeAuthPolicy, O as createWorkspaceBridgeRegistry, Q as createWorkspaceBridgeRuntimeEnvContribution, T as defineServerPlugin, U as resolveBridgeCallUrl, V as resolveBridgeTokenUrl, X as validateServerPlugin, Y as validateWorkspaceBridgeOperationDefinition } from './runtimeEnv-HolIkcoB.js';
3
3
  import { FastifyRequest, FastifyInstance } from 'fastify';
4
- import { U as UiBridge, W as WorkspaceBridge } from './ui-bridge-BbuUZ5iC.js';
5
- export { C as CommandResult, a as UiCommand, b as UiState } from './ui-bridge-BbuUZ5iC.js';
4
+ import { U as UiBridge, W as WorkspaceBridge } from './ui-bridge-D2eO3epD.js';
5
+ export { C as CommandResult, a as UiCommand, b as UiState } from './ui-bridge-D2eO3epD.js';
6
6
  import { A as AgentTool } from './agent-tool-CB0RQyx9.js';
7
7
  import { W as WorkspaceBridgeOperationDefinition, a as WorkspaceBridgeCallRequest, B as BridgeAuthContext, b as WorkspaceBridgeCallResponse, c as WorkspaceBridgeError, d as BridgeCallerClass, e as BridgeIdempotencyPolicy } from './workspace-bridge-rpc-A98RA5o6.js';
8
8
  export { f as BridgeActorAttribution, g as BridgeActorKind, h as BridgeRedactedActorRef, i as WorkspaceBridgeCallFailure, j as WorkspaceBridgeCallSuccess, k as WorkspaceBridgeErrorCode, l as WorkspaceBridgeFileAssetPointer, m as WorkspaceBridgeJsonValue, n as createWorkspaceBridgeError } from './workspace-bridge-rpc-A98RA5o6.js';
@@ -12,6 +12,7 @@ import { PluginLogger } from './runtime-server.js';
12
12
  export { RuntimePluginContext, RuntimePluginHandler, RuntimePluginResponse, RuntimePluginRouter, RuntimeServerPlugin, defineRuntimeServerPlugin, validateRuntimeServerPlugin } from './runtime-server.js';
13
13
  import { ErrorCode } from '@hachej/boring-agent/shared';
14
14
  import './manifest-C2vVgH_e.js';
15
+ import './filesystem-vhLA0ERd.js';
15
16
 
16
17
  declare function definePluginAsset(importMetaUrl: string, name: string, relativeSource: string, options?: {
17
18
  target?: string;
@@ -74,6 +75,7 @@ interface UiRoutesOptions {
74
75
  * these slots are published out-of-band by server plugins.
75
76
  */
76
77
  preserveStateKeys?: string[];
78
+ getPreserveStateKeys?: (request: FastifyRequest) => string[] | Promise<string[]>;
77
79
  paneStatusStore?: PaneRenderStatusStore;
78
80
  }
79
81
  declare function uiRoutes(app: FastifyInstance, opts: UiRoutesOptions, done: (err?: Error) => void): void;
package/dist/server.js CHANGED
@@ -262,8 +262,9 @@ function uiRoutes(app, opts, done) {
262
262
  const body = request.body;
263
263
  const bridge = await resolveBridge(request);
264
264
  const current = await bridge.getState() ?? {};
265
+ const preserveStateKeys = opts.getPreserveStateKeys ? await opts.getPreserveStateKeys(request) : opts.preserveStateKeys ?? [];
265
266
  const preserved = Object.fromEntries(
266
- (opts.preserveStateKeys ?? []).filter((key) => !(key in body.state) && key in current).map((key) => [key, current[key]])
267
+ preserveStateKeys.filter((key) => !(key in body.state) && key in current).map((key) => [key, current[key]])
267
268
  );
268
269
  await bridge.setState({ ...body.state, ...preserved });
269
270
  return reply.code(204).send();
@@ -343,6 +344,14 @@ data: ${JSON.stringify({ v: UI_BRIDGE_PROTOCOL_VERSION })}
343
344
  // src/server/ui-control/tools/uiTools.ts
344
345
  import { stat } from "fs/promises";
345
346
  import { resolve, isAbsolute, relative, win32 } from "path";
347
+
348
+ // src/shared/types/filesystem.ts
349
+ var USER_FILESYSTEM_ID = "user";
350
+ function normalizeUiFilesystem(filesystem) {
351
+ return filesystem && filesystem.length > 0 ? filesystem : USER_FILESYSTEM_ID;
352
+ }
353
+
354
+ // src/server/ui-control/tools/uiTools.ts
346
355
  function makeError(message) {
347
356
  return {
348
357
  content: [{ type: "text", text: message }],
@@ -360,9 +369,9 @@ function isPathAbsolute(filePath) {
360
369
  function isOutsideWorkspaceRel(rel) {
361
370
  return rel === ".." || rel.startsWith("../") || rel.startsWith("..\\") || isPathAbsolute(rel);
362
371
  }
363
- function validatePathSyntax(relPath, workspaceRoot) {
372
+ function validatePathSyntax(relPath, workspaceRoot, opts = {}) {
364
373
  const rootHint = workspaceRoot ? ` (${workspaceRoot})` : "";
365
- if (isPathAbsolute(relPath)) {
374
+ if (!opts.allowAbsolute && isPathAbsolute(relPath)) {
366
375
  return {
367
376
  ok: false,
368
377
  reason: `path "${relPath}" is absolute \u2014 pass a path relative to the workspace root${rootHint}.`
@@ -444,7 +453,10 @@ function isVerified(kind, params, state) {
444
453
  const tabs = state.openTabs ?? [];
445
454
  if (kind === "openFile") {
446
455
  const path = typeof params.path === "string" ? params.path : null;
447
- return path !== null && tabs.some((t) => t.params?.path === path);
456
+ const filesystem = normalizeUiFilesystem(typeof params.filesystem === "string" ? params.filesystem : void 0);
457
+ return path !== null && tabs.some(
458
+ (t) => t.params?.path === path && normalizeUiFilesystem(typeof t.params?.filesystem === "string" ? t.params.filesystem : void 0) === filesystem
459
+ );
448
460
  }
449
461
  if (kind === "openPanel") {
450
462
  const id = typeof params.id === "string" ? params.id : null;
@@ -484,7 +496,7 @@ function createExecUiTool(workspaceBridge, opts = {}) {
484
496
  "",
485
497
  "Supported `kind` values:",
486
498
  "",
487
- " openFile params: { path: string, mode?: 'view'|'edit'|'diff' }",
499
+ " openFile params: { path: string, mode?: 'view'|'edit'|'diff', filesystem?: 'user'|'company_context' }",
488
500
  " \u2014 Open a file in the workbench. The workbench pane",
489
501
  " auto-opens if collapsed. Path must be relative to the",
490
502
  " workspace root (e.g. `src/foo.ts`, not `foo.ts` if it",
@@ -499,6 +511,8 @@ function createExecUiTool(workspaceBridge, opts = {}) {
499
511
  " is found.",
500
512
  " If the path is a folder, openFile reveals/selects it in",
501
513
  " the file tree instead of opening an editor tab.",
514
+ " Omit filesystem for normal workspace files (defaults to user). Use filesystem:'company_context' only when a company_context binding is advertised.",
515
+ " Path prefixes such as company_context:/x do not switch filesystem identity.",
502
516
  " Example: {kind:'openFile', params:{path:'README.md'}}",
503
517
  "",
504
518
  " openPanel params: { id: string, component: string,",
@@ -513,11 +527,15 @@ function createExecUiTool(workspaceBridge, opts = {}) {
513
527
  " component:'chart-canvas',",
514
528
  " params:{seriesId:'GDPC1'}}}",
515
529
  "",
516
- " openSurface params: { kind: string, target: string, meta?: object }",
530
+ " openSurface params: { kind: string, target: string, filesystem?: 'user'|'company_context', meta?: object }",
517
531
  " \u2014 Open an app-owned target through the workspace",
518
532
  " surface resolver registry. Use this when the app",
519
533
  " defines the mapping from domain target to panel",
520
534
  " component, for example a catalog row.",
535
+ " For kind:'workspace.open.path', filesystem follows the",
536
+ " same rules as openFile: omit for user files; pass",
537
+ " filesystem:'company_context' only for advertised company",
538
+ " context bindings; path prefixes do not switch identity.",
521
539
  " Example: {kind:'openSurface', params:{",
522
540
  " kind:'catalog.open-row',",
523
541
  " target:'orders_daily',",
@@ -591,29 +609,32 @@ function createExecUiTool(workspaceBridge, opts = {}) {
591
609
  `${kind}: ${kind === "navigateToLine" ? "file" : "path"} param is required`
592
610
  );
593
611
  }
594
- const syntax = validatePathSyntax(relPath, workspaceRoot);
612
+ const filesystem = kind === "openFile" ? normalizeUiFilesystem(typeof cmdParams.filesystem === "string" ? cmdParams.filesystem : void 0) : USER_FILESYSTEM_ID;
613
+ const syntax = validatePathSyntax(relPath, workspaceRoot, { allowAbsolute: filesystem !== USER_FILESYSTEM_ID });
595
614
  if (!syntax.ok) return makeError(syntax.reason);
596
- if (workspaceRoot) {
597
- const check = await validateExistingPath(workspaceRoot, relPath);
598
- if (!check.ok) {
599
- return makeError(check.reason);
600
- }
601
- if (kind === "openFile" && check.kind === "dir") {
602
- effectiveKind = "expandToFile";
603
- }
604
- } else if (resolvePathKind) {
605
- const pathKind = await resolvePathKind(relPath);
606
- if (!pathKind) {
607
- return makeError(`file not found at "${relPath}". Try find or grep to locate the file before retrying openFile.`);
608
- }
609
- if (kind === "openFile" && pathKind === "dir") {
610
- effectiveKind = "expandToFile";
615
+ if (filesystem === USER_FILESYSTEM_ID) {
616
+ if (workspaceRoot) {
617
+ const check = await validateExistingPath(workspaceRoot, relPath);
618
+ if (!check.ok) {
619
+ return makeError(check.reason);
620
+ }
621
+ if (kind === "openFile" && check.kind === "dir") {
622
+ effectiveKind = "expandToFile";
623
+ }
624
+ } else if (resolvePathKind) {
625
+ const pathKind = await resolvePathKind(relPath);
626
+ if (!pathKind) {
627
+ return makeError(`file not found at "${relPath}". Try find or grep to locate the file before retrying openFile.`);
628
+ }
629
+ if (kind === "openFile" && pathKind === "dir") {
630
+ effectiveKind = "expandToFile";
631
+ }
611
632
  }
612
633
  }
613
634
  }
614
635
  try {
615
636
  const command = { kind: effectiveKind, params: cmdParams };
616
- const result = await workspaceBridge.emitUiEffect(command);
637
+ const result = await workspaceBridge.postCommand(command);
617
638
  if (result.status === "error") {
618
639
  return {
619
640
  content: [{ type: "text", text: JSON.stringify(result) }],
package/dist/shared.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { C as CommandResult, a as UiCommand, b as UiState, W as WorkspaceBridge } from './ui-bridge-BbuUZ5iC.js';
1
+ export { C as CommandResult, a as UiCommand, b as UiState, W as WorkspaceBridge } from './ui-bridge-D2eO3epD.js';
2
2
  export { f as BridgeActorAttribution, g as BridgeActorKind, B as BridgeAuthContext, d as BridgeCallerClass, e as BridgeIdempotencyPolicy, h as BridgeRedactedActorRef, i as WorkspaceBridgeCallFailure, a as WorkspaceBridgeCallRequest, b as WorkspaceBridgeCallResponse, j as WorkspaceBridgeCallSuccess, c as WorkspaceBridgeError, k as WorkspaceBridgeErrorCode, l as WorkspaceBridgeFileAssetPointer, m as WorkspaceBridgeJsonValue, W as WorkspaceBridgeOperationDefinition, n as createWorkspaceBridgeError } from './workspace-bridge-rpc-A98RA5o6.js';
3
- export { C as CommandConfig, P as PaneProps, a as PanelConfig, b as PanelRegistration, S as SurfaceOpenRequest, c as SurfacePanelResolution, d as SurfaceResolverConfig, e as SurfaceResolverRegistration, W as WORKSPACE_OPEN_PATH_SURFACE_KIND, f as definePanel } from './surface-CDklwi48.js';
3
+ export { C as CommandConfig, P as PaneProps, a as PanelConfig, b as PanelRegistration, S as SurfaceOpenRequest, c as SurfacePanelResolution, d as SurfaceResolverConfig, e as SurfaceResolverRegistration, W as WORKSPACE_OPEN_PATH_SURFACE_KIND, f as definePanel } from './surface-aLQ_Hryw.js';
4
+ export { C as COMPANY_CONTEXT_FILESYSTEM_ID, F as FilesystemId, U as USER_FILESYSTEM_ID, a as UiFileResource, b as UiFileResourceInput, n as normalizeUiFileResource, c as normalizeUiFilesystem, u as uiFileResourceKey, w as withUiFileResource } from './filesystem-vhLA0ERd.js';
4
5
  export { A as AgentTool, J as JSONSchema, T as ToolExecContext, a as ToolResult } from './agent-tool-CB0RQyx9.js';
5
6
  import 'react';
6
7
  import 'dockview-react';
package/dist/shared.js CHANGED
@@ -26,6 +26,34 @@ function createWorkspaceBridgeError(code, message, details) {
26
26
  return details === void 0 ? { code, message } : { code, message, details };
27
27
  }
28
28
 
29
+ // src/shared/types/filesystem.ts
30
+ var USER_FILESYSTEM_ID = "user";
31
+ var COMPANY_CONTEXT_FILESYSTEM_ID = "company_context";
32
+ function normalizeUiFilesystem(filesystem) {
33
+ return filesystem && filesystem.length > 0 ? filesystem : USER_FILESYSTEM_ID;
34
+ }
35
+ function normalizeUiFileResource(input) {
36
+ if (typeof input === "string") {
37
+ return { filesystem: USER_FILESYSTEM_ID, path: input };
38
+ }
39
+ return {
40
+ filesystem: normalizeUiFilesystem(input.filesystem),
41
+ path: input.path
42
+ };
43
+ }
44
+ function uiFileResourceKey(resource) {
45
+ const normalized = normalizeUiFileResource(resource);
46
+ return `${normalized.filesystem}:${normalized.path}`;
47
+ }
48
+ function withUiFileResource(value, fallbackFilesystem) {
49
+ const filesystem = typeof value.filesystem === "string" ? value.filesystem : normalizeUiFilesystem(fallbackFilesystem);
50
+ return {
51
+ ...value,
52
+ filesystem,
53
+ path: String(value.path ?? "")
54
+ };
55
+ }
56
+
29
57
  // src/shared/types/surface.ts
30
58
  var WORKSPACE_OPEN_PATH_SURFACE_KIND = "workspace.open.path";
31
59
 
@@ -47,10 +75,16 @@ function safeCapture(telemetry, event) {
47
75
  }
48
76
  }
49
77
  export {
78
+ COMPANY_CONTEXT_FILESYSTEM_ID,
79
+ USER_FILESYSTEM_ID,
50
80
  WORKSPACE_OPEN_PATH_SURFACE_KIND,
51
81
  WorkspaceBridgeErrorCode,
52
82
  createWorkspaceBridgeError,
53
83
  definePanel,
54
84
  noopTelemetry,
55
- safeCapture
85
+ normalizeUiFileResource,
86
+ normalizeUiFilesystem,
87
+ safeCapture,
88
+ uiFileResourceKey,
89
+ withUiFileResource
56
90
  };
@@ -1,5 +1,6 @@
1
1
  import { ComponentType } from 'react';
2
2
  import { DockviewPanelApi, DockviewApi } from 'dockview-react';
3
+ import { F as FilesystemId } from './filesystem-vhLA0ERd.js';
3
4
 
4
5
  /**
5
6
  * Shared panel and command types — no runtime deps beyond React/dockview.
@@ -111,6 +112,7 @@ declare const WORKSPACE_OPEN_PATH_SURFACE_KIND = "workspace.open.path";
111
112
  interface SurfaceOpenRequest {
112
113
  kind: string;
113
114
  target: string;
115
+ filesystem?: FilesystemId;
114
116
  meta?: Record<string, unknown>;
115
117
  }
116
118
  interface SurfacePanelResolution {