@qwen-code/web-shell 0.25.1-preview.1 → 0.25.1-preview.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/{agents-route-DAa1HKQE.js → agents-route-B3FonPY-.js} +2 -2
  2. package/dist/daemon-react-sdk.js +1 -1
  3. package/dist/{index-zUj3SlrB.js → index-BPRuZpl-.js} +45926 -45076
  4. package/dist/index.js +3 -3
  5. package/dist/sw.js +1 -1
  6. package/dist/{toolNames-B_KiYcXs.js → toolNames-CusX912Z.js} +1375 -1334
  7. package/dist/transcript.js +3775 -3757
  8. package/dist/types/components/ChatEditor.d.ts +4 -7
  9. package/dist/types/components/WorkspaceSelector.d.ts +9 -1
  10. package/dist/types/components/artifacts/artifactUtils.d.ts +9 -0
  11. package/dist/types/components/managed/generated/managed-agent-api.d.ts +74 -17
  12. package/dist/types/components/managed/use-managed-actions.d.ts +6 -5
  13. package/dist/types/components/sidebar/WebShellSidebar.d.ts +7 -1
  14. package/dist/types/components/sidebar/WorkspaceSection.d.ts +9 -1
  15. package/dist/types/components/workspaces/HostLabel.d.ts +8 -0
  16. package/dist/types/components/workspaces/WorkspaceHostProjects.d.ts +11 -4
  17. package/dist/types/components/workspaces/WorkspaceLocation.d.ts +4 -1
  18. package/dist/types/config/daemon-target.d.ts +76 -0
  19. package/dist/types/config/daemon.d.ts +16 -0
  20. package/dist/types/config/host-fanout.d.ts +53 -0
  21. package/dist/types/config/remote-connections.d.ts +3 -0
  22. package/dist/types/config/workspace-hosts.d.ts +7 -0
  23. package/dist/types/trajectory/types.d.ts +1 -0
  24. package/dist/types/trajectory/useTrajectoryWindow.d.ts +21 -36
  25. package/dist/types/trajectory/window-messages.d.ts +9 -0
  26. package/dist/types/trajectory/window-messages.transcript-stub.d.ts +7 -0
  27. package/dist/types/utils/workspace.d.ts +10 -0
  28. package/package.json +1 -1
@@ -10,6 +10,7 @@ import { type ComposerSubmitMetadata, type EditorHandle } from '../hooks/useComp
10
10
  import type { ContextUsageControls } from '../hooks/useContextUsageControls';
11
11
  import type { VoiceStatusRevision, VoiceWorkspaceTarget } from '../voice/voice-workspace-target';
12
12
  import { type SessionGitIntent } from './GitModePopover';
13
+ import { type WorkspaceSelectorOption } from './WorkspaceSelector';
13
14
  export type ComposerToolbarAction = 'approvalMode' | 'plan' | 'contextUsage' | 'gitBranch' | 'model' | 'commands' | 'files' | 'widthMode' | 'voice' | 'workspace' | 'addMenu';
