dsh-over-ssh 0.1.0 → 0.1.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.
- package/README.md +10 -10
- package/agents/agent-manifest.json +1 -1
- package/lib/client.js +363 -314
- package/lib/file-references.js +80 -35
- package/lib/fs.js +158 -75
- package/lib/index.js +4103 -3397
- package/lib/terminal-wrapper.js +9 -4
- package/lib/types/src/config.d.ts +80 -9
- package/lib/types/src/file-references.d.ts +0 -1
- package/lib/types/src/host/app/backend.d.ts +9 -1
- package/lib/types/src/host/app/recycle-bin/recycle-bin-contract.d.ts +0 -1
- package/lib/types/src/host/app/recycle-bin/recycle-bin-service.d.ts +0 -1
- package/lib/types/src/host/app/session-admin/session-admin-contract.d.ts +12 -1
- package/lib/types/src/host/app/session-admin/session-admin-service.d.ts +0 -1
- package/lib/types/src/host/app/transport/transport-selector.d.ts +0 -1
- package/lib/types/src/host/app/transport/transport-service.d.ts +0 -1
- package/lib/types/src/host/domain/capability.d.ts +0 -1
- package/lib/types/src/host/domain/errors.d.ts +0 -1
- package/lib/types/src/host/domain/roots/connection.d.ts +0 -1
- package/lib/types/src/host/domain/roots/root.d.ts +24 -9
- package/lib/types/src/host/domain/roots/session-roots.d.ts +0 -1
- package/lib/types/src/host/domain/roots/ssh-config.d.ts +0 -1
- package/lib/types/src/host/domain/session/session-admin.d.ts +0 -1
- package/lib/types/src/host/domain/transfer/recycle-bin.d.ts +0 -1
- package/lib/types/src/host/domain/transfer/transfer.d.ts +0 -1
- package/lib/types/src/host/infra/transport/agent/agent-installer.d.ts +0 -1
- package/lib/types/src/host/infra/transport/ssh/ssh2-transport.d.ts +0 -1
- package/lib/types/src/host/infra/transport/transport-base.d.ts +0 -1
- package/lib/types/src/host/infra/transport/transport.d.ts +16 -2
- package/lib/types/src/host/integration/agent/agent-preflight.d.ts +0 -1
- package/lib/types/src/host/integration/fs/file-reference-provider.d.ts +0 -1
- package/lib/types/src/host/integration/fs/fs-provider.d.ts +0 -2
- package/lib/types/src/host/integration/transfer/transfer-service.d.ts +0 -1
- package/lib/types/src/index.d.ts +23 -1
- package/lib/types/src/local-bridge-refs.d.ts +0 -1
- package/lib/types/src/local-bridge.d.ts +0 -1
- package/lib/types/src/shared/root-keys.d.ts +120 -0
- package/lib/types/src/wiring/helpers.d.ts +0 -1
- package/package.json +5 -3
- package/lib/types/src/client/controls.d.ts +0 -131
- package/lib/types/src/client/core/card-focus-trap.d.ts +0 -45
- package/lib/types/src/client/core/controls.d.ts +0 -164
- package/lib/types/src/client/core/latest.d.ts +0 -48
- package/lib/types/src/client/core/locale.d.ts +0 -38
- package/lib/types/src/client/core/message.d.ts +0 -37
- package/lib/types/src/client/core/panel-model.d.ts +0 -134
- package/lib/types/src/client/core/portal.d.ts +0 -266
- package/lib/types/src/client/core/remote.d.ts +0 -84
- package/lib/types/src/client/core/styles.d.ts +0 -458
- package/lib/types/src/client/file-tree-io.d.ts +0 -19
- package/lib/types/src/client/file-tree.d.ts +0 -271
- package/lib/types/src/client/flows/directory-browser.d.ts +0 -587
- package/lib/types/src/client/flows/session-directory.d.ts +0 -415
- package/lib/types/src/client/flows/workspace-directory-flow.d.ts +0 -480
- package/lib/types/src/client/locale.d.ts +0 -31
- package/lib/types/src/client/panel-model.d.ts +0 -37
- package/lib/types/src/client/panel.d.ts +0 -77
- package/lib/types/src/client/roots/connection-test.d.ts +0 -69
- package/lib/types/src/client/roots/roots-panel-state.d.ts +0 -307
- package/lib/types/src/client/roots/roots-panel-view.d.ts +0 -280
- package/lib/types/src/client/roots/roots-panel.d.ts +0 -364
- package/lib/types/src/client/roots/transfer-panel-view.d.ts +0 -35
- package/lib/types/src/client/roots/transfer-panel.d.ts +0 -241
- package/lib/types/src/client/roots/transfer-progress.d.ts +0 -67
- package/lib/types/src/client/roots-panel-view.d.ts +0 -236
- package/lib/types/src/client/roots-panel.d.ts +0 -347
- package/lib/types/src/client/session/session-panel-view.d.ts +0 -336
- package/lib/types/src/client/session/session-panel.d.ts +0 -322
- package/lib/types/src/client/session/session-remote-mark.d.ts +0 -110
- package/lib/types/src/client/session/session-row-actions.d.ts +0 -398
- package/lib/types/src/client/session-panel.d.ts +0 -152
- package/lib/types/src/client/styles.d.ts +0 -252
- package/lib/types/src/client/workspace-directory-flow.d.ts +0 -342
- package/lib/types/src/fs.d.ts +0 -46
- package/lib/types/src/host/app/recycle-bin/recycle-bin-move.d.ts +0 -18
- package/lib/types/src/host/app/recycle-bin/recycle-bin-world.d.ts +0 -38
- package/lib/types/src/host/app/recycle-bin-contract.d.ts +0 -215
- package/lib/types/src/host/app/recycle-bin-move.d.ts +0 -18
- package/lib/types/src/host/app/recycle-bin-service.d.ts +0 -45
- package/lib/types/src/host/app/recycle-bin-world.d.ts +0 -35
- package/lib/types/src/host/app/roots/roots-api-connections.d.ts +0 -49
- package/lib/types/src/host/app/roots/roots-api-contract.d.ts +0 -369
- package/lib/types/src/host/app/roots/roots-api-directories.d.ts +0 -13
- package/lib/types/src/host/app/roots/roots-api-http.d.ts +0 -77
- package/lib/types/src/host/app/roots/roots-api-long-poll.d.ts +0 -130
- package/lib/types/src/host/app/roots/roots-api-projections.d.ts +0 -102
- package/lib/types/src/host/app/roots/roots-api-roots.d.ts +0 -13
- package/lib/types/src/host/app/roots/roots-api-state.d.ts +0 -22
- package/lib/types/src/host/app/roots/roots-api-transfers.d.ts +0 -26
- package/lib/types/src/host/app/roots/roots-api.d.ts +0 -55
- package/lib/types/src/host/app/roots/user-roots.d.ts +0 -552
- package/lib/types/src/host/app/roots-api-connections.d.ts +0 -49
- package/lib/types/src/host/app/roots-api-contract.d.ts +0 -339
- package/lib/types/src/host/app/roots-api-directories.d.ts +0 -13
- package/lib/types/src/host/app/roots-api-http.d.ts +0 -77
- package/lib/types/src/host/app/roots-api-projections.d.ts +0 -102
- package/lib/types/src/host/app/roots-api-roots.d.ts +0 -13
- package/lib/types/src/host/app/roots-api-state.d.ts +0 -22
- package/lib/types/src/host/app/roots-api-support.d.ts +0 -182
- package/lib/types/src/host/app/roots-api-transfers.d.ts +0 -13
- package/lib/types/src/host/app/roots-api.d.ts +0 -55
- package/lib/types/src/host/app/routed-fs.d.ts +0 -239
- package/lib/types/src/host/app/serialize.d.ts +0 -37
- package/lib/types/src/host/app/session-admin/session-admin-context.d.ts +0 -36
- package/lib/types/src/host/app/session-admin/session-admin-delete.d.ts +0 -34
- package/lib/types/src/host/app/session-admin-context.d.ts +0 -36
- package/lib/types/src/host/app/session-admin-contract.d.ts +0 -214
- package/lib/types/src/host/app/session-admin-delete.d.ts +0 -34
- package/lib/types/src/host/app/session-admin-service.d.ts +0 -38
- package/lib/types/src/host/app/takeover/takeover-plan.d.ts +0 -227
- package/lib/types/src/host/app/takeover/takeover-rows.d.ts +0 -55
- package/lib/types/src/host/app/transport-selector.d.ts +0 -98
- package/lib/types/src/host/app/transport-service.d.ts +0 -75
- package/lib/types/src/host/app/user-roots.d.ts +0 -461
- package/lib/types/src/host/domain/bin-location.d.ts +0 -79
- package/lib/types/src/host/domain/connection.d.ts +0 -95
- package/lib/types/src/host/domain/glob-pattern.d.ts +0 -62
- package/lib/types/src/host/domain/literal-text.d.ts +0 -63
- package/lib/types/src/host/domain/path-grammar.d.ts +0 -84
- package/lib/types/src/host/domain/recycle-bin.d.ts +0 -337
- package/lib/types/src/host/domain/root.d.ts +0 -74
- package/lib/types/src/host/domain/roots/bin-location.d.ts +0 -91
- package/lib/types/src/host/domain/roots/route-table.d.ts +0 -102
- package/lib/types/src/host/domain/route-table.d.ts +0 -80
- package/lib/types/src/host/domain/session/terminal-target.d.ts +0 -136
- package/lib/types/src/host/domain/session-admin.d.ts +0 -330
- package/lib/types/src/host/domain/shell.d.ts +0 -47
- package/lib/types/src/host/domain/ssh-config.d.ts +0 -73
- package/lib/types/src/host/domain/terminal-target.d.ts +0 -132
- package/lib/types/src/host/domain/tool-requests.d.ts +0 -369
- package/lib/types/src/host/domain/transfer.d.ts +0 -260
- package/lib/types/src/host/infra/backend/local-backend.d.ts +0 -84
- package/lib/types/src/host/infra/backend/local-version.d.ts +0 -43
- package/lib/types/src/host/infra/backend/platform-local-backend.d.ts +0 -89
- package/lib/types/src/host/infra/backend/remote-backend.d.ts +0 -239
- package/lib/types/src/host/infra/cache/lru.d.ts +0 -52
- package/lib/types/src/host/infra/cache/versioned.d.ts +0 -77
- package/lib/types/src/host/infra/temp-name.d.ts +0 -19
- package/lib/types/src/host/infra/transport/agent/agent-protocol-client.d.ts +0 -132
- package/lib/types/src/host/infra/transport/agent/agent-protocol-codec.d.ts +0 -140
- package/lib/types/src/host/infra/transport/agent/agent-protocol-errors.d.ts +0 -41
- package/lib/types/src/host/infra/transport/agent/agent-protocol-frames.d.ts +0 -197
- package/lib/types/src/host/infra/transport/agent/agent-protocol-types.d.ts +0 -564
- package/lib/types/src/host/infra/transport/agent/agent-transport.d.ts +0 -418
- package/lib/types/src/host/infra/transport/agent-installer.d.ts +0 -121
- package/lib/types/src/host/infra/transport/agent-protocol-client.d.ts +0 -123
- package/lib/types/src/host/infra/transport/agent-protocol-codec.d.ts +0 -131
- package/lib/types/src/host/infra/transport/agent-protocol-errors.d.ts +0 -41
- package/lib/types/src/host/infra/transport/agent-protocol-frames.d.ts +0 -197
- package/lib/types/src/host/infra/transport/agent-protocol-types.d.ts +0 -509
- package/lib/types/src/host/infra/transport/agent-transport.d.ts +0 -353
- package/lib/types/src/host/infra/transport/alias-transport.d.ts +0 -206
- package/lib/types/src/host/infra/transport/askpass-fs.d.ts +0 -20
- package/lib/types/src/host/infra/transport/askpass.d.ts +0 -133
- package/lib/types/src/host/infra/transport/command-pool.d.ts +0 -61
- package/lib/types/src/host/infra/transport/fs-commands.d.ts +0 -140
- package/lib/types/src/host/infra/transport/git-status-route.d.ts +0 -63
- package/lib/types/src/host/infra/transport/git-status.d.ts +0 -101
- package/lib/types/src/host/infra/transport/node-spawn.d.ts +0 -26
- package/lib/types/src/host/infra/transport/session-window.d.ts +0 -51
- package/lib/types/src/host/infra/transport/shell-quote.d.ts +0 -59
- package/lib/types/src/host/infra/transport/ssh/alias-transport.d.ts +0 -206
- package/lib/types/src/host/infra/transport/ssh/askpass-fs.d.ts +0 -20
- package/lib/types/src/host/infra/transport/ssh/askpass.d.ts +0 -133
- package/lib/types/src/host/infra/transport/ssh/shell-quote.d.ts +0 -62
- package/lib/types/src/host/infra/transport/ssh/ssh-argv.d.ts +0 -43
- package/lib/types/src/host/infra/transport/ssh-argv.d.ts +0 -43
- package/lib/types/src/host/infra/transport/ssh2-transport.d.ts +0 -302
- package/lib/types/src/host/integration/agent/agent-install-io.d.ts +0 -33
- package/lib/types/src/host/integration/agent/askpass-registry.d.ts +0 -66
- package/lib/types/src/host/integration/agent-install-io.d.ts +0 -33
- package/lib/types/src/host/integration/agent-preflight.d.ts +0 -56
- package/lib/types/src/host/integration/anchor-directory.d.ts +0 -56
- package/lib/types/src/host/integration/askpass-registry.d.ts +0 -59
- package/lib/types/src/host/integration/bin-root-resolver.d.ts +0 -81
- package/lib/types/src/host/integration/connection-test.d.ts +0 -73
- package/lib/types/src/host/integration/file-reference-provider.d.ts +0 -115
- package/lib/types/src/host/integration/fs/git-status-wiring.d.ts +0 -21
- package/lib/types/src/host/integration/fs/platform-errors.d.ts +0 -94
- package/lib/types/src/host/integration/fs/remote-file-tools.d.ts +0 -369
- package/lib/types/src/host/integration/fs/remote-index.d.ts +0 -177
- package/lib/types/src/host/integration/fs-provider.d.ts +0 -226
- package/lib/types/src/host/integration/lsp/lsp-framing.d.ts +0 -38
- package/lib/types/src/host/integration/lsp/lsp-registry.d.ts +0 -67
- package/lib/types/src/host/integration/lsp/lsp-session.d.ts +0 -130
- package/lib/types/src/host/integration/management-tools.d.ts +0 -64
- package/lib/types/src/host/integration/recycle-bin-service.d.ts +0 -247
- package/lib/types/src/host/integration/remote/connection-test.d.ts +0 -73
- package/lib/types/src/host/integration/remote/remote-face.d.ts +0 -127
- package/lib/types/src/host/integration/remote/remote-tool-backend.d.ts +0 -108
- package/lib/types/src/host/integration/remote-face.d.ts +0 -127
- package/lib/types/src/host/integration/remote-file-tools.d.ts +0 -241
- package/lib/types/src/host/integration/remote-home.d.ts +0 -69
- package/lib/types/src/host/integration/remote-index.d.ts +0 -165
- package/lib/types/src/host/integration/remote-job-tools.d.ts +0 -295
- package/lib/types/src/host/integration/remote-tool-backend.d.ts +0 -97
- package/lib/types/src/host/integration/remote-tools.d.ts +0 -206
- package/lib/types/src/host/integration/root-registry.d.ts +0 -115
- package/lib/types/src/host/integration/roots/anchor-directory.d.ts +0 -56
- package/lib/types/src/host/integration/roots/bin-root-resolver.d.ts +0 -81
- package/lib/types/src/host/integration/roots/remote-home.d.ts +0 -69
- package/lib/types/src/host/integration/roots/root-registry.d.ts +0 -144
- package/lib/types/src/host/integration/roots/roots-wiring.d.ts +0 -219
- package/lib/types/src/host/integration/roots/session-root-index.d.ts +0 -52
- package/lib/types/src/host/integration/roots-api.d.ts +0 -407
- package/lib/types/src/host/integration/roots-wiring.d.ts +0 -211
- package/lib/types/src/host/integration/session/session-api.d.ts +0 -88
- package/lib/types/src/host/integration/session/session-bin-lock.d.ts +0 -80
- package/lib/types/src/host/integration/session/session-header.d.ts +0 -151
- package/lib/types/src/host/integration/session/session-labels.d.ts +0 -56
- package/lib/types/src/host/integration/session/session-route-wiring.d.ts +0 -50
- package/lib/types/src/host/integration/session-admin-service.d.ts +0 -236
- package/lib/types/src/host/integration/session-api.d.ts +0 -81
- package/lib/types/src/host/integration/session-bin-lock.d.ts +0 -80
- package/lib/types/src/host/integration/session-header.d.ts +0 -118
- package/lib/types/src/host/integration/session-labels.d.ts +0 -56
- package/lib/types/src/host/integration/session-route-wiring.d.ts +0 -50
- package/lib/types/src/host/integration/session-scope.d.ts +0 -113
- package/lib/types/src/host/integration/session-tools.d.ts +0 -44
- package/lib/types/src/host/integration/strict-arguments.d.ts +0 -79
- package/lib/types/src/host/integration/takeover/takeover-api.d.ts +0 -62
- package/lib/types/src/host/integration/takeover/takeover-route-wiring.d.ts +0 -60
- package/lib/types/src/host/integration/takeover/takeover-service.d.ts +0 -167
- package/lib/types/src/host/integration/terminal-manifest.d.ts +0 -94
- package/lib/types/src/host/integration/tools/management-tools.d.ts +0 -245
- package/lib/types/src/host/integration/tools/remote-job-tools.d.ts +0 -316
- package/lib/types/src/host/integration/tools/remote-lsp-tools.d.ts +0 -43
- package/lib/types/src/host/integration/tools/remote-tools.d.ts +0 -236
- package/lib/types/src/host/integration/tools/session-target.d.ts +0 -52
- package/lib/types/src/host/integration/tools/session-tools.d.ts +0 -46
- package/lib/types/src/host/integration/tools/strict-arguments.d.ts +0 -79
- package/lib/types/src/host/integration/tools/terminal-manifest.d.ts +0 -94
- package/lib/types/src/host/integration/transfer/remote-copy.d.ts +0 -66
- package/lib/types/src/host/integration/transfer/transfer-adapters.d.ts +0 -48
- package/lib/types/src/host/integration/transfer/transfer-tracker.d.ts +0 -106
- package/lib/types/src/host/integration/transfer-adapters.d.ts +0 -44
- package/lib/types/src/host/integration/transfer-service.d.ts +0 -164
- package/lib/types/src/host/integration/transfer-tracker.d.ts +0 -106
- package/lib/types/src/host/integration/user-roots.d.ts +0 -461
- package/lib/types/src/wiring/connections.d.ts +0 -189
- package/lib/types/src/wiring/fs.d.ts +0 -13
- package/lib/types/src/wiring/install-memo.d.ts +0 -32
- package/lib/types/src/wiring/legacy-dirs.d.ts +0 -62
- package/lib/types/src/wiring/package-paths.d.ts +0 -35
- package/lib/types/src/wiring/roots.d.ts +0 -21
- package/lib/types/src/wiring/state-dir.d.ts +0 -29
- package/lib/types/src/wiring/tools.d.ts +0 -35
|
@@ -1,415 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The **session entry**: add a directory to the workspace the current session is in, without leaving the
|
|
3
|
-
* conversation and **without creating a workspace**.
|
|
4
|
-
*
|
|
5
|
-
* What the user asked for: "不要在设置中加,不方便" (adding directories through the settings page is
|
|
6
|
-
* inconvenient), and the directory-flow hole is no answer to it either - that hole's owner
|
|
7
|
-
* (`ui-workspace`) adopts a picked path by calling `createWorkspace({ path })`, which **creates a new
|
|
8
|
-
* workspace**. This entry is the other shape: it registers the directory as one of this plugin's roots
|
|
9
|
-
* (the same `/api/over-ssh/roots` action the settings panel uses), and nothing else. The root is
|
|
10
|
-
* live immediately, so the session that is already open - and every other one - can read and write under
|
|
11
|
-
* it through the router. No workspace is created, no session is moved.
|
|
12
|
-
*
|
|
13
|
-
* Where it lives: `conversation.input.left`, a `list`-kind, session-scoped hole in the composer tool row
|
|
14
|
-
* ("compact controls at the left of the composer tool row"). It is the only one of the four candidate
|
|
15
|
-
* holes that is **inside the conversation**: the two `sidebar.workspaces.session.*` holes are row actions
|
|
16
|
-
* of the sidebar list (they hand out a `sessionId`, not the composer), and `conversation.input.right` sits
|
|
17
|
-
* next to the submit button, where a mis-click costs more than it saves. `ctx.slots.inject` is used rather
|
|
18
|
-
* than a bare `register`, because the hole belongs to `ui-conversation` and may be declared after this
|
|
19
|
-
* plugin (a bare register into an undeclared slot **throws** and would take the settings section down with
|
|
20
|
-
* it), and the registration re-runs on `locale/change` for the same reason the other two surfaces do.
|
|
21
|
-
*
|
|
22
|
-
* Where "the current workspace" comes from: the framework hands every session-scoped occupant a
|
|
23
|
-
* `sessionId` seat plus the `useSessions` / `useWorkspaces` selector hooks. The session's `cwd` comes from
|
|
24
|
-
* the session list; when that seat is absent the workspace containing the session is looked up by
|
|
25
|
-
* `sessionIds` instead. **Neither is guaranteed**: a composition without those packages hands out neither, and
|
|
26
|
-
* then the entry says so in the panel (`sessionAddWorkspaceUnknown`) and **refuses to add anything** — every
|
|
27
|
-
* root this card can list is scoped to a workspace, so with no workspace there is nothing to scope one to. It
|
|
28
|
-
* used to write an unscoped root "which is in effect for every session anyway"; that sentence was wrong twice
|
|
29
|
-
* over (audit 0056): unscoped roots are listed by no session, and the tool layer resolves by cwd/anchor rather
|
|
30
|
-
* than by workspace, so "in effect for every session" was never something the list could promise. The entry
|
|
31
|
-
* never guesses a path.
|
|
32
|
-
*
|
|
33
|
-
* The card is **portalled** through `./portal.ts`, exactly like the directory-flow dialog: a container on
|
|
34
|
-
* `document.body` while the card is up. The composer tool row is a flex row this plugin does not own, and a
|
|
35
|
-
* `position: fixed` card *inside* it would still be re-anchored by any ancestor with a `transform` or
|
|
36
|
-
* `contain`; from `body` there is no such ancestor to worry about. The trigger stays where it is, so closing
|
|
37
|
-
* hands focus back to it (it is whatever held focus before the card opened).
|
|
38
|
-
*
|
|
39
|
-
* **Unverified** (see `doc/02-platform/workspace-directory-flow.md`): the portal has not been looked at in a
|
|
40
|
-
* real GUI.
|
|
41
|
-
*
|
|
42
|
-
* @module dsh-over-ssh/client/session-directory
|
|
43
|
-
*/
|
|
44
|
-
import { type ReactNode } from 'react';
|
|
45
|
-
import { type DirectoryBrowserIo } from './directory-browser.ts';
|
|
46
|
-
import type { OverSshKey } from '../core/locale.ts';
|
|
47
|
-
import { type CardPortalTarget } from '../core/portal.ts';
|
|
48
|
-
import { type ApiResult, type FetchLike, type MessageKey, type RootRow } from '../roots/roots-panel.ts';
|
|
49
|
-
import { type RootsPanelCopy } from '../roots/roots-panel-view.ts';
|
|
50
|
-
/** The hole this entry fills: a `list`-kind, session-scoped seat at the left of the composer tool row. */
|
|
51
|
-
export declare const SESSION_DIRECTORY_SLOT = "conversation.input.left";
|
|
52
|
-
/**
|
|
53
|
-
* The hole's declaration, mirrored.
|
|
54
|
-
*
|
|
55
|
-
* `@deepseek-ai/dsh-client-ui-conversation` declares this key (and its `session` scope) but is **not** a
|
|
56
|
-
* dependency of this repository, while the registration below has to type-check here. The shape is quoted
|
|
57
|
-
* from `packages/client/ui-conversation/src/client/contract/slots.ts`:
|
|
58
|
-
* `'conversation.input.left': { kind: 'list'; scope: 'session' }`.
|
|
59
|
-
*/
|
|
60
|
-
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
61
|
-
interface SlotMap {
|
|
62
|
-
/** Compact controls at the left of the composer tool row. */
|
|
63
|
-
'conversation.input.left': {
|
|
64
|
-
kind: 'list';
|
|
65
|
-
scope: 'session';
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/** Stable entry id, so a locale-driven re-registration replaces the same row instead of adding a second. */
|
|
70
|
-
export declare const SESSION_DIRECTORY_ID = "over-ssh-add-directory";
|
|
71
|
-
/** Placement among the shipped composer controls (the platform uses 100-steps). */
|
|
72
|
-
export declare const SESSION_DIRECTORY_ORDER = 200;
|
|
73
|
-
/**
|
|
74
|
-
* Classes of the body-level container this entry's card is portalled into: the floating shell
|
|
75
|
-
* (`CLASS.portal`) plus this surface's own name (`CLASS.portalComposer`). Both placements now centre the card
|
|
76
|
-
* in the window; the class distinguishes the surface, not the geometry (see `styles.ts`).
|
|
77
|
-
*/
|
|
78
|
-
export declare const SESSION_DIRECTORY_PORTAL_CLASS: string;
|
|
79
|
-
/**
|
|
80
|
-
* The card's click sink: the composer entry sits in the conversation and its dialog is modal, so pointer input has
|
|
81
|
-
* to stop at the card (audit 2026-11-01b ui P2-1).
|
|
82
|
-
*/
|
|
83
|
-
export declare const SESSION_DIRECTORY_BACKDROP_CLASS: "dsh-rw-backdrop";
|
|
84
|
-
/** One root as this entry adds it. Local roots carry no connection; remote ones must. */
|
|
85
|
-
export interface SessionDirectoryRootDraft {
|
|
86
|
-
readonly location: 'local' | 'remote';
|
|
87
|
-
readonly path: string;
|
|
88
|
-
readonly connectionId?: string;
|
|
89
|
-
/** The workspace this directory is added to; the card lists only roots that carry it. */
|
|
90
|
-
readonly workspaces?: readonly string[];
|
|
91
|
-
/** The conversation this directory is added to — the strict scope (ADR-0013). */
|
|
92
|
-
readonly sessions?: readonly string[];
|
|
93
|
-
}
|
|
94
|
-
/** The calls this entry makes: the browser's three plus the one write. */
|
|
95
|
-
export interface SessionDirectoryIo extends DirectoryBrowserIo {
|
|
96
|
-
/**
|
|
97
|
-
* Register one root and answer the **anchor path** the host computed, when it reports one.
|
|
98
|
-
*
|
|
99
|
-
* The anchor is not needed here (this entry creates no workspace) but it is what the host answers, and
|
|
100
|
-
* dropping it would make this call diverge from the settings panel's for no gain.
|
|
101
|
-
*/
|
|
102
|
-
addRoot(draft: SessionDirectoryRootDraft): Promise<ApiResult<{
|
|
103
|
-
readonly anchorPath?: string;
|
|
104
|
-
}>>;
|
|
105
|
-
/** The plugin's roots as the route reports them (narrowed locally; no credential field survives). */
|
|
106
|
-
loadRoots(workspacePath: string | undefined, sessionId?: string): Promise<ApiResult<readonly RootRow[]>>;
|
|
107
|
-
/**
|
|
108
|
-
* Drop one root from **this** workspace.
|
|
109
|
-
*
|
|
110
|
-
* `workspaces` is a union on the add side, so a root can be listed by several workspaces; removing it from
|
|
111
|
-
* one must not take it from the others. The host removes the root itself only when the last workspace drops
|
|
112
|
-
* it (the global delete, which the settings panel performs, omits `workspace`).
|
|
113
|
-
*/
|
|
114
|
-
removeRoot(key: string, workspacePath?: string, sessionId?: string): Promise<ApiResult<unknown>>;
|
|
115
|
-
/**
|
|
116
|
-
* 宿主系统的原生目录选择框;`null` 表示用户取消,缺席表示这个组合没有这个能力。
|
|
117
|
-
*
|
|
118
|
-
* 可选:没有它时对话框照旧用内置浏览器,只是少一颗「浏览…」按钮。
|
|
119
|
-
*/
|
|
120
|
-
pickLocal?: (() => Promise<string | null>) | undefined;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Bind the entry's calls to this plugin's route.
|
|
124
|
-
*
|
|
125
|
-
* @param options - `fetch` (same-origin in the app) and a route override for tests.
|
|
126
|
-
* @returns the calls the entry uses.
|
|
127
|
-
*/
|
|
128
|
-
export declare function createSessionDirectoryIo(options: {
|
|
129
|
-
readonly fetchImpl: FetchLike;
|
|
130
|
-
readonly path?: string;
|
|
131
|
-
/** 原生目录选择框;见 {@link SessionDirectoryIo.pickLocal}。 */
|
|
132
|
-
readonly pickLocal?: (() => Promise<string | null>) | undefined;
|
|
133
|
-
}): SessionDirectoryIo;
|
|
134
|
-
/** Everything the entry renders from. */
|
|
135
|
-
export interface SessionDirectoryState {
|
|
136
|
-
/** True while the floating card is up. */
|
|
137
|
-
readonly open: boolean;
|
|
138
|
-
/** True while the add-root request is in flight. */
|
|
139
|
-
readonly pending: boolean;
|
|
140
|
-
/** The workspace the session is in, as the framework seats reported it; absent when unavailable. */
|
|
141
|
-
readonly workspacePath?: string;
|
|
142
|
-
/** The conversation this card acts for, when the platform handed one over (ADR-0013). */
|
|
143
|
-
readonly sessionId?: string;
|
|
144
|
-
/** The directory that was just added (the path the user chose). */
|
|
145
|
-
readonly added?: string;
|
|
146
|
-
/** The last refusal or failure. */
|
|
147
|
-
readonly notice?: MessageKey;
|
|
148
|
-
/** The plugin's roots as last read; empty until the first answer. */
|
|
149
|
-
readonly roots: readonly RootRow[];
|
|
150
|
-
/** True while a roots read or a removal is in flight. */
|
|
151
|
-
readonly rootsPending: boolean;
|
|
152
|
-
/**
|
|
153
|
-
* True while the card is **reading** its roots list.
|
|
154
|
-
*
|
|
155
|
-
* Separate from {@link SessionDirectoryState.rootsPending}, which is the removal gate: the card used to render
|
|
156
|
-
* 「还没有添加目录。点「浏览…」…」 during the first read, i.e. it claimed the list was empty before it had an
|
|
157
|
-
* answer (audit 2026-11-01b ui P2-3).
|
|
158
|
-
*/
|
|
159
|
-
readonly rootsReading: boolean;
|
|
160
|
-
/** True while the browser **step** is open (the card shows the picker instead of its buttons). */
|
|
161
|
-
readonly browsing: boolean;
|
|
162
|
-
/** The root key being removed, so its own row can hold still. */
|
|
163
|
-
readonly removing?: string;
|
|
164
|
-
}
|
|
165
|
-
/** What the reducer accepts. */
|
|
166
|
-
export type SessionDirectoryAction = {
|
|
167
|
-
readonly type: 'toggled';
|
|
168
|
-
} | {
|
|
169
|
-
readonly type: 'closed';
|
|
170
|
-
} | {
|
|
171
|
-
readonly type: 'workspace-known';
|
|
172
|
-
readonly path?: string | undefined;
|
|
173
|
-
} | {
|
|
174
|
-
readonly type: 'session-known';
|
|
175
|
-
readonly sessionId?: string | undefined;
|
|
176
|
-
} | {
|
|
177
|
-
readonly type: 'submitted';
|
|
178
|
-
} | {
|
|
179
|
-
readonly type: 'added';
|
|
180
|
-
readonly path: string;
|
|
181
|
-
} | {
|
|
182
|
-
readonly type: 'refused';
|
|
183
|
-
readonly message: MessageKey;
|
|
184
|
-
} | {
|
|
185
|
-
readonly type: 'failed';
|
|
186
|
-
readonly reason: string;
|
|
187
|
-
} | {
|
|
188
|
-
readonly type: 'browse-toggled';
|
|
189
|
-
}
|
|
190
|
-
/** A roots read started; the list keeps what it had and the card may say "reading". */
|
|
191
|
-
| {
|
|
192
|
-
readonly type: 'roots-reading';
|
|
193
|
-
} | {
|
|
194
|
-
readonly type: 'roots-loaded';
|
|
195
|
-
readonly roots: readonly RootRow[];
|
|
196
|
-
} | {
|
|
197
|
-
readonly type: 'roots-failed';
|
|
198
|
-
readonly reason: string;
|
|
199
|
-
} | {
|
|
200
|
-
readonly type: 'root-removing';
|
|
201
|
-
readonly key: string;
|
|
202
|
-
} | {
|
|
203
|
-
readonly type: 'root-removed';
|
|
204
|
-
readonly key: string;
|
|
205
|
-
};
|
|
206
|
-
/** @returns the state a freshly mounted entry holds. */
|
|
207
|
-
export declare function initialSessionDirectoryState(): SessionDirectoryState;
|
|
208
|
-
/**
|
|
209
|
-
* The entry's state machine. Pure: an action that changes nothing returns the **same object**.
|
|
210
|
-
*
|
|
211
|
-
* `workspace-known` is dispatched by the shell on every render (the seat can resolve later); it is a no-op
|
|
212
|
-
* when the path has not moved, so the panel is not re-rendered by an unchanged fact.
|
|
213
|
-
*
|
|
214
|
-
* @param state - the current state.
|
|
215
|
-
* @param action - what happened.
|
|
216
|
-
* @returns the next state.
|
|
217
|
-
*/
|
|
218
|
-
export declare function sessionDirectoryReducer(state: SessionDirectoryState, action: SessionDirectoryAction): SessionDirectoryState;
|
|
219
|
-
/** The complete render input. */
|
|
220
|
-
export interface SessionDirectoryView {
|
|
221
|
-
/** True while the floating card is up. */
|
|
222
|
-
readonly visible: boolean;
|
|
223
|
-
/** True while the add-root request is in flight. */
|
|
224
|
-
readonly pending: boolean;
|
|
225
|
-
/** The workspace the session is in, or `undefined` when the seats could not answer. */
|
|
226
|
-
readonly workspacePath?: string;
|
|
227
|
-
/** The directory that was just added. */
|
|
228
|
-
readonly added?: string;
|
|
229
|
-
/** The refusal or failure text, resolved against the active dictionary. */
|
|
230
|
-
readonly notice: string;
|
|
231
|
-
/** The workspace line, resolved against the active dictionary. */
|
|
232
|
-
readonly workspaceLine: string;
|
|
233
|
-
/** The directories this session can use, ready to render. */
|
|
234
|
-
readonly roots: readonly SessionRootRow[];
|
|
235
|
-
/** True while the list is being read or a row is being removed. */
|
|
236
|
-
readonly rootsPending: boolean;
|
|
237
|
-
/** True while the list is being read (so the empty state must not be shown). */
|
|
238
|
-
readonly rootsReading: boolean;
|
|
239
|
-
/** True while the browser step is open. */
|
|
240
|
-
readonly browsing: boolean;
|
|
241
|
-
}
|
|
242
|
-
/** One directory row of the session card; text is already localized. */
|
|
243
|
-
export interface SessionRootRow {
|
|
244
|
-
readonly key: string;
|
|
245
|
-
readonly title: string;
|
|
246
|
-
readonly subtitle: string;
|
|
247
|
-
/** 「本地」/「远端」 — the one fact a path alone cannot state. */
|
|
248
|
-
readonly badge: string;
|
|
249
|
-
/** Only a root in the plugin's own file can be removed; a profile-declared one cannot. */
|
|
250
|
-
readonly removable: boolean;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Turn the state into render input, resolving the two dynamic lines through the active dictionary.
|
|
254
|
-
*
|
|
255
|
-
* @param state - the entry state.
|
|
256
|
-
* @param copy - the dictionary of the active locale.
|
|
257
|
-
* @returns the flags and the resolved text.
|
|
258
|
-
*/
|
|
259
|
-
export declare function selectSessionDirectoryView(state: SessionDirectoryState, copy: RootsPanelCopy): SessionDirectoryView;
|
|
260
|
-
/** What the controller needs. */
|
|
261
|
-
export interface SessionDirectoryDeps {
|
|
262
|
-
readonly io: SessionDirectoryIo;
|
|
263
|
-
/** The dictionary of the active locale; a thunk, because the locale can change under a mounted entry. */
|
|
264
|
-
readonly copy: () => RootsPanelCopy;
|
|
265
|
-
}
|
|
266
|
-
/** The calls the container makes. */
|
|
267
|
-
export interface SessionDirectoryController {
|
|
268
|
-
readonly getState: () => SessionDirectoryState;
|
|
269
|
-
readonly subscribe: (listener: () => void) => () => void;
|
|
270
|
-
/** Open or close the floating card. */
|
|
271
|
-
readonly toggle: () => void;
|
|
272
|
-
readonly close: () => void;
|
|
273
|
-
/** Push the workspace the framework seats reported (or `undefined` when they could not). */
|
|
274
|
-
readonly setWorkspacePath: (path: string | undefined) => void;
|
|
275
|
-
/** Push the conversation this card acts for (ADR-0013), or `undefined` when the seat could not answer. */
|
|
276
|
-
readonly setSessionId: (sessionId: string | undefined) => void;
|
|
277
|
-
/** Validate and register the picked directory; the world comes from whether a connection was used. */
|
|
278
|
-
readonly commit: (path: string, connectionId: string | undefined) => Promise<void>;
|
|
279
|
-
/** Open or close the browser step. */
|
|
280
|
-
readonly browse: () => void;
|
|
281
|
-
/** Re-read the plugin's roots (on open, and after every change). */
|
|
282
|
-
readonly refreshRoots: () => Promise<void>;
|
|
283
|
-
/** Drop one root from this plugin's list. */
|
|
284
|
-
readonly removeRoot: (key: string) => Promise<void>;
|
|
285
|
-
/** Re-arm after a mount (React's development replay runs the cleanup once before the real lifetime). */
|
|
286
|
-
readonly activate: () => void;
|
|
287
|
-
readonly dispose: () => void;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Build the stateful half of the entry.
|
|
291
|
-
*
|
|
292
|
-
* The write goes through `validateRootDraft` - the same authority the settings panel and the directory-flow
|
|
293
|
-
* dialog use - so a local path that is not absolute, or a remote path with `..` in it, is refused here
|
|
294
|
-
* before anything reaches the host. A `remote` pick without a connection is refused the same way.
|
|
295
|
-
*
|
|
296
|
-
* @param deps - the injected calls and the active dictionary.
|
|
297
|
-
* @returns the controller the container subscribes to.
|
|
298
|
-
*/
|
|
299
|
-
export declare function createSessionDirectory(deps: SessionDirectoryDeps): SessionDirectoryController;
|
|
300
|
-
/** What the entry's controls call. */
|
|
301
|
-
export interface SessionDirectorySectionActions {
|
|
302
|
-
readonly onToggle: () => void;
|
|
303
|
-
readonly onClose: () => void;
|
|
304
|
-
/** Open or close the browser step. */
|
|
305
|
-
readonly onBrowse: () => void;
|
|
306
|
-
/** Drop one directory from this session's list. */
|
|
307
|
-
readonly onRemoveRoot: (key: string) => void;
|
|
308
|
-
}
|
|
309
|
-
/** Props of the pure template: copy, state, callbacks and the browser the shell mounted (or `null` in tests). */
|
|
310
|
-
export interface SessionDirectorySectionProps {
|
|
311
|
-
readonly copy: RootsPanelCopy;
|
|
312
|
-
readonly state: SessionDirectoryState;
|
|
313
|
-
readonly actions: SessionDirectorySectionActions;
|
|
314
|
-
/** The directory browser element, built by the container; `null` renders the card without one. */
|
|
315
|
-
readonly browser?: ReactNode;
|
|
316
|
-
/**
|
|
317
|
-
* The body-level portal the card is mounted into. Absent renders the card **in place**, which is the
|
|
318
|
-
* DOM-less degradation (SSR, a direct template call): a runtime without a document has no composer row to
|
|
319
|
-
* escape either.
|
|
320
|
-
*/
|
|
321
|
-
readonly portal?: CardPortalTarget | undefined;
|
|
322
|
-
/**
|
|
323
|
-
* `id` of the card's heading, referenced by `aria-labelledby`.
|
|
324
|
-
*
|
|
325
|
-
* **Required**, and supplied by the caller (`useId()` in the container). It used to default to a module-level
|
|
326
|
-
* constant — one id for every mount — which is the shape the id audit (2026-10-31 client.md §2.4) is about.
|
|
327
|
-
*/
|
|
328
|
-
readonly titleId: string;
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Render the session entry. Pure: calling it twice with the same props yields the same tree.
|
|
332
|
-
*
|
|
333
|
-
* @param props - copy, state, callbacks, the browser element, the portal and the heading's id.
|
|
334
|
-
* @returns the trigger and, while open, the card (inside the portal when one is given).
|
|
335
|
-
*/
|
|
336
|
-
export declare function SessionDirectorySection({ copy, state, actions, browser, portal, titleId, }: SessionDirectorySectionProps): ReactNode;
|
|
337
|
-
/** The minimal shape of the session list snapshot this module reads (a structural mirror). */
|
|
338
|
-
interface SessionListLike {
|
|
339
|
-
readonly byId?: Readonly<Record<string, {
|
|
340
|
-
readonly cwd?: string;
|
|
341
|
-
} | undefined>>;
|
|
342
|
-
}
|
|
343
|
-
/** The minimal shape of the workspace snapshot this module reads (a structural mirror). */
|
|
344
|
-
interface WorkspaceSnapshotLike {
|
|
345
|
-
readonly items?: readonly {
|
|
346
|
-
readonly path?: string;
|
|
347
|
-
readonly sessionIds?: readonly string[];
|
|
348
|
-
}[];
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* One framework selector seat, as this module calls it.
|
|
352
|
-
*
|
|
353
|
-
* Structural on purpose: `useSessions` / `useWorkspaces` are merged into `GlobalStandardProps` by packages
|
|
354
|
-
* that are **not** dependencies of this repository, so the seat is described by the one call this module
|
|
355
|
-
* makes instead of imported.
|
|
356
|
-
*/
|
|
357
|
-
export type SessionSeatHook<Snapshot> = (selector: (snapshot: Snapshot) => unknown) => unknown;
|
|
358
|
-
/** Props of the React shell: the injected calls plus whatever seats the renderer handed this occurrence. */
|
|
359
|
-
export interface SessionDirectoryContainerProps {
|
|
360
|
-
/** The active locale's dictionary; the shell resolves its own dynamic keys through it. */
|
|
361
|
-
readonly copy: RootsPanelCopy;
|
|
362
|
-
/** The injected calls. Created once by the entry, never by the component. */
|
|
363
|
-
readonly io: SessionDirectoryIo;
|
|
364
|
-
/** Session identity (the `sessionId` seat of a session-scoped slot); absent without `ui-session`. */
|
|
365
|
-
readonly sessionId?: string | undefined;
|
|
366
|
-
/** The `useSessions` seat; absent without `ui-session`. */
|
|
367
|
-
readonly useSessions?: SessionSeatHook<SessionListLike> | undefined;
|
|
368
|
-
/** The `useWorkspaces` seat; absent without `ui-workspace`. */
|
|
369
|
-
readonly useWorkspaces?: SessionSeatHook<WorkspaceSnapshotLike> | undefined;
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Read the current workspace path from whichever framework seat can answer.
|
|
373
|
-
*
|
|
374
|
-
* The session's own `cwd` is preferred (it is the directory the session actually runs in); the workspace
|
|
375
|
-
* containing the session is the fallback, looked up by `sessionIds`. Both are `undefined` in a composition
|
|
376
|
-
* that hands out neither seat, which the panel states rather than hides.
|
|
377
|
-
*
|
|
378
|
-
* Exported so the preference order and the fallback are asserted offline: the seats are plain callbacks, and
|
|
379
|
-
* a test needs no renderer to drive them.
|
|
380
|
-
*
|
|
381
|
-
* @param props - the shell props carrying the seats.
|
|
382
|
-
* @returns the workspace path, or `undefined`.
|
|
383
|
-
*/
|
|
384
|
-
export declare function readWorkspacePath(props: SessionDirectoryContainerProps): string | undefined;
|
|
385
|
-
/**
|
|
386
|
-
* The identity of a roots read: which workspace the list is scoped to, or that the card is closed.
|
|
387
|
-
*
|
|
388
|
-
* A read is only valid for the workspace it was issued for, so this value is what decides **when a re-read is
|
|
389
|
-
* owed**. It is a named pure function rather than a bare dependency array because this repository's tests do
|
|
390
|
-
* not render hooks (`client-roots-view.test.ts` says why): an effect's dependency list cannot be executed by a
|
|
391
|
-
* test, so the *decision* is extracted here where it can be. (A mutation that drops the dependency from the
|
|
392
|
-
* effect used to leave every test green — found by the round-2 mutation experiment.)
|
|
393
|
-
*
|
|
394
|
-
* Why it matters: the seats that answer "which workspace is this session in" can answer **after** the card is
|
|
395
|
-
* already open. Reading only on `open` made the first (unknown-workspace) answer final, so a late seat left the
|
|
396
|
-
* list empty until the card was closed and reopened (audit 0056, review T3).
|
|
397
|
-
*
|
|
398
|
-
* @param state - the entry state.
|
|
399
|
-
* @returns `closed` when the card is closed, otherwise a key that changes when the workspace does.
|
|
400
|
-
*/
|
|
401
|
-
export declare function rootsQueryKey(state: SessionDirectoryState): string;
|
|
402
|
-
/**
|
|
403
|
-
* Subscribe to a per-mount entry and render {@link SessionDirectorySection}.
|
|
404
|
-
*
|
|
405
|
-
* The card is **portalled** (`./portal.ts`): one container per mount, attached to `document.body` while the
|
|
406
|
-
* card is up and removed when it closes. The trigger alone stays in the composer row. Opening also moves focus
|
|
407
|
-
* into the card and remembers the trigger, so Esc closes and closing hands focus back.
|
|
408
|
-
*
|
|
409
|
-
* @param props - the injected dictionary and calls plus the framework seats.
|
|
410
|
-
* @returns the trigger and, while open, the card with its browser.
|
|
411
|
-
*/
|
|
412
|
-
export declare function SessionDirectoryContainer(props: SessionDirectoryContainerProps): ReactNode;
|
|
413
|
-
/** The dictionary keys this module renders, so a test can assert the two locales carry them. */
|
|
414
|
-
export type SessionDirectoryKey = Extract<OverSshKey, 'sessionAddOpen' | 'sessionAddTitle' | 'sessionAddHint' | 'sessionAddWorkspace' | 'sessionAddWorkspaceUnknown' | 'sessionAddDone' | 'sessionAddFailed' | 'sessionAddPick' | 'sessionBrowse' | 'sessionBrowseBack' | 'sessionRootsTitle' | 'sessionRootsEmpty' | 'sessionRootsHint' | 'sessionRootsFailed' | 'rootsRemove' | 'close' | 'flowPending'>;
|
|
415
|
-
export {};
|