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

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 (37) hide show
  1. package/dist/{agents-route-DAa1HKQE.js → agents-route-CufkSNnD.js} +2 -2
  2. package/dist/daemon-react-sdk.js +1 -1
  3. package/dist/{index-zUj3SlrB.js → index-Deg_ZdBo.js} +50292 -48857
  4. package/dist/index.js +3 -3
  5. package/dist/sw.js +1 -1
  6. package/dist/{toolNames-B_KiYcXs.js → toolNames-Co4lBbW-.js} +1564 -1472
  7. package/dist/transcript.js +3815 -3757
  8. package/dist/types/components/ChatEditor.d.ts +4 -7
  9. package/dist/types/components/QueuedPromptDisplay.d.ts +4 -1
  10. package/dist/types/components/WorkspaceSelector.d.ts +9 -1
  11. package/dist/types/components/artifacts/artifactUtils.d.ts +9 -0
  12. package/dist/types/components/managed/ManagedSessionCwdControl.d.ts +9 -0
  13. package/dist/types/components/managed/generated/managed-agent-api.d.ts +81 -17
  14. package/dist/types/components/managed/java-managed-agent-client.d.ts +2 -1
  15. package/dist/types/components/managed/managed-agent-provider.d.ts +18 -1
  16. package/dist/types/components/managed/managed-request-error.d.ts +6 -0
  17. package/dist/types/components/managed/use-managed-actions.d.ts +6 -5
  18. package/dist/types/components/managed/use-managed-cwd-change.d.ts +21 -0
  19. package/dist/types/components/managed/use-managed-session.d.ts +15 -1
  20. package/dist/types/components/sidebar/WebShellSidebar.d.ts +7 -1
  21. package/dist/types/components/sidebar/WorkspaceSection.d.ts +9 -1
  22. package/dist/types/components/workspaces/HostLabel.d.ts +8 -0
  23. package/dist/types/components/workspaces/WorkspaceHostProjects.d.ts +11 -4
  24. package/dist/types/components/workspaces/WorkspaceLocation.d.ts +4 -1
  25. package/dist/types/config/daemon-target.d.ts +76 -0
  26. package/dist/types/config/daemon.d.ts +16 -0
  27. package/dist/types/config/host-fanout.d.ts +53 -0
  28. package/dist/types/config/remote-connections.d.ts +3 -0
  29. package/dist/types/config/workspace-hosts.d.ts +7 -0
  30. package/dist/types/daemon/session/types.d.ts +9 -1
  31. package/dist/types/hooks/useQueuedPrompts.d.ts +2 -0
  32. package/dist/types/trajectory/types.d.ts +1 -0
  33. package/dist/types/trajectory/useTrajectoryWindow.d.ts +21 -36
  34. package/dist/types/trajectory/window-messages.d.ts +9 -0
  35. package/dist/types/trajectory/window-messages.transcript-stub.d.ts +7 -0
  36. package/dist/types/utils/workspace.d.ts +10 -0
  37. package/package.json +1 -1
@@ -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
@@ -1,11 +1,18 @@
1
1
  import type { DaemonWorkspaceCapability } from '@qwen-code/sdk/daemon';
2
2
  export declare const WorkspaceHostsEnabled: import("react").Context<boolean>;
3
+ export declare const WORKSPACE_HOSTS_CHANGE_EVENT = "qwen-workspace-hosts";
3
4
  export interface WorkspaceHost {
4
5
  origin: string;
5
6
  workspaces: Pick<DaemonWorkspaceCapability, 'id' | 'cwd' | 'displayName'>[];
6
7
  }
7
8
  export declare function readWorkspaceHosts(): WorkspaceHost[];
8
9
  export declare function rememberWorkspaceHost(origin: string, workspaces: WorkspaceHost['workspaces']): void;
10
+ /**
11
+ * Drop a host from the saved workspace catalog, e.g. when its connection is
12
+ * removed from Settings: the fan-out group must disappear in the same tab,
13
+ * not just on the next load.
14
+ */
15
+ export declare function forgetWorkspaceHost(origin: string): void;
9
16
  /** Saved hosts, kept in sync with catalog updates from this and other tabs. */