14
15
  interface ChatEditorProps {
15
16
  onSubmit: (text: string, images?: import('../adapters/promptTypes').PromptImage[], files?: import('../adapters/promptTypes').PromptFile[], commitAccepted?: import('../hooks/useComposerCore').ComposerSubmitCommit, metadata?: ComposerSubmitMetadata) => boolean | void;
@@ -101,16 +102,12 @@ interface ChatEditorProps {
101
102
  onSelectModel?: (model: string) => void;
102
103
  reasoning?: DaemonReasoningControls;
103
104
  onSelectReasoningEffort?: (value: ReasoningSelection, source?: 'toggle') => Promise<void> | void;
104
- workspaces?: Array<{
105
- id: string;
106
- cwd: string;
107
- label: string;
108
- primary: boolean;
109
- trusted: boolean;
110
- }>;
105
+ workspaces?: WorkspaceSelectorOption[];
111
106
  selectedWorkspaceCwd?: string;
112
107
  workspaceSelectionDisabled?: boolean;
113
108
  onSelectWorkspace?: (workspaceCwd: string | undefined) => void;
109
+ /** Host-aware variant; see WorkspaceSelector. */
110
+ onSelectHostedWorkspace?: (hostOrigin: string, workspaceCwd: string | undefined) => void;
114
111
  scratchWorkspaceSupported?: boolean;
115
112
  existingFolderWorkspaceSupported?: boolean;
116
113
  standaloneTargetSupported?: boolean;
@@ -4,6 +4,8 @@ export interface WorkspaceSelectorOption {
4
4
  label: string;
5
5
  primary: boolean;
6
6
  trusted: boolean;
7
+ /** Daemon host this workspace lives on; defaults to the page origin. */
8
+ hostOrigin?: string;
7
9
  }
8
10
  interface WorkspaceSelectorProps {
9
11
  workspaces: WorkspaceSelectorOption[];
@@ -17,6 +19,12 @@ interface WorkspaceSelectorProps {
17
19
  selectedStandalone?: boolean;
18
20
  className?: string;
19
21
  onSelectWorkspace: (cwd: string | undefined) => void;
22
+ /**
23
+ * Host-aware selection for multi-daemon pages. When provided it fires
24
+ * INSTEAD of `onSelectWorkspace`, with the option's host (page origin when
25
+ * unset); `undefined` cwd keeps marking the host's primary workspace.
26
+ */
27
+ onSelectHostedWorkspace?: (hostOrigin: string, cwd: string | undefined) => void;
20
28
  onSelectStandalone?: () => void;
21
29
  onCreateScratch: () => void;
22
30
  onOpenExistingFolder: () => void;
@@ -25,5 +33,5 @@ interface WorkspaceSelectorProps {
25
33
  * Composer workspace menu. Capability-gated creation actions and disabled
26
34
  * untrusted entries keep presentation aligned with daemon authorization.
27
35
  */
28
- export declare function WorkspaceSelector({ workspaces, selectedWorkspaceCwd, disabled, busy, scratchSupported, existingFolderSupported, standaloneSupported, selectedStandalone, className, onSelectWorkspace, onSelectStandalone, onCreateScratch, onOpenExistingFolder, }: WorkspaceSelectorProps): import("react/jsx-runtime").JSX.Element | null;
36
+ export declare function WorkspaceSelector({ workspaces, selectedWorkspaceCwd, disabled, busy, scratchSupported, existingFolderSupported, standaloneSupported, selectedStandalone, className, onSelectWorkspace, onSelectHostedWorkspace, onSelectStandalone, onCreateScratch, onOpenExistingFolder, }: WorkspaceSelectorProps): import("react/jsx-runtime").JSX.Element | null;
29
37
  export {};
@@ -30,6 +30,15 @@ export declare function readWorkspaceFileAsBlob(readFileBytes: (filePath: string
30
30
  }): Promise<Blob>;
31
31
  export declare function downloadWorkspaceFile(workspaceActions: Pick<DaemonWorkspaceActions, 'readFileBytes' | 'stat'>, workspacePath: string, mimeType?: string, isCancelled?: () => boolean): Promise<void>;
32
32
  export declare function getArtifactLocation(artifact: DaemonSessionArtifact): string;
33
+ /**
34
+ * Workspace files are shown by filename. Links and managed artifacts have no
35
+ * file, so they keep the stored title.
36
+ */
37
+ export declare function artifactDisplayName(artifact: Pick<DaemonSessionArtifact, 'title'> & {
38
+ workspacePath?: string;
39
+ }): string;
40
+ /** A backslash stays in the name, matching `path.posix.basename`. */
41
+ export declare function workspaceFileName(workspacePath: string | undefined): string | undefined;
33
42
  export declare function normalizePath(value: string | undefined): string;
34
43
  export declare function stripWorkspacePath(path: string, workspaceCwd?: string): string;
35
44
  export declare function isSamePath(left: string | undefined, right: string | undefined, workspaceCwd?: string): boolean;
@@ -57,7 +57,7 @@ export interface paths {
57
57
  };
58
58
  get?: never;
59
59
  put?: never;
60
- /** @description POST SSE consumed through fetch response.body. An afterSequence below the replay floor ends the stream with one agent.session.resync_required frame instead of a 409; reload the transcript and resume after its lastSequence. */
60
+ /** @description POST SSE consumed through fetch response.body. An afterSequence below the replay floor ends the stream with one agent.session.resync_required frame instead of a 409 only while the Snapshot backs the floor (replay_floor_sequence <= snapshot_through_sequence); a stream reconciliation discards the Snapshot without lowering the floor, and during that rebuild such a cursor is served from the retained events. On the resync frame, reload the transcript and resume after its lastSequence. */
61
61
  post: operations["webShellStreamEvents"];
62
62
  delete?: never;
63
63
  options?: never;
@@ -74,7 +74,7 @@ export interface paths {
74
74
  };
75
75
  get?: never;
76
76
  put?: never;
77
- /** @description Maps workspaceId/cwdRelative to public Workspace selection without using environmentId or absolute cwd. Shares G0's opt-in initial file-tool Turn admission and fixed server-owned profile with public Session creation. The Session creator may submit later Turns under the same opt-in with current read and create grants on the bound ACTIVE Workspace generation and storage. Cancellation of running work requires the creator’s read grant and the opt-in, even after create authority is revoked (a live cancel reuses the owner's resident Harness attachment; a cold connector cache passively re-attaches for a persisted cancellation after frozen identity checks, independently of current creation grants, registry state or mount readiness; new work still rechecks execution authority); Workspace close follows its separate close capability and lifecycle admission; archive and unarchive follow retention capabilities after reliable Workspace close; delete supports either L3 idle ACTIVE files Sessions or L2 CLOSED/ARCHIVED Sessions; controlled same-Workspace cwd changes ship through the durable cwd_change operations (v1.32). The per-caller workspaceTurns capability on this surface advertises current submit and rename admission; it does not gate cancellation. Freeze selection with the original idempotency key; admission does not prove physical directory readiness. */
77
+ /** @description Maps workspaceId/cwdRelative to public Workspace selection without using environmentId or absolute cwd. Shares G0's opt-in initial file-tool Turn admission and fixed server-owned profile with public Session creation. Any caller holding the OPERATOR role may submit later Turns and rename the Session under the same opt-in, while the Workspace registry row stays ACTIVE and still backs the binding, the actor recorded by the Workspace create command keeps OPERATOR or above, and the Session is an active, undeleted qwen-code Session on the frozen execution profile; Workspace close follows its separate close capability and lifecycle admission; the same caller may cancel a running Turn (its delivery re-checks no grants); archive and unarchive follow their separate retention capabilities after reliable Workspace close; delete supports either L3 idle ACTIVE files Sessions or L2 CLOSED/ARCHIVED Sessions; controlled same-Workspace cwd changes ship through the durable cwd_change operations (v1.32). The per-caller workspaceTurns capability on this surface advertises the same submit/rename admission rule; it does not gate cancellation. Freeze selection with the original idempotency key; admission does not prove physical directory readiness. */
78
78
  post: operations["webShellCreateSession"];
79
79
  delete?: never;
80
80
  options?: never;
@@ -140,7 +140,7 @@ export interface paths {
140
140
  };
141
141
  get?: never;
142
142
  put?: never;
143
- /** @description W2, implemented: the camelCase twin of the public changeSessionCwd with the matched refusal order: 400 invalid_request for a missing or malformed field; 401 actor_required without a trusted actor; 400 invalid_idempotency_key for a malformed idempotencyKey — with two documented divergences: a key over 128 characters is refused during request validation with 400 invalid_request before the service's check, and a blank idempotencyKey is refused there too, while the public header answers 400 invalid_idempotency_key for both shapes; 400 invalid_cwd for a lexical violation and 400 invalid_request for an expectedContextRevision below 1; 404 session_not_found for an unknown Session id; 400 unsupported_feature for an unbound Session; 404 session_not_found for an unreadable Session and 403 session_operation_forbidden when a readable actor is not the creator; 409 idempotency_conflict when one key carries different content; 409 workspace_unavailable when execution is disabled; 404 session_not_found for a deleted Session — a completed change under the same key still replays instead; then 409 session_state_conflict, 409 workspace_unavailable from moved Registry facts, 409 context_revision_conflict and 409 session_context_busy exactly like the public surface. Poll the operation or await session.context.changed; do not treat 202 as activation. */
143
+ /** @description W2, implemented: the camelCase twin of the public changeSessionCwd with the matched refusal order: 400 invalid_request for a missing or malformed field; 401 actor_required without a trusted actor; 400 invalid_idempotency_key for a malformed idempotencyKey — with two documented divergences: a key over 128 characters is refused during request validation with 400 invalid_request before the service's check, and a blank idempotencyKey is refused there too, while the public header answers 400 invalid_idempotency_key for both shapes; 400 invalid_cwd for a lexical violation and 400 invalid_request for an expectedContextRevision below 1; 404 session_not_found for an unknown Session id; 400 unsupported_feature for an unbound Session; 404 session_not_found for an unreadable Session; 409 idempotency_conflict when one key carries different content, and a completed change under the same key always replays instead, before the role refusal; 403 session_operation_forbidden when a readable actor's Workspace role is below OPERATOR; 409 workspace_unavailable when execution is disabled; 404 session_not_found for a deleted Session; then 409 session_state_conflict, 409 workspace_unavailable from moved Registry facts (the recorded create-command actor's grant included, and the settlement re-checks the V56-persisted initiator the same way, so demoting either actor fails the operation, exactly like the public surface), 409 context_revision_conflict and 409 session_context_busy. Poll the operation or await session.context.changed; do not treat 202 as activation. */
144
144
  post: operations["webShellChangeCwd"];
145
145
  delete?: never;
146
146
  options?: never;
@@ -173,7 +173,7 @@ export interface paths {
173
173
  };
174
174
  get?: never;
175
175
  put?: never;
176
- /** @description D6 serves Hosted permission Actions. Question Actions and vote_recorded remain planned. Reads follow Session authorization; only the Session creator may respond (a Session with no recorded creator and no recorded create command answers to any caller in its tenant). Responses are durable operations, reconciled against the original journal decision. */
176
+ /** @description D6 serves Hosted permission Actions. Question Actions and vote_recorded remain planned. Reads follow Session authorization; the Session's recorded owner or any caller holding OPERATOR on the bound Workspace may respond (an unbound Session with no recorded creator and no recorded create command answers to any caller in its tenant, matching its read ACL; a bound Session without an owner record answers through the create-command actor recorded for it, or through the Workspace role arm). Responses are durable operations, reconciled against the original journal decision. */
177
177
  post: operations["queryWebShellActions"];
178
178
  delete?: never;
179
179
  options?: never;
@@ -190,7 +190,7 @@ export interface paths {
190
190
  };
191
191
  get?: never;
192
192
  put?: never;
193
- /** @description D6 serves Hosted permission Actions. Question Actions and vote_recorded remain planned. Reads follow Session authorization; only the Session creator may respond (a Session with no recorded creator and no recorded create command answers to any caller in its tenant). Responses are durable operations, reconciled against the original journal decision. */
193
+ /** @description D6 serves Hosted permission Actions. Question Actions and vote_recorded remain planned. Reads follow Session authorization; the Session's recorded owner or any caller holding OPERATOR on the bound Workspace may respond (an unbound Session with no recorded creator and no recorded create command answers to any caller in its tenant, matching its read ACL; a bound Session without an owner record answers through the create-command actor recorded for it, or through the Workspace role arm). Responses are durable operations, reconciled against the original journal decision. */
194
194
  post: operations["getWebShellAction"];
195
195
  delete?: never;
196
196
  options?: never;
@@ -207,7 +207,7 @@ export interface paths {
207
207
  };
208
208
  get?: never;
209
209
  put?: never;
210
- /** @description D6 serves Hosted permission Actions. Question Actions and vote_recorded remain planned. Reads follow Session authorization; only the Session creator may respond (a Session with no recorded creator and no recorded create command answers to any caller in its tenant). Responses are durable operations, reconciled against the original journal decision. */
210
+ /** @description D6 serves Hosted permission Actions. Question Actions and vote_recorded remain planned. Reads follow Session authorization; the Session's recorded owner or any caller holding OPERATOR on the bound Workspace may respond (an unbound Session with no recorded creator and no recorded create command answers to any caller in its tenant, matching its read ACL; a bound Session without an owner record answers through the create-command actor recorded for it, or through the Workspace role arm). Responses are durable operations, reconciled against the original journal decision. */
211
211
  post: operations["respondWebShellAction"];
212
212
  delete?: never;
213
213
  options?: never;
@@ -224,7 +224,7 @@ export interface paths {
224
224
  };
225
225
  get?: never;
226
226
  put?: never;
227
- /** @description Uses the same close admission, creator authorization and durable cleanup semantics as the public close route. sessionClose describes deployment support; it does not grant actor authorization. New L3 Workspace close operations run SessionEnd only, retain data, and finish after durable effects verification and original Runtime stop. SessionDelete is reserved for ACTIVE delete. Missing protocol support rejects new admission; previously admitted operations retain their saved protocol. Unknown outcomes remain recovery_blocked. */
227
+ /** @description Uses the same close admission, owner authorization and durable cleanup semantics as the public close route. sessionClose describes deployment support; it does not grant actor authorization. New L3 Workspace close operations run SessionEnd only, retain data, and finish after durable effects verification and original Runtime stop. SessionDelete is reserved for ACTIVE delete. Missing protocol support rejects new admission; previously admitted operations retain their saved protocol. Unknown outcomes remain recovery_blocked. */
228
228
  post: operations["closeWebShellSession"];
229
229
  delete?: never;
230
230
  options?: never;
@@ -241,7 +241,7 @@ export interface paths {
241
241
  };
242
242
  get?: never;
243
243
  put?: never;
244
- /** @description Workspace-bound archive requires a closed Session with completed reliable-close evidence and the creator with current read access. It completes atomically during admission, preserves data and the permanent close fence, and calls neither Harness nor Runtime. A readable non-creator returns 403; missing close evidence returns 409 workspace_unavailable. */
244
+ /** @description Workspace-bound archive requires a closed Session with completed reliable-close evidence and the Session's recorded owner with current read access. It completes atomically during admission, preserves data and the permanent close fence, and calls neither Harness nor Runtime. A readable non-owner returns 403; missing close evidence returns 409 workspace_unavailable. */
245
245
  post: operations["archiveWebShellSession"];
246
246
  delete?: never;
247
247
  options?: never;
@@ -258,7 +258,7 @@ export interface paths {
258
258
  };
259
259
  get?: never;
260
260
  put?: never;
261
- /** @description Workspace-bound ACTIVE deletion supports idle hosted-workspace-files/1 Sessions when L3 lifecycle protocol and reliable Runtime stop are available. Only the creator with current read access may admit it; accepted, running, cancelling or approval-waiting Turns return 409 turn_active. Admission persists a lifecycle-only execution fence and a versioned actor-scoped operation. SessionEnd settles before SessionDelete; committed Hook results are verified in Session Store and saved before permanent draining, attachment cleanup and original worker stop. Unknown outcomes or missing original stop evidence remain recovery_blocked and are never replayed on a replacement worker. CLOSED/ARCHIVED deletion retains L2: completed reliable-close evidence is required and no Harness or Hook is invoked. Completion atomically commits retirement, tombstone, receipt and terminal event, retaining shared Workspace files and neighboring holders. Authorized same-actor/key replays return the original operation, including after deletion; readable non-creators return 403. Missing lifecycle capability or close evidence returns 409 workspace_unavailable. */
261
+ /** @description Workspace-bound ACTIVE deletion supports idle hosted-workspace-files/1 Sessions when L3 lifecycle protocol and reliable Runtime stop are available. Only the Session's recorded owner (owner_actor_key, with the pre-V40 creator fallback) with current read access may admit it; accepted, running, cancelling or approval-waiting Turns return 409 turn_active. Admission persists a lifecycle-only execution fence and a versioned actor-scoped operation. SessionEnd settles before SessionDelete; committed Hook results are verified in Session Store and saved before permanent draining, attachment cleanup and original worker stop. Unknown outcomes or missing original stop evidence remain recovery_blocked and are never replayed on a replacement worker. CLOSED/ARCHIVED deletion retains L2: completed reliable-close evidence is required and no Harness or Hook is invoked. Completion atomically commits retirement, tombstone, receipt and terminal event, retaining shared Workspace files and neighboring holders. Authorized same-actor/key replays return the original operation, including after deletion; a readable non-owner returns 403. Missing lifecycle capability or close evidence returns 409 workspace_unavailable. */
262
262
  post: operations["deleteWebShellSession"];
263
263
  delete?: never;
264
264
  options?: never;
@@ -331,6 +331,22 @@ export interface paths {
331
331
  patch?: never;
332
332
  trace?: never;
333
333
  };
334
+ "/api/agent/web-shell/v1/tasks/cancel": {
335
+ parameters: {
336
+ query?: never;
337
+ header?: never;
338
+ path?: never;
339
+ cookie?: never;
340
+ };
341
+ get?: never;
342
+ put?: never;
343
+ post: operations["cancelWebShellTask"];
344
+ delete?: never;
345
+ options?: never;
346
+ head?: never;
347
+ patch?: never;
348
+ trace?: never;
349
+ };
334
350
  "/api/agent/web-shell/v1/tool-results/get": {
335
351
  parameters: {
336
352
  query?: never;
@@ -388,7 +404,7 @@ export interface paths {
388
404
  };
389
405
  get?: never;
390
406
  put?: never;
391
- /** @description Synchronously restores an archived Session to closed. Workspace-bound Sessions require completed reliable-close evidence and the creator with current read access (404 unreadable, 403 readable non-creator). Bound keys are tenant/Session/actor scoped. Replay returns the current visible Session without repeating the mutation; a deleted Session returns 404. The permanent close fence is preserved and no Harness or Runtime call is made. */
407
+ /** @description Synchronously restores an archived Session to closed. Workspace-bound Sessions require completed reliable-close evidence and the Session's recorded owner with current read access (404 unreadable, 403 readable non-owner). Bound keys are tenant/Session/actor scoped. Replay returns the current visible Session without repeating the mutation; a deleted Session returns 404. The permanent close fence is preserved and no Harness or Runtime call is made. */
392
408
  post: operations["unarchiveWebShellSession"];
393
409
  delete?: never;
394
410
  options?: never;
@@ -528,14 +544,14 @@ export interface components {
528
544
  /** @default false */
529
545
  actions: boolean;
530
546
  /**
531
- * @description True when the caller may submit later Turns of this Workspace-bound Session: the deployment enables Workspace files, the caller created the Session and currently holds Workspace read and create grants on a registry row whose state is ACTIVE and still carries the Workspace generation and storage identity the Session was bound to, and the Session is an active, undeleted qwen-code Session on the frozen execution profile. Cancelling only aborts work that is already running, so the creator may cancel a running Turn even when this is false, as long as they can still read the Workspace and the deployment still enables Workspace files. False for every other caller and for unbound Sessions, which do not use it.
547
+ * @description True when the caller may submit later Turns of this Workspace-bound Session or rename it: the deployment enables Workspace files, the caller holds the OPERATOR role on a Workspace registry row whose state is ACTIVE and still backs the Session's binding, the actor recorded by the Workspace create command keeps OPERATOR or above, and the Session is an active qwen-code Session on the frozen execution profile. Cancelling only aborts work already running, so an OPERATOR caller may cancel a running Turn even when this is false; the capability does not gate cancellation. False for every other caller and for unbound Sessions, which do not use it.
532
548
  * @default false
533
549
  */
534
550
  workspaceTurns: boolean;
535
551
  tasks: boolean;
536
552
  artifacts: boolean;
537
553
  /**
538
- * @description Deployment support for close independently of archive/delete. Admission also requires creator ownership and current read access for a bound Session.
554
+ * @description Deployment support for close independently of archive/delete. Admission also requires Session ownership and current read access for a bound Session.
539
555
  * @default false
540
556
  */
541
557
  sessionClose?: boolean;
@@ -687,7 +703,7 @@ export interface components {
687
703
  * @default false
688
704
  */
689
705
  workspaceContext: boolean;
690
- /** @description Supports authorized Workspace discovery, Session creation, and saved binding read-back. This capability does not advertise execution readiness. Deployments may separately opt in to an initial Workspace Read/Write/Edit Turn at creation; the Session creator may submit and cancel later Turns under the same opt-in, while close follows its separate capability and lifecycle admission; archive, delete and unarchive follow their separate retention capabilities after reliable Workspace close. */
706
+ /** @description Supports authorized Workspace discovery, Session creation, and saved binding read-back. This capability does not advertise execution readiness. Deployments may separately opt in to an initial Workspace Read/Write/Edit Turn at creation; callers holding the OPERATOR role may submit later Turns or rename under the same opt-in while the registry row stays ACTIVE and still backs the Session's binding and the actor recorded by the Workspace create command keeps OPERATOR or above, and may cancel a running Turn (its delivery re-checks no grants), while close follows its separate capability and lifecycle admission; archive, delete and unarchive follow their separate retention capabilities after reliable Workspace close. */
691
707
  workspaceBinding: boolean;
692
708
  };
693
709
  /** @description Same authorized explicit default as default_workspace, including when outside this page; null if absent or not creatable. A non-null default is active and has canCreateSession=true. */
@@ -759,6 +775,8 @@ export interface components {
759
775
  sessionId: string;
760
776
  /** @enum {unknown} */
761
777
  type: "create_session" | "submit_input" | "cancel" | "action_response" | "close" | "archive" | "delete" | "task_cancel";
778
+ /** @description Task that a task_cancel operation targets. */
779
+ taskId?: string;
762
780
  /** @enum {unknown} */
763
781
  status: "pending" | "running" | "completed" | "failed" | "cancelled" | "recovery_blocked";
764
782
  /** @enum {unknown} */
@@ -767,10 +785,10 @@ export interface components {
767
785
  deliveryState: "pending" | "leased" | "confirmed" | "blocked";
768
786
  receiptId?: string;
769
787
  actionResolution?: components["schemas"]["WebShellActionResolution"];
770
- /** @description Reason a durable response or task cancellation failed. Action response failures come from the original committed Action, or a definitive invalid response. Workspace close recovery_blocked reports original resource identity or unsettled execution; the Session remains closing. */
788
+ /** @description Reason a durable response or task cancellation failed. Action response failures come from the original committed Action, or a definitive invalid response. Task cancel failures are task_already_settled (the run ended before the stop request was recorded), task_action_unavailable and task_not_found; a recovery_blocked task cancel reports task_cancel_unconfirmed. Workspace close recovery_blocked reports original resource identity or unsettled execution; the Session remains closing. */
771
789
  failureCode?: string;
772
790
  replayed: boolean;
773
- } & (unknown & unknown & unknown & unknown);
791
+ } & (unknown & unknown & unknown & unknown & unknown);
774
792
  WebShellQuestionAction: {
775
793
  actionId: string;
776
794
  /** Format: uuid */
@@ -894,7 +912,7 @@ export interface components {
894
912
  */
895
913
  TaskRuntimeState: "unbound" | "provisioning" | "ready" | "draining" | "lost";
896
914
  /**
897
- * @description Actions the task supports now, the same for every caller. cancel: the cancel route accepts a new command for this task; whether a caller may use it is an authorization check (403 on the cancel route). send_input: reserved for a later capability route. read_output: the task events route returns output events for this task to any caller that can read it. read_output does not change during the task's life, and a task without it produces no output events: its output goes only to Artifacts, so the events route never filters out events that exist.
915
+ * @description Actions the task supports now, the same for every caller. cancel: the cancel route accepts a new command for this task (since 1.40, child_agent tasks in pending, running, waiting or degraded, in an active Session); whether a caller may use it is an authorization check (403 on the cancel route). send_input: reserved for a later capability route. read_output: the task events route returns output events for this task to any caller that can read it. read_output does not change during the task's life, and a task without it produces no output events: its output goes only to Artifacts, so the events route never filters out events that exist.
898
916
  * @enum {string}
899
917
  */
900
918
  TaskActionCapability: "cancel" | "send_input" | "read_output";
@@ -983,6 +1001,14 @@ export interface components {
983
1001
  /** @default 20 */
984
1002
  limit?: number;
985
1003
  };
1004
+ WebShellTaskCancelRequest: {
1005
+ /** @description Trace correlation only; excluded from the request digest, so a retry with another requestId still replays. A header-safe value (1 to 128 visible ASCII characters) is echoed as X-Request-Id; any other value is replaced by a server-chosen id. */
1006
+ requestId?: string | null;
1007
+ /** Format: uuid */
1008
+ sessionId: string;
1009
+ taskId: string;
1010
+ idempotencyKey: string;
1011
+ };
986
1012
  /** @description state_changed, output or artifact. The set is open: a later minor version may add types and optional fields. Clients ignore unknown optional fields and unknown types, while still checkpointing event cursors; strict validation against an older minor response schema is not supported. Existing fields forbidden for a known type cannot be repurposed on that type. */
987
1013
  TaskEventType: string;
988
1014
  ToolResultPreview: {
@@ -1532,7 +1558,7 @@ export interface operations {
1532
1558
  };
1533
1559
  400: components["responses"]["BadRequest"];
1534
1560
  401: components["responses"]["Unauthorized"];
1535
- /** @description Responding requires the Session creator (action_forbidden). A Session with no recorded creator and no recorded create command (anonymous open-mode creation, or a Session created before the V40 migration that also has no Workspace creation record) answers to any caller in its tenant, matching its read ACL. The tenant filter's 403 actor_scope_mismatch also applies on this route. */
1561
+ /** @description Responding requires the Session's recorded owner or a Workspace OPERATOR (action_forbidden). An unbound Session with no recorded creator and no recorded create command (anonymous open-mode creation, or an unbound Session created before the V40 migration that also has no Workspace creation record) answers to any caller in its tenant, matching its read ACL; a bound Session with no recorded owner answers through the create-command actor recorded for it, or through the Workspace role arm. The tenant filter's 403 actor_scope_mismatch also applies on this route. */
1536
1562
  403: components["responses"]["Forbidden"];
1537
1563
  /** @description Unknown or unreadable Session (session_not_found), or unknown Action (action_not_found). */
1538
1564
  404: components["responses"]["NotFound"];
@@ -1748,6 +1774,37 @@ export interface operations {
1748
1774
  413: components["responses"]["PayloadTooLarge"];
1749
1775
  };
1750
1776
  };
1777
+ cancelWebShellTask: {
1778
+ parameters: {
1779
+ query?: never;
1780
+ header?: never;
1781
+ path?: never;
1782
+ cookie?: never;
1783
+ };
1784
+ requestBody: {
1785
+ content: {
1786
+ "application/json": components["schemas"]["WebShellTaskCancelRequest"];
1787
+ };
1788
+ };
1789
+ responses: {
1790
+ /** @description Same authorized task cancellation semantics as the public API: key validation, current access, idempotent replay, then new-request capability, Session, task and storage-migration checks (409 workspace_unavailable under a migration fence). Replay returns the same operation and latest durable state. 202 is durable admission, completed is authority acceptance, and neither proves physical stop. Admission requires no other open operation on the Session (409 session_operation_active), as on the lifecycle routes. A requestId in the body becomes the response's X-Request-Id and stays out of the request digest. */
1791
+ 202: {
1792
+ headers: {
1793
+ "X-Request-Id": components["headers"]["RequestId"];
1794
+ [name: string]: unknown;
1795
+ };
1796
+ content: {
1797
+ "application/json": components["schemas"]["WebShellCommandOperation"];
1798
+ };
1799
+ };
1800
+ 400: components["responses"]["BadRequest"];
1801
+ 401: components["responses"]["Unauthorized"];
1802
+ 403: components["responses"]["Forbidden"];
1803
+ 404: components["responses"]["NotFound"];
1804
+ 409: components["responses"]["Conflict"];
1805
+ 413: components["responses"]["PayloadTooLarge"];
1806
+ };
1807
+ };
1751
1808
  getWebShellToolResult: {
1752
1809
  parameters: {
1753
1810
  query?: never;
@@ -12,11 +12,12 @@ export interface ManagedActionsState {
12
12
  /** Sending an answer failed; the approval is shown again. */
13
13
  answerError?: unknown;
14
14
  /**
15
- * The service refused an answer as creator-only. That is a fact about the
16
- * viewer and the Session, not about one Action, so it outlives the refused
17
- * Action, covers every later approval the same Session raises, and survives
18
- * leaving that Session and coming back. It is remembered per mount: a reload
19
- * or reopening the panel starts clean.
15
+ * The service refused an answer under the owner-or-Workspace-operator
16
+ * rule. That refusal is a fact about the viewer's Workspace role row,
17
+ * which an operator can raise while the page stays open, so the latch
18
+ * covers every later approval the same Session raises and survives
19
+ * leaving that Session and coming back — but `retry()` drops it and
20
+ * re-probes instead of treating one 403 as permanent for the mount.
20
21
  */
21
22
  respondForbidden: boolean;
22
23
  respond(actionId: string, optionId: string): Promise<void>;
@@ -89,6 +89,12 @@ interface WebShellSidebarProps {
89
89
  onNewSession: (workspaceCwd?: string) => Promise<boolean> | boolean;
90
90
  onNewStandaloneSession?: () => Promise<boolean> | boolean;
91
91
  onLoadSession: (sessionId: string, workspaceCwd?: string) => Promise<void> | void;
92
+ /**
93
+ * Opens a session listed by a fan-out host group (#13727): the caller
94
+ * focuses that host in-app and loads the session there. When absent, the
95
+ * groups fall back to full navigation via `openHostedWorkspace`.
96
+ */
97
+ onOpenHostSession?: (origin: string, sessionId: string, workspaceCwd?: string) => void;
92
98
  onSelectCurrentSession?: () => void;
93
99
  onSessionRenameConfirmed?: (workspaceCwd: string | undefined, sessionId: string, displayName: string) => void;
94
100
  /**
@@ -156,4 +162,4 @@ interface WebShellSidebarProps {
156
162
  onLoadStandaloneSession?: (sessionId: string) => Promise<void> | void;
157
163
  onStandaloneNotice?: (message: string) => void;
158
164
  }
159
- export declare function WebShellSidebar({ collapsed, layout, activePage, containerWidth, onOpenHome, onCollapsedChange, onOpenSettings, onOpenAgents, onOpenPlugins, onOpenChannels, onOpenLive, onLiveVoiceSlotChange, onOpenManagedSessions, onOpenDaemonStatus, onOpenScheduledTasks, onOpenWorkflows, onOpenGoals, onOpenSessions, canOpenSessionsOverview, onOpenWorkspacesOverview, onOpenSplitView, canOpenSplitView, onNewSession, onNewStandaloneSession, onLoadSession, onSelectCurrentSession, onSessionRenameConfirmed, onSessionsDeleted, onError, theme, onThemeChange, mobileOpen, onMobileClose, selectedWorkspaceCwd, onSelectWorkspace, onOpenGitDiff, onOpenCommit, onOpenAddWorkspace, workspaces: providedWorkspaces, lockedWorkspaceCwd, lockedWorkspace: lockedWorkspaceOptions, branding, primaryNav: primaryNavOptions, showSessionSourceSwitch, showLive, hideProjectHeader, sessionActions: sessionActionsOptions, footer, workspaceOverview, onOpenWorkspaceManagement, onNewWorktreeSession, projectFeaturesEnabled, onLoadStandaloneSession, onStandaloneNotice, }: WebShellSidebarProps): import("react/jsx-runtime").JSX.Element;
165
+ export declare function WebShellSidebar({ collapsed, layout, activePage, containerWidth, onOpenHome, onCollapsedChange, onOpenSettings, onOpenAgents, onOpenPlugins, onOpenChannels, onOpenLive, onLiveVoiceSlotChange, onOpenManagedSessions, onOpenDaemonStatus, onOpenScheduledTasks, onOpenWorkflows, onOpenGoals, onOpenSessions, canOpenSessionsOverview, onOpenWorkspacesOverview, onOpenSplitView, canOpenSplitView, onNewSession, onNewStandaloneSession, onLoadSession, onOpenHostSession, onSelectCurrentSession, onSessionRenameConfirmed, onSessionsDeleted, onError, theme, onThemeChange, mobileOpen, onMobileClose, selectedWorkspaceCwd, onSelectWorkspace, onOpenGitDiff, onOpenCommit, onOpenAddWorkspace, workspaces: providedWorkspaces, lockedWorkspaceCwd, lockedWorkspace: lockedWorkspaceOptions, branding, primaryNav: primaryNavOptions, showSessionSourceSwitch, showLive, hideProjectHeader, sessionActions: sessionActionsOptions, footer, workspaceOverview, onOpenWorkspaceManagement, onNewWorktreeSession, projectFeaturesEnabled, onLoadStandaloneSession, onStandaloneNotice, }: WebShellSidebarProps): import("react/jsx-runtime").JSX.Element;
@@ -10,6 +10,14 @@ export interface WorkspaceHeaderActionsContext {
10
10
  }
11
11
  interface WorkspaceSectionProps {
12
12
  workspace: DaemonWorkspaceCapability;
13
+ /**
14
+ * localStorage seed for the expansion/collapsed-group preferences,
15
+ * defaulting to the workspace id. Multi-host renderers pass an
16
+ * origin-prefixed id so two daemons hosting the same workspace id
17
+ * never share a preference; single-host callers leave it unset and
18
+ * keep the keys they always had.
19
+ */
20
+ storageKey?: string;
13
21
  remote?: boolean;
14
22
  renderHeader?: (expanded: boolean) => ReactNode;
15
23
  hideHeader?: boolean;
@@ -117,5 +125,5 @@ interface WorkspaceSectionProps {
117
125
  /** Commit entry for the same picker; the row still opens without it. */
118
126
  onOpenCommit?: (workspaceCwd: string) => void;
119
127
  }
120
- export declare function WorkspaceSection({ workspace, remote, renderHeader, hideHeader, client, reloadToken, untrustedLabel, readOnlyLabel, trustToOpenLabel, noSessionsLabel, loadErrorLabel, organizationEnabled, sessionCatalogRequestsEnabled, sessionGroupCatalog, sessionLiveStateEnabled, sourceType, channelGroupingEnabled, ungroupedLabel, searchQuery, expanded: controlledExpanded, autoExpandKey, forceAutoExpand, onExpandedChange, renderSessions, renderSession, pendingSession, mapSession, showSessionDetails, headerActions, overviewEnabled, overviewMenuOpen, overviewItems, gitBranchWanted, sessionStats, onRenameGroup, onDeleteGroup, renameGroupLabel, deleteGroupLabel, groupActionsDisabled, excludePinned, limitSessions, isPinnedSectionMember, onOpenPathLocally, onOpenTerminalLocally, onOpenGitDiff, onOpenCommit, }: WorkspaceSectionProps): import("react/jsx-runtime").JSX.Element;
128
+ export declare function WorkspaceSection({ workspace, storageKey, remote, renderHeader, hideHeader, client, reloadToken, untrustedLabel, readOnlyLabel, trustToOpenLabel, noSessionsLabel, loadErrorLabel, organizationEnabled, sessionCatalogRequestsEnabled, sessionGroupCatalog, sessionLiveStateEnabled, sourceType, channelGroupingEnabled, ungroupedLabel, searchQuery, expanded: controlledExpanded, autoExpandKey, forceAutoExpand, onExpandedChange, renderSessions, renderSession, pendingSession, mapSession, showSessionDetails, headerActions, overviewEnabled, overviewMenuOpen, overviewItems, gitBranchWanted, sessionStats, onRenameGroup, onDeleteGroup, renameGroupLabel, deleteGroupLabel, groupActionsDisabled, excludePinned, limitSessions, isPinnedSectionMember, onOpenPathLocally, onOpenTerminalLocally, onOpenGitDiff, onOpenCommit, }: WorkspaceSectionProps): import("react/jsx-runtime").JSX.Element;
121
129
  export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Icon + short name for one daemon host: the page origin reads as "Local",
3
+ * anything else shows its URL host. Shared by the sidebar host groups and
4
+ * the composer workspace picker so every surface names hosts identically.
5
+ */
6
+ export declare function HostLabel({ origin }: {
7
+ origin: string;
8
+ }): import("react/jsx-runtime").JSX.Element;
@@ -3,9 +3,16 @@
3
3
  * saved there is nothing to tell apart, so the plain list stays unlabeled.
4
4
  */
5
5
  export declare function WorkspaceHostHeading(): import("react/jsx-runtime").JSX.Element | null;
6
+ export type OpenHostSessionHandler = (origin: string, sessionId: string, workspaceCwd?: string) => void;
6
7
  /**
7
- * Saved projects on the other hosts, grouped by host below the live list.
8
- * Only the connected host is live; choosing one of these reloads the page
9
- * against its host.
8
+ * Live projects on the other hosts, grouped by host among the focused one's
9
+ * rank (#13727): when `rankOf` is provided, every group carries its own
10
+ * flex order inside the sidebar's host container, so a focused switch keeps
11
+ * all groups in place. Each group polls its own daemon; a host that drops
12
+ * offline or rejects the saved credential keeps its last known projects
13
+ * with a muted status hint.
10
14
  */
11
- export declare function OtherHostProjects(): import("react/jsx-runtime").JSX.Element | null;
15
+ export declare function OtherHostProjects({ onOpenHostSession, rankOf, }: {
16
+ onOpenHostSession?: OpenHostSessionHandler;
17
+ rankOf?: (origin: string) => number;
18
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * Compact label naming the host a chat runs on, with the working directory in
3
3
  * its tooltip. Hidden until a project can live on more than one host.
4
+ * `hostOrigin` names the ACTIVE session's host on multi-daemon pages; without
5
+ * it the page daemon (the behavior before fan-out) decides.
4
6
  */
5
- export declare function WorkspaceLocation({ cwd }: {
7
+ export declare function WorkspaceLocation({ cwd, hostOrigin, }: {
6
8
  cwd?: string;
9
+ hostOrigin?: string;
7
10
  }): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { ReactNode } from 'react';
7
+ export interface FocusHostTarget {
8
+ origin: string;
9
+ /** Preselect this workspace on the new host (by id), or clear otherwise. */
10
+ workspaceId?: string;
11
+ }
12
+ /**
13
+ * One-shot intent carried across a focused-host switch: the remounted app
14
+ * performs it against the NEW host's provider (composer create on a picked
15
+ * workspace, or open an existing session). Kept here because this provider
16
+ * sits outside the interactive provider's remount boundary.
17
+ */
18
+ export interface HostHandoff {
19
+ kind: 'create' | 'open';
20
+ /** The focused host this intent belongs to — stale intents are dropped. */
21
+ origin: string;
22
+ workspaceCwd?: string;
23
+ sessionId?: string;
24
+ /** Composer text to restore on the new host (attachments cannot carry). */
25
+ draftText?: string;
26
+ }
27
+ export interface DaemonTargetController {
28
+ /** The focused daemon origin (page origin when no `?daemon=` is active). */
29
+ activeOrigin: string;
30
+ /** Origins the current document may open network connections to. */
31
+ coveredOrigins: ReadonlySet<string>;
32
+ coversOrigin(origin: string): boolean;
33
+ /**
34
+ * Focus another CSP-covered host: remounts the interactive provider at the
35
+ * new origin and rewrites `?daemon=` (+ optional `?workspace=`) in place.
36
+ * Never navigates; throws on an uncovered origin — callers must route those
37
+ * through the navigation-based connect flow instead.
38
+ */
39
+ focusHost(target: FocusHostTarget): void;
40
+ /** Token for the focused host, refreshed when the focused origin (or any
41
+ * controller dependency) changes; a token edit alone does not re-key it. */
42
+ activeToken: string | undefined;
43
+ /**
44
+ * Focus another host and hand an intent to the remounted app. The app
45
+ * drains it via `takePendingHandoff` once the new provider is connected
46
+ * (create a session in that workspace / open that session there).
47
+ */
48
+ focusHostWithHandoff(target: FocusHostTarget, handoff: HostHandoff): void;
49
+ /** Pending intent from the latest focus switch; consumed exactly once. */
50
+ pendingHandoff: HostHandoff | undefined;
51
+ takePendingHandoff(): HostHandoff | undefined;
52
+ }
53
+ export declare function DaemonTargetProvider({ children, }: {
54
+ children: ReactNode;
55
+ }): ReactNode;
56
+ export declare function useDaemonTarget(): DaemonTargetController;
57
+ /** Optional-context variant for components rendered both inside and outside
58
+ * the standalone tree (tests, embedded shells without the provider). */
59
+ export declare function useDaemonTargetOptional(): DaemonTargetController | undefined;
60
+ /**
61
+ * Intercept same-origin anchor clicks that point at another connected host
62
+ * (#13727): a transcript/session link with `?daemon=B` would otherwise
63
+ * hard-reload the document, losing all sidebar and composer state. When the
64
+ * target is inside the CSP-covered set the click becomes an in-app focus
65
+ * switch (open that session there); anything uncovered keeps the default
66
+ * navigation, which still re-serves the shell widened for the host.
67
+ */
68
+ export declare function useInterceptHostLinks(): void;
69
+ /**
70
+ * Keep the URL's `fanout` params equal to the saved-host set minus the
71
+ * focused daemon (which `?daemon=` already covers). Runs on mount, on host
72
+ * catalog changes, on focus switches, on cross-tab storage writes, and when
73
+ * the tab regains focus (settings flows that edited catalogs in place).
74
+ * `replaceState` only — the current document's CSP is unaffected.
75
+ */
76
+ export declare function useFanoutUrlSync(): void;
@@ -1,4 +1,20 @@
1
1
  export declare function getDaemonBaseUrl(): string;
2
+ /**
3
+ * Repeated `?fanout=` values validated into daemon origins. Fanout params
4
+ * name the hosts this page connects to simultaneously (multi-daemon view,
5
+ * #13727): the served CSP covers exactly the `daemon` + `fanout` set, so a
6
+ * focused-host switch inside that set never reloads the document. The page
7
+ * origin is dropped — `'self'` already covers it.
8
+ */
9
+ export declare function getFanoutOrigins(): string[];
10
+ /**
11
+ * Point the URL's `fanout` params at exactly `origins`, preserving every
12
+ * other param. `replaceState` only: this cannot widen the CURRENT document's
13
+ * CSP (the header is fixed at load) — it keeps the NEXT load in sync, so the
14
+ * host set stays covered without a reload. A newly-connected host therefore
15
+ * navigates once before it can be used; every switch after that is in-app.
16
+ */
17
+ export declare function syncFanoutParams(origins: readonly string[]): void;
2
18
  /**
3
19
  * Whether host-local affordances are safe to offer here: true only when this
4
20
  * page was served from a loopback host AND the shell is not pointed at a
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { DaemonClient } from '@qwen-code/sdk/daemon';
7
+ import type { DaemonCapabilities } from '@qwen-code/sdk/daemon';
8
+ export type HostConnectionStatus = 'connecting' | 'online' | 'offline' | 'unauthorized';
9
+ /**
10
+ * Stable read-only client for `origin`. Recreated only when the stored
11
+ * per-origin token changed; a client whose daemon vanished stays online as an
12
+ * instance (its next request fails) and its entry is dropped when the host
13
+ * loses its last subscriber.
14
+ */
15
+ export declare function getHostClient(origin: string): DaemonClient;
16
+ export declare const HOST_FANOUT_POLL_MS = 30000;
17
+ export interface HostCapabilitiesState {
18
+ workspaces: DaemonCapabilities['workspaces'];
19
+ status: HostConnectionStatus;
20
+ /** Bumps on every content-changed refresh so poll consumers resubscribe. */
21
+ generation: number;
22
+ }
23
+ /**
24
+ * Live `capabilities().workspaces` + connection status for one fan-out host.
25
+ * Shares the store's single poll round with every other consumer; the last
26
+ * successful payload survives later failures (status flips to
27
+ * offline/unauthorized but the rows keep rendering) and hosts are always
28
+ * polled with their own per-origin client.
29
+ */
30
+ export declare function useHostCapabilities(origin: string): HostCapabilitiesState & {
31
+ refresh: () => void;
32
+ };
33
+ /**
34
+ * The single ordered host set both the sidebar fan-out and App composers
35
+ * render from: every saved workspace host and connected remote origin, minus
36
+ * the focused daemon (its own UI comes from the interactive provider), plus
37
+ * the page origin when focused remote — the "way back" group. Memoized on
38
+ * content so consumers can pass it straight into `useHostFanout`.
39
+ */
40
+ export declare function useFanoutOrigins(): string[];
41
+ /**
42
+ * Live connection state + a client for every `origins` entry, drawn from the
43
+ * shared per-origin store: subscribing here never adds a second poller — the
44
+ * composer picker and the sidebar groups observe the same rounds. Failed
45
+ * hosts keep their last-known snapshot; hosts that lose their last
46
+ * subscriber are dropped from the client pool.
47
+ */
48
+ export declare function useHostFanout(origins: readonly string[]): {
49
+ clientsByOrigin: ReadonlyMap<string, DaemonClient>;
50
+ statusByOrigin: ReadonlyMap<string, HostConnectionStatus>;
51
+ workspacesByOrigin: ReadonlyMap<string, DaemonCapabilities['workspaces'] | undefined>;
52
+ refreshAll: () => void;
53
+ };
@@ -1,7 +1,10 @@
1
+ export declare const REMOTE_CONNECTIONS_CHANGE_EVENT = "qwen-remote-connections";
1
2
  export declare function formatOriginHost(origin: string): string;
2
3
  export declare function readRemoteConnections(): string[];
3
4
  export declare function rememberRemoteConnection(origin: string): void;
4
5
  export declare function forgetRemoteConnection(origin: string): string[];
6
+ /** Saved connection origins, kept in sync with catalog updates. */
7
+ export declare function useRemoteConnections(): string[];
5
8
  export declare function isRemoteConnectionKnown(origin: string): boolean;
6
9
  /**
7
10
  * Remote computers offered as a workspace location: the persisted catalog plus