10
17
  export declare function useWorkspaceHosts(): WorkspaceHost[];
11
18
  export declare function openHostedWorkspace(origin: string, workspaceId?: string): void;
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import type { ReactNode } from 'react';
7
- import type { CreateSessionRequest, DaemonBranchSessionRequest, DaemonCapabilities, DaemonBackgroundTurn, DaemonEvent, DaemonApprovalMode, DaemonApprovalModeResult, DaemonAvailableCommand, DaemonForkSessionResult, DaemonInputAnnotation, DaemonSessionBtwResult, DaemonSessionGenerationEvent, DaemonSessionAttachmentReference, DaemonSessionAttachmentData, DaemonMidTurnMessageResult, DaemonMidTurnMessagesResult, DaemonRemoveMidTurnMessageResult, DaemonPendingPromptsResult, DaemonRemovePendingPromptResult, DaemonSessionContextStatus, DaemonSessionSavedWorkflowDetail, DaemonSessionContextUsageStatus, DaemonSessionRecapResult, DaemonRewindResult, DaemonRewindSnapshotInfo, DaemonSession, DaemonSessionSummary, DaemonSessionSupportedCommandsStatus, DaemonSessionTaskWithWorkflowStatus, DaemonSessionTasksStatus, DaemonSessionWorkflowTaskStatus, DaemonSessionWorkflowTasksStatus, DaemonSessionStatsStatus, DaemonSessionArtifactsEnvelope, DaemonSessionArtifactInput, DaemonSessionArtifactMutationResult, SessionSourceInput, SessionSourcesResult, SessionSourceUpsertResult, SessionSourceRemoveResult, DaemonSkillToggleMutation, DaemonShellCommandResult, DaemonTranscriptBlock, DaemonTranscriptStore, DaemonWorkspaceGitStatus, DaemonWorkspaceProvidersStatus, DaemonStandaloneCreationRecovery, DaemonStandaloneWorkingDirectory, HeartbeatResult, GoalControlRequest, GoalSnapshotV2, GoalStateResponse, PermissionResponse, PromptContentBlock, PromptResult, ReasoningSelection, SessionMetadataResult, SetModelResult } from '@qwen-code/sdk/daemon';
7
+ import type { CreateSessionRequest, DaemonBranchSessionRequest, DaemonCapabilities, DaemonBackgroundTurn, DaemonEvent, DaemonApprovalMode, DaemonApprovalModeResult, DaemonAvailableCommand, DaemonForkSessionResult, DaemonInputAnnotation, DaemonSessionBtwResult, DaemonSessionGenerationEvent, DaemonSessionAttachmentReference, DaemonSessionAttachmentData, DaemonMidTurnMessageResult, DaemonMidTurnMessagesResult, DaemonRemoveMidTurnMessageResult, DaemonSendMidTurnMessagesNowResult, DaemonPendingPromptsResult, DaemonRemovePendingPromptResult, DaemonSessionContextStatus, DaemonSessionSavedWorkflowDetail, DaemonSessionContextUsageStatus, DaemonSessionRecapResult, DaemonRewindResult, DaemonRewindSnapshotInfo, DaemonSession, DaemonSessionSummary, DaemonSessionSupportedCommandsStatus, DaemonSessionTaskWithWorkflowStatus, DaemonSessionTasksStatus, DaemonSessionWorkflowTaskStatus, DaemonSessionWorkflowTasksStatus, DaemonSessionStatsStatus, DaemonSessionArtifactsEnvelope, DaemonSessionArtifactInput, DaemonSessionArtifactMutationResult, SessionSourceInput, SessionSourcesResult, SessionSourceUpsertResult, SessionSourceRemoveResult, DaemonSkillToggleMutation, DaemonShellCommandResult, DaemonTranscriptBlock, DaemonTranscriptStore, DaemonWorkspaceGitStatus, DaemonWorkspaceProvidersStatus, DaemonStandaloneCreationRecovery, DaemonStandaloneWorkingDirectory, HeartbeatResult, GoalControlRequest, GoalSnapshotV2, GoalStateResponse, PermissionResponse, PromptContentBlock, PromptResult, ReasoningSelection, SessionMetadataResult, SetModelResult } from '@qwen-code/sdk/daemon';
8
8
  export type DaemonConnectionStatus = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';
9
9
  export interface DaemonSessionOwnerSnapshot {
10
10
  isCurrent(): boolean;
@@ -489,6 +489,14 @@ export interface DaemonSessionActions {
489
489
  onAdmissionStarted?: () => void;
490
490
  }): Promise<DaemonMidTurnMessageResult>;
491
491
  removeMidTurnMessage(messageId: string, opts?: PendingPromptActionOptions): Promise<DaemonRemoveMidTurnMessageResult>;
492
+ /**
493
+ * Ask the daemon to deliver the queued mid-turn messages now, cutting short
494
+ * a model response that a foreground turn is streaming, unless it has
495
+ * started a tool call.
496
+ * Pre-flight the daemon's `session_mid_turn_send_now` capability: older
497
+ * daemons lack the route.
498
+ */
499
+ sendMidTurnMessagesNow(opts?: PendingPromptActionOptions): Promise<DaemonSendMidTurnMessagesNowResult>;
492
500
  /**
493
501
  * Best-effort reconciliation snapshot (queue + delivery-state rings) from the
494
502
  * daemon. Resolves `undefined` (never throws/raises a notice) when there
@@ -70,6 +70,8 @@ export interface UseQueuedPromptsResult {
70
70
  enqueuePrompt: (text: string, images?: PromptImage[], files?: PromptFile[], onComplete?: () => void, inputAnnotations?: DaemonInputAnnotation[], onAdmitted?: () => void, submittedPrompt?: string) => boolean;
71
71
  removeQueuedPrompt: (id: number) => void;
72
72
  insertQueuedPrompt: (id: number) => Promise<void>;
73
+ /** Ask the daemon to deliver the queued mid-turn messages now. */
74
+ sendQueuedPromptNow: (id: number) => Promise<void>;
73
75
  editQueuedPrompt: (id: number) => Promise<void>;
74
76
  editLastQueuedPrompt: () => boolean;
75
77
  clearQueuedPrompts: () => boolean;
@@ -82,6 +82,7 @@ export interface TrajectoryRequestRow extends TrajectoryRowBase {
82
82
  /** Folded from the round's assistant block; absent when none carried it. */
83
83
  usage?: DaemonTurnUsage;
84
84
  recordId?: string;
85
+ executionId?: string;
85
86
  responseId?: string;
86
87
  promptId?: string;
87
88
  /** Set when a subagent issued the request. */
@@ -59,55 +59,40 @@ export type TrajectoryWindowFailure = {
59
59
  } | {
60
60
  kind: 'unreadable';
61
61
  message: string;
62
+ } | {
63
+ kind: 'expired' | 'protocol' | 'budget';
62
64
  };
65
+ export declare const TRAJECTORY_BOOKMARK_LIMIT = 64;
66
+ export declare const TRAJECTORY_CURSOR_BUDGET: number;
63
67
  export interface TrajectoryWindow {
64
68
  trajectory: Trajectory | undefined;
65
69
  status: 'idle' | 'loading' | 'ready' | 'error';
66
- /**
67
- * The newest page could not be read. The window already on screen, if any,
68
- * is kept.
69
- */
70
70
  error?: TrajectoryWindowFailure;
71
- /**
72
- * Pages read so far by the load under way, or held by the window once it
73
- * is ready. What the placeholder counts while the walk back is running.
74
- */
75
71
  loadedPages: number;
76
- /**
77
- * The session has history older than the window: the walk stopped at the
78
- * page cap, at a page the daemon gave no cursor for, or at an older page it
79
- * could not read.
80
- */
72
+ windowPages: number;
81
73
  truncated: boolean;
82
- /**
83
- * An older page could not be read, so the window stops just after it. The
84
- * newer pages are drawn; `refresh` is the retry.
85
- */
86
74
  olderFailure?: TrajectoryWindowFailure;
87
- /** Read the window again from the newest page. Also every retry. */
75
+ navigationError?: TrajectoryWindowFailure;
76
+ mode: 'latest' | 'history';
77
+ navigationVersion: number;
78
+ canRefresh: boolean;
79
+ canOlder: boolean;
80
+ canNewer: boolean;
81
+ historyReleased: boolean;
82
+ bookmarks: number;
88
83
  refresh: () => void;
84
+ older: () => void;
85
+ newer: () => void;
86
+ retry: () => void;
89
87
  }
90
88
  /**
91
- * Hold a window of one session's transcript and fold it into a trajectory.
92
- *
93
- * The pages are this view's own: paged replay is the only path that emits
94
- * timing frames, and the chat store is fed by the live stream and by bulk
95
- * replay, neither of which carries them. Reading here also keeps the window
96
- * contiguous by construction, which is what lets the projection pair a frame
97
- * with what it measured.
98
- *
99
- * A load walks back from the newest page by cursor, up to the page cap, and
100
- * the window lands once, whole, when the walk ends. Nothing is ever put in
101
- * front of rows already drawn: a list that grew upwards under the reader would
102
- * have to move its scroll offset, its keys, its selection and its focus in
103
- * step, and no part of that is observable outside a real browser.
104
- *
105
- * `refresh` rebuilds the window from the newest page rather than splicing into
106
- * it: page boundaries are chosen per request, so a fresh page and the held
107
- * ones overlap by an unknown amount and cannot be joined without dropping or
108
- * repeating records.
89
+ * Windows are contiguous cursor walks, committed whole. Only bookmarks survive
90
+ * a switch: replaying a saved cursor stays in its snapshot, whereas a read
91
+ * without one explicitly returns to the latest snapshot.
109
92
  */
110
93
  export declare function useTrajectoryWindow(loadPage: TrajectoryPageLoader | undefined, options?: {
111
94
  pageSize?: number;
112
95
  maxPages?: number;
96
+ bookmarkLimit?: number;
97
+ cursorBudget?: number;
113
98
  }): TrajectoryWindow;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ type WindowMessage = string | ((vars?: Record<string, string | number>) => string);
7
+ export declare const TRAJECTORY_WINDOW_MESSAGES_EN: Record<string, WindowMessage>;
8
+ export declare const TRAJECTORY_WINDOW_MESSAGES_ZH: Record<string, WindowMessage>;
9
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export declare const TRAJECTORY_WINDOW_MESSAGES_EN: {};
7
+ export declare const TRAJECTORY_WINDOW_MESSAGES_ZH: {};
@@ -14,6 +14,16 @@ export declare function workspaceBasename(cwd: string): string;
14
14
  export declare function sshWorkspaceLabel(ssh: NonNullable<DaemonWorkspaceCapability['ssh']>): string;
15
15
  export declare function workspaceLabel(workspace: Pick<DaemonWorkspaceCapability, 'cwd' | 'displayName' | 'ssh'>): string;
16
16
  export declare function workspaceLabelForCwd(cwd: string, workspaces: readonly Pick<DaemonWorkspaceCapability, 'cwd' | 'displayName' | 'ssh'>[] | undefined): string;
17
+ /**
18
+ * Suffix the parent directory onto labels that collide inside one list.
19
+ * Two daemons — or one daemon with two checkouts — frequently register the
20
+ * same basename (`qwen-code` everywhere); the menu must tell them apart by
21
+ * the workspace's own location, not only by tooltip or host badge.
22
+ */
23
+ export declare function disambiguateWorkspaceLabels<T extends {
24
+ label: string;
25
+ cwd: string;
26
+ }>(entries: readonly T[]): T[];
17
27
  /**
18
28
  * True when the daemon advertises more than one registered workspace — i.e. the
19
29
  * multi-workspace session surfaces (per-workspace labels/tags) should show.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwen-code/web-shell",
3
- "version": "0.25.1-preview.1",
3
+ "version": "0.25.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/QwenLM/qwen-code.git",