@exagone313/dsh-podman 0.2.0-rc.3 → 0.2.0

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 (191) hide show
  1. package/README.md +14 -2
  2. package/README.zh.md +14 -2
  3. package/cordis.patch.yml +58 -0
  4. package/dist/approval-reasons.d.ts +3 -4
  5. package/dist/approval-reasons.js +40 -49
  6. package/dist/approval-reasons.test.js +43 -15
  7. package/dist/approval.js +27 -10
  8. package/dist/approval.test.js +165 -34
  9. package/dist/card-route.d.ts +3 -2
  10. package/dist/card-route.js +154 -42
  11. package/dist/card-route.test.js +85 -43
  12. package/dist/card-test-support.js +39 -66
  13. package/dist/client/ContainerCard.d.ts +1 -1
  14. package/dist/client/ContainerCard.js +92 -50
  15. package/dist/client/card-protocol.d.ts +6 -3
  16. package/dist/client/container-card-caches.js +11 -6
  17. package/dist/client/container-card-controller.d.ts +16 -18
  18. package/dist/client/container-card-controller.js +92 -40
  19. package/dist/client/container-card-create-modal.d.ts +2 -2
  20. package/dist/client/container-card-create-modal.js +13 -5
  21. package/dist/client/container-card-default-env.d.ts +10 -0
  22. package/dist/client/container-card-default-env.js +69 -0
  23. package/dist/client/container-card-directory.d.ts +2 -2
  24. package/dist/client/container-card-directory.js +12 -4
  25. package/dist/client/container-card-editors.d.ts +3 -3
  26. package/dist/client/container-card-editors.js +104 -32
  27. package/dist/client/container-card-images.d.ts +4 -4
  28. package/dist/client/container-card-images.js +19 -6
  29. package/dist/client/container-card-paths.d.ts +3 -3
  30. package/dist/client/container-card-paths.js +18 -11
  31. package/dist/client/container-card-row.d.ts +10 -6
  32. package/dist/client/container-card-row.js +82 -13
  33. package/dist/client/container-card-secrets.d.ts +3 -3
  34. package/dist/client/container-card-secrets.js +8 -6
  35. package/dist/client/container-card-shared.d.ts +4 -17
  36. package/dist/client/container-card-shared.js +9 -25
  37. package/dist/client/container-card-styles.d.ts +2 -8
  38. package/dist/client/container-card-styles.js +14 -52
  39. package/dist/client/container-card-volumes.d.ts +2 -2
  40. package/dist/client/container-card-volumes.js +9 -5
  41. package/dist/client/container-card-workspace.d.ts +8 -6
  42. package/dist/client/container-card-workspace.js +9 -3
  43. package/dist/client/directory-picker.js +2 -1
  44. package/dist/client/index.js +13141 -2036
  45. package/dist/client/locales.d.ts +6 -1
  46. package/dist/client/locales.js +106 -38
  47. package/dist/client/podman-terminal-guide.d.ts +11 -0
  48. package/dist/client/podman-terminal-guide.js +208 -0
  49. package/dist/client/podman-terminal-title.d.ts +7 -0
  50. package/dist/client/podman-terminal-title.js +30 -0
  51. package/dist/client/podman-terminal.d.ts +26 -0
  52. package/dist/client/podman-terminal.js +412 -0
  53. package/dist/client/read-only-approval.d.ts +2 -2
  54. package/dist/client/read-only-approval.js +13 -3
  55. package/dist/client/slot-contract.d.ts +0 -11
  56. package/dist/client/terminal-preference.d.ts +26 -0
  57. package/dist/client/terminal-preference.js +67 -0
  58. package/dist/client/terminal-protocol.d.ts +85 -0
  59. package/dist/client/terminal-protocol.js +14 -0
  60. package/dist/client/terminal-tab.d.ts +60 -0
  61. package/dist/client/terminal-tab.js +35 -0
  62. package/dist/client/terminal-targets.d.ts +33 -0
  63. package/dist/client/terminal-targets.js +65 -0
  64. package/dist/client/terminal-titles.d.ts +23 -0
  65. package/dist/client/terminal-titles.js +52 -0
  66. package/dist/client/terminal-transport.d.ts +63 -0
  67. package/dist/client/terminal-transport.js +207 -0
  68. package/dist/client/tool-views.js +215 -49
  69. package/dist/container-env.d.ts +11 -0
  70. package/dist/container-env.js +96 -0
  71. package/dist/container-env.test.d.ts +1 -0
  72. package/dist/container-env.test.js +93 -0
  73. package/dist/containers.test.js +196 -18
  74. package/dist/daemons.test.js +18 -4
  75. package/dist/dsh-version.d.ts +1 -0
  76. package/dist/dsh-version.js +46 -0
  77. package/dist/env-rows.d.ts +14 -0
  78. package/dist/env-rows.js +52 -0
  79. package/dist/env-rows.test.d.ts +1 -0
  80. package/dist/env-rows.test.js +43 -0
  81. package/dist/fs-provider.d.ts +1 -0
  82. package/dist/fs-provider.js +26 -12
  83. package/dist/fs-provider.test.js +51 -10
  84. package/dist/generated/version.d.ts +2 -2
  85. package/dist/generated/version.js +2 -2
  86. package/dist/grpc/proto/dshctl/v1/control.proto +11 -1
  87. package/dist/grpc/proto/dshguest/v1/guest.proto +5 -0
  88. package/dist/grpc/runtime-client.d.ts +3 -1
  89. package/dist/grpc/runtime-client.js +90 -17
  90. package/dist/guest-rpc.d.ts +15 -19
  91. package/dist/guest-rpc.js +289 -70
  92. package/dist/guest-rpc.test.d.ts +1 -0
  93. package/dist/guest-rpc.test.js +241 -0
  94. package/dist/guest-terminal.d.ts +30 -0
  95. package/dist/guest-terminal.js +196 -0
  96. package/dist/images.test.js +10 -3
  97. package/dist/index.d.ts +11 -16
  98. package/dist/index.js +42 -36
  99. package/dist/locales.test.d.ts +1 -0
  100. package/dist/locales.test.js +34 -0
  101. package/dist/misc.test.js +38 -10
  102. package/dist/mount-enums.js +2 -1
  103. package/dist/mount-input.d.ts +2 -0
  104. package/dist/mount-input.js +38 -22
  105. package/dist/mounts.test.js +81 -11
  106. package/dist/naming.test.d.ts +1 -0
  107. package/dist/naming.test.js +28 -0
  108. package/dist/output-reader.js +36 -4
  109. package/dist/package-deps.test.d.ts +1 -0
  110. package/dist/package-deps.test.js +49 -0
  111. package/dist/paths.test.js +4 -2
  112. package/dist/plugin-meta.test.d.ts +1 -0
  113. package/dist/plugin-meta.test.js +29 -0
  114. package/dist/project-path.js +33 -7
  115. package/dist/project-path.test.js +14 -0
  116. package/dist/prompts.d.ts +0 -4
  117. package/dist/prompts.js +15 -84
  118. package/dist/read-only-shell.js +3 -1
  119. package/dist/read-only-shell.test.js +80 -25
  120. package/dist/runtime-client.test.d.ts +1 -0
  121. package/dist/runtime-client.test.js +53 -0
  122. package/dist/secrets.test.js +21 -6
  123. package/dist/settings-commands.test.js +61 -14
  124. package/dist/settings-create.test.js +32 -10
  125. package/dist/settings-default-env.test.d.ts +1 -0
  126. package/dist/settings-default-env.test.js +175 -0
  127. package/dist/settings-mounts.test.js +46 -7
  128. package/dist/settings-schema.d.ts +6 -11
  129. package/dist/settings-schema.js +4 -8
  130. package/dist/settings-schema.test.d.ts +1 -0
  131. package/dist/settings-schema.test.js +35 -0
  132. package/dist/settings-workspaces.test.js +38 -63
  133. package/dist/spill-store.d.ts +1 -0
  134. package/dist/spill-store.js +17 -4
  135. package/dist/spill-store.test.js +31 -8
  136. package/dist/subprocess.d.ts +4 -0
  137. package/dist/subprocess.js +148 -162
  138. package/dist/subprocess.test.js +118 -8
  139. package/dist/terminal-preference.test.d.ts +1 -0
  140. package/dist/terminal-preference.test.js +62 -0
  141. package/dist/terminal-route.d.ts +10 -0
  142. package/dist/terminal-route.js +270 -0
  143. package/dist/terminal-route.test.d.ts +1 -0
  144. package/dist/terminal-route.test.js +265 -0
  145. package/dist/terminal-sessions.d.ts +69 -0
  146. package/dist/terminal-sessions.js +252 -0
  147. package/dist/terminal-shells.d.ts +22 -0
  148. package/dist/terminal-shells.js +99 -0
  149. package/dist/terminal-tab.test.d.ts +1 -0
  150. package/dist/terminal-tab.test.js +58 -0
  151. package/dist/terminal-targets.test.d.ts +1 -0
  152. package/dist/terminal-targets.test.js +43 -0
  153. package/dist/terminal-titles.test.d.ts +1 -0
  154. package/dist/terminal-titles.test.js +36 -0
  155. package/dist/test-support.d.ts +35 -5
  156. package/dist/test-support.js +91 -29
  157. package/dist/tool-defs.js +19 -4
  158. package/dist/tool-handlers.js +80 -28
  159. package/dist/tool-params.js +19 -5
  160. package/dist/version-compat.d.ts +4 -0
  161. package/dist/version-compat.js +29 -0
  162. package/dist/version-compat.test.d.ts +1 -0
  163. package/dist/version-compat.test.js +27 -0
  164. package/dist/volumes.test.js +1 -1
  165. package/dist/workspace-binding.d.ts +19 -10
  166. package/dist/workspace-binding.js +252 -78
  167. package/dist/workspace-binding.test.js +202 -27
  168. package/docs/architecture.md +71 -20
  169. package/docs/architecture.zh.md +62 -12
  170. package/docs/configuration.md +61 -20
  171. package/docs/configuration.zh.md +53 -19
  172. package/docs/development-prompt.md +72 -0
  173. package/docs/development-prompt.zh.md +69 -0
  174. package/docs/development.md +184 -29
  175. package/docs/development.zh.md +165 -26
  176. package/docs/install-dsh-and-dsh-podman.md +24 -21
  177. package/docs/install-dsh-and-dsh-podman.zh.md +20 -21
  178. package/docs/uninstall.md +83 -0
  179. package/docs/uninstall.zh.md +79 -0
  180. package/docs/update.md +120 -0
  181. package/docs/update.zh.md +114 -0
  182. package/docs/usage.md +108 -61
  183. package/docs/usage.zh.md +76 -38
  184. package/locale/en.json +6 -0
  185. package/locale/zh.json +6 -0
  186. package/package.json +58 -25
  187. package/quadlet/dsh-podman-orchestrator.container +46 -0
  188. package/quadlet/dsh.container +35 -0
  189. package/LICENSE.pkg +0 -17103
  190. package/dist/preferences.d.ts +0 -6
  191. package/dist/preferences.js +0 -27
@@ -1,5 +1,10 @@
1
1
  export declare const NS = "podman";
2
- export type ContainerPluginKey = "cardTitle" | "cardDescription" | "reload" | "reloading" | "notice" | "configTitle" | "defaultImage" | "socketsRoot" | "projectsRoot" | "defaultImageHint" | "save" | "discard" | "workspacesTitle" | "noContainers" | "createContainer" | "containersTitle" | "containerName" | "workspace" | "image" | "status" | "created" | "projects" | "remove" | "removePod" | "confirmRemovePod" | "recreate" | "recreateWithImage" | "imagesTitle" | "imageId" | "baseImage" | "imageTag" | "builtAt" | "packages" | "volumesTitle" | "createVolume" | "removeVolume" | "volumeName" | "secretsTitle" | "createSecret" | "secretName" | "secretCharset" | "selectImage" | "setSecret" | "removeSecret" | "removeImage" | "rebuildImage" | "rebuildAllImages" | "buildImage" | "build" | "buildImageTitle" | "pullImage" | "setDefaultImage" | "setDefaultImageTitle" | "baseImagesTitle" | "customImagesTitle" | "primitive" | "packageManager" | "parent" | "cancel" | "removeTag" | "env" | "secretEnv" | "envTitle" | "envKey" | "envValue" | "addEnv" | "removeEnv" | "secretLength" | "containerSecretsTitle" | "attachSecret" | "secretEnvName" | "detachSecret" | "none" | "unavailable" | "busy" | "confirmTitle" | "confirm" | "confirmRemoveContainer" | "confirmRecreate" | "confirmRemoveImage" | "confirmRebuildImage" | "confirmRebuildAllImages" | "confirmRemoveVolume" | "confirmSetSecret" | "confirmRemoveSecret" | "confirmDetachSecret" | "mountsTitle" | "addMount" | "mountKind" | "mountProject" | "mountProjectPath" | "browse" | "browseTitle" | "browseSelect" | "browseLoading" | "browseError" | "browseUnavailable" | "browseHidden" | "browseTruncated" | "browseOutsideRoot" | "mountDestination" | "pathsTitle" | "noPaths" | "editPaths" | "addPath" | "add" | "moveUp" | "moveDown" | "apply" | "dragToReorder" | "remountWaiting" | "remountApprove" | "remountReject" | "mountVolume" | "mountSecret" | "mountMode" | "readOnly" | "readWrite" | "remountReadOnly" | "remountReadWrite" | "confirmRemountReadOnly" | "confirmRemountReadWrite" | "confirmRemoveMount" | "cachesTitle" | "noCaches" | "cacheUsage" | "cacheKeepLatest" | "confirmCacheKeepLatest" | "cacheRemoveAll" | "confirmCacheRemoveAll" | "addContainer" | "invalidContainerName" | "containerNameTaken" | "invalidName" | "invalidImageId" | "terminalSignal" | "terminalExitCode" | "terminalRunning" | "terminalFailed" | "terminalDone" | "terminalNoOutput" | "terminalCollapseAria" | "terminalExpandAria" | "terminalExpandRest" | "toolTitle_container_bash" | "toolTitle_container_exec" | "toolTitle_container_read" | "toolTitle_container_write" | "toolTitle_container_edit" | "toolTitle_container_glob" | "toolTitle_container_grep" | "toolTitle_container_list" | "toolTitle_container_start" | "toolTitle_container_recreate" | "toolTitle_container_remove" | "toolTitle_container_mount_list" | "toolTitle_container_mount_add" | "toolTitle_container_mount_remove" | "toolTitle_container_mount_update" | "toolTitle_container_path_set" | "toolTitle_container_path_add" | "toolTitle_container_path_remove" | "toolTitle_container_secret_add" | "toolTitle_container_secret_remove" | "toolTitle_image_list" | "toolTitle_image_get" | "toolTitle_image_build" | "toolTitle_image_rebuild" | "toolTitle_image_rebuild_all" | "toolTitle_image_remove" | "toolTitle_volume_list" | "toolTitle_volume_create" | "toolTitle_volume_remove" | "toolTitle_secret_list" | "toolTitle_secret_create" | "toolTitle_secret_remove" | "toolTitle_daemon_start" | "toolTitle_daemon_list" | "toolTitle_daemon_logs" | "toolTitle_daemon_restart" | "toolTitle_daemon_stop";
2
+ export type ContainerPluginKey = "cardTitle" | "cardDescription" | "versionMismatchMajor" | "versionMismatchMinor" | "versionsTitle" | "orchestrator" | "versionUnknown" | "dsh" | "copyVersions" | "copied" | "copyFailed" | "reload" | "notice" | "defaultImage" | "defaultImageHint" | "defaultEnvironment" | "defaultEnvironmentHint" | "gitIdentity" | "gitName" | "gitEmail" | "gitIdentityHint" | "applyDefaults" | "confirmApplyDefaults" | "clear" | "save" | "discard" | "workspacesTitle" | "noContainers" | "createContainer" | "containerName" | "image" | "status" | "created" | "projects" | "remove" | "removePod" | "confirmRemovePod" | "recreate" | "recreateWithImage" | "imagesTitle" | "imageId" | "imageTag" | "builtAt" | "packages" | "volumesTitle" | "createVolume" | "removeVolume" | "volumeName" | "secretsTitle" | "createSecret" | "secretName" | "secretCharset" | "selectImage" | "setSecret" | "removeSecret" | "removeImage" | "rebuildImage" | "rebuildAllImages" | "buildImage" | "build" | "buildImageTitle" | "pullImage" | "setDefaultImage" | "setDefaultImageTitle" | "baseImagesTitle" | "customImagesTitle" | "primitive" | "packageManager" | "parent" | "cancel" | "removeTag" | "env" | "secretEnv" | "envTitle" | "envKey" | "envValue" | "addEnv" | "removeEnv" | "secretLength" | "containerSecretsTitle" | "attachSecret" | "secretEnvName" | "detachSecret" | "none" | "unavailable" | "busy" | "confirmTitle" | "confirm" | "confirmRemoveContainer" | "confirmRecreate" | "confirmRemoveImage" | "confirmRebuildImage" | "confirmRebuildAllImages" | "confirmRemoveVolume" | "confirmSetSecret" | "confirmRemoveSecret" | "confirmDetachSecret" | "mountsTitle" | "addMount" | "mountKind" | "mountProject" | "mountProjectPath" | "browse" | "browseTitle" | "browseSelect" | "browseLoading" | "browseError" | "browseUnavailable" | "browseHidden" | "browseTruncated" | "browseOutsideRoot" | "mountDestination" | "pathsTitle" | "noPaths" | "editPaths" | "addPath" | "add" | "moveUp" | "moveDown" | "apply" | "dragToReorder" | "remountWaiting" | "remountApprove" | "remountReject" | "mountVolume" | "mountSecret" | "mountTmpfs" | "mountAt" | "mountMode" | "readOnly" | "readWrite" | "mountReadOnlySuffix" | "mountReadWriteSuffix" | "remountReadOnly" | "remountReadWrite" | "confirmRemountReadOnly" | "confirmRemountReadWrite" | "confirmRemoveMount" | "cachesTitle" | "noCaches" | "cacheUsage" | "cacheKeepLatest" | "confirmCacheKeepLatest" | "cacheRemoveAll" | "confirmCacheRemoveAll" | "addContainer" | "invalidContainerName" | "containerNameTaken" | "invalidName" | "invalidImageId" | "terminalSignal" | "terminalExitCode" | "terminalNoExitCode" | "terminalRunning" | "terminalFailed" | "terminalDone" | "terminalNoOutput" | "terminalCollapseAria" | "terminalExpandAria" | "terminalExpandRest" | "toolTitle_container_bash" | "toolTitle_container_exec" | "toolTitle_container_read" | "toolTitle_container_write" | "toolTitle_container_edit" | "toolTitle_container_glob" | "toolTitle_container_grep" | "toolTitle_container_list" | "toolTitle_container_start" | "toolTitle_container_recreate" | "toolTitle_container_remove" | "toolTitle_container_mount_list" | "toolTitle_container_mount_add" | "toolTitle_container_mount_remove" | "toolTitle_container_mount_update" | "toolTitle_container_path_set" | "toolTitle_container_path_add" | "toolTitle_container_path_remove" | "toolTitle_container_secret_add" | "toolTitle_container_secret_remove" | "toolTitle_image_list" | "toolTitle_image_get" | "toolTitle_image_build" | "toolTitle_image_rebuild" | "toolTitle_image_rebuild_all" | "toolTitle_image_remove" | "toolTitle_volume_list" | "toolTitle_volume_create" | "toolTitle_volume_remove" | "toolTitle_secret_list" | "toolTitle_secret_create" | "toolTitle_secret_remove" | "toolTitle_daemon_start" | "toolTitle_daemon_list" | "toolTitle_daemon_logs" | "toolTitle_daemon_restart" | "toolTitle_daemon_stop" | "terminalTabTitle" | "terminalGuideTitle" | "terminalGuideDescription" | "terminalShortcut" | "terminalShortcutNoSession" | "terminalContainer" | "terminalShell" | "terminalDefaultContainer" | "terminalStart" | "terminalConnect" | "terminalReconnect" | "terminalStatusConnecting" | "terminalStatusRunning" | "terminalStatusExited" | "terminalStatusDetached" | "terminalNoShells" | "terminalShellsFailed" | "terminalLoading";
3
+ /**
4
+ * Translate one key, interpolating `{name}` placeholders when given. Components
5
+ * that build dialog copy declare this so they can name their subject.
6
+ */
7
+ export type Translate = (key: ContainerPluginKey, params?: Record<string, string>) => string;
3
8
  export declare const en: Record<ContainerPluginKey, string>;
4
9
  export declare const zh: Record<ContainerPluginKey, string>;
5
10
  declare module "@deepseek-ai/dsh-client-ui-slots" {
@@ -5,34 +5,45 @@ export const NS = "podman";
5
5
  export const en = {
6
6
  cardTitle: "dsh-podman",
7
7
  cardDescription: "Manage the guest containers and their images.",
8
+ versionMismatchMajor: "This plugin's major version differs from the orchestrator's; update the dsh image or the orchestrator image so both match.",
9
+ versionMismatchMinor: "This plugin and the orchestrator have compatible but different versions; consider updating both images.",
10
+ versionsTitle: "Versions",
11
+ orchestrator: "dsh-podman-orchestrator",
12
+ versionUnknown: "unknown",
13
+ dsh: "dsh",
14
+ copyVersions: "Copy versions",
15
+ copied: "Copied",
16
+ copyFailed: "Copy failed",
8
17
  reload: "Reload this view",
9
- reloading: "Reloading…",
10
18
  notice: "Notice",
11
- configTitle: "Configuration",
12
19
  defaultImage: "Default image",
13
- socketsRoot: "Sockets root",
14
- projectsRoot: "Projects root",
15
20
  defaultImageHint: "Image used when a workspace has no image of its own.",
21
+ defaultEnvironment: "Default environment",
22
+ defaultEnvironmentHint: "Seeded into a container when it is created. Edit a container's own environment and recreate it to change or remove a value for that container.",
23
+ gitIdentity: "Git identity",
24
+ gitName: "Name",
25
+ gitEmail: "Email",
26
+ gitIdentityHint: "Fills GIT_AUTHOR_NAME/EMAIL and GIT_COMMITTER_NAME/EMAIL for new containers, so commits made inside them are attributed to you.",
27
+ applyDefaults: "Apply default environment variables",
28
+ confirmApplyDefaults: "Add the default environment variables to the containers that are missing them? Matching running containers are recreated (their processes and daemons stop); existing values are kept and stopped containers are left alone.",
29
+ clear: "Clear",
16
30
  save: "Save",
17
31
  discard: "Discard",
18
32
  workspacesTitle: "Workspaces",
19
33
  noContainers: "This workspace has no containers yet.",
20
34
  createContainer: "Create container",
21
- containersTitle: "Containers",
22
35
  containerName: "Container",
23
- workspace: "Workspace",
24
36
  image: "Image",
25
37
  status: "Status",
26
38
  created: "Created",
27
39
  projects: "Projects",
28
40
  remove: "Remove",
29
41
  removePod: "Remove pod",
30
- confirmRemovePod: "Remove this workspace's pod and all its containers? Volume and project data is kept.",
42
+ confirmRemovePod: "Remove the pod of workspace “{workspace}” and all its containers? Volume and project data is kept.",
31
43
  recreate: "Recreate",
32
44
  recreateWithImage: "Recreate with image",
33
45
  imagesTitle: "Images",
34
46
  imageId: "Image ID",
35
- baseImage: "Base image",
36
47
  imageTag: "Tag",
37
48
  builtAt: "Built at",
38
49
  packages: "Packages",
@@ -80,15 +91,15 @@ export const en = {
80
91
  busy: "Working…",
81
92
  confirmTitle: "Confirm action",
82
93
  confirm: "Confirm",
83
- confirmRemoveContainer: "Remove the default container of this workspace?",
84
- confirmRecreate: "Recreate this container? Its ephemeral state is lost.",
85
- confirmRemoveImage: "Remove this image? Containers using it must be recreated from another image.",
86
- confirmRebuildImage: "Rebuild this image in place?",
94
+ confirmRemoveContainer: "Remove container “{container}” from workspace “{workspace}”?",
95
+ confirmRecreate: "Recreate container “{container}” in workspace “{workspace}”? Its ephemeral state is lost.",
96
+ confirmRemoveImage: "Remove image “{image}”? Containers using it must be recreated from another image.",
97
+ confirmRebuildImage: "Rebuild image “{image}” in place?",
87
98
  confirmRebuildAllImages: "Rebuild every image in dependency order (base first)?",
88
- confirmRemoveVolume: "Remove this volume and its data?",
89
- confirmSetSecret: "Overwrite this secret's value?",
90
- confirmRemoveSecret: "Remove this secret? Containers using it must drop it first.",
91
- confirmDetachSecret: "Detach this secret environment variable from the container?",
99
+ confirmRemoveVolume: "Remove volume “{volume}” and its data?",
100
+ confirmSetSecret: "Overwrite the value of secret “{secret}”?",
101
+ confirmRemoveSecret: "Remove secret “{secret}”? Containers using it must drop it first.",
102
+ confirmDetachSecret: "Detach secret “{secret}” from environment variable {env}?",
92
103
  mountsTitle: "Mounts",
93
104
  addMount: "Add mount",
94
105
  mountKind: "Kind",
@@ -118,14 +129,18 @@ export const en = {
118
129
  remountReject: "Reject",
119
130
  mountVolume: "Volume",
120
131
  mountSecret: "Secret",
132
+ mountTmpfs: "tmpfs",
133
+ mountAt: "at",
121
134
  mountMode: "Mode",
122
135
  readOnly: "Read-only",
123
136
  readWrite: "Read-write",
137
+ mountReadOnlySuffix: "(ro)",
138
+ mountReadWriteSuffix: "(rw)",
124
139
  remountReadOnly: "Remount as read-only",
125
140
  remountReadWrite: "Remount as read-write",
126
- confirmRemountReadOnly: "Remount this mount as read-only and recreate the container?",
127
- confirmRemountReadWrite: "Remount this mount as read-write and recreate the container?",
128
- confirmRemoveMount: "Remove this mount from the container and recreate it?",
141
+ confirmRemountReadOnly: "Remount {mount} as read-only and recreate the container?",
142
+ confirmRemountReadWrite: "Remount {mount} as read-write and recreate the container?",
143
+ confirmRemoveMount: "Remove mount {mount} from the container and recreate it?",
129
144
  cachesTitle: "Package caches",
130
145
  noCaches: "No package cache is configured.",
131
146
  cacheUsage: "{size} · {n} files",
@@ -140,6 +155,7 @@ export const en = {
140
155
  invalidImageId: "Start with a letter, digit, or '_'; only letters, digits, '.', '_', '-', '/', ':' (max 128).",
141
156
  terminalSignal: "signal {signal}",
142
157
  terminalExitCode: "exit code {code}",
158
+ terminalNoExitCode: "no exit code",
143
159
  terminalRunning: "Running",
144
160
  terminalFailed: "Failed",
145
161
  terminalDone: "Done",
@@ -184,38 +200,67 @@ export const en = {
184
200
  toolTitle_daemon_logs: "Daemon logs",
185
201
  toolTitle_daemon_restart: "Restart daemon",
186
202
  toolTitle_daemon_stop: "Stop daemon",
203
+ terminalTabTitle: "Terminal",
204
+ terminalGuideTitle: "New terminal",
205
+ terminalGuideDescription: "Run commands in the Session workspace",
206
+ terminalShortcut: "New terminal",
207
+ terminalShortcutNoSession: "Select a session first",
208
+ terminalContainer: "Container",
209
+ terminalShell: "Shell",
210
+ terminalDefaultContainer: "Default container",
211
+ terminalStart: "Start",
212
+ terminalConnect: "Connect",
213
+ terminalReconnect: "Reconnect",
214
+ terminalStatusConnecting: "Connecting…",
215
+ terminalStatusRunning: "Connected",
216
+ terminalStatusExited: "Process exited ({code})",
217
+ terminalStatusDetached: "Detached (opened elsewhere)",
218
+ terminalNoShells: "No shells available",
219
+ terminalShellsFailed: "Could not list shells: {message}",
220
+ terminalLoading: "Loading…",
187
221
  };
188
222
  export const zh = {
189
223
  cardTitle: "dsh-podman",
190
224
  cardDescription: "管理工作区容器及其镜像。",
225
+ versionMismatchMajor: "此插件与 orchestrator 的主版本不同;请更新 dsh 镜像或 orchestrator 镜像,使两者一致。",
226
+ versionMismatchMinor: "此插件与 orchestrator 的版本不同但兼容;建议同时更新两个镜像。",
227
+ versionsTitle: "版本",
228
+ orchestrator: "dsh-podman-orchestrator",
229
+ versionUnknown: "未知",
230
+ dsh: "dsh",
231
+ copyVersions: "复制版本",
232
+ copied: "已复制",
233
+ copyFailed: "复制失败",
191
234
  reload: "刷新此视图",
192
- reloading: "刷新中…",
193
235
  notice: "提示",
194
- configTitle: "配置",
195
236
  defaultImage: "默认镜像",
196
- socketsRoot: "套接字根目录",
197
- projectsRoot: "项目根目录",
198
237
  defaultImageHint: "工作区没有自带镜像时使用的镜像。",
238
+ defaultEnvironment: "默认环境变量",
239
+ defaultEnvironmentHint: "容器创建时注入的环境变量。编辑容器自身的环境变量后重建该容器,即可修改或移除其中的某一项。",
240
+ gitIdentity: "Git 身份",
241
+ gitName: "姓名",
242
+ gitEmail: "邮箱",
243
+ gitIdentityHint: "为新容器填入 GIT_AUTHOR_NAME/EMAIL 与 GIT_COMMITTER_NAME/EMAIL,使容器内提交的提交者信息正确。",
244
+ applyDefaults: "应用默认环境变量",
245
+ confirmApplyDefaults: "为缺少默认环境变量的容器补上这些变量?匹配的运行中容器会被重建(其进程与守护进程会停止);已有值保持不变,已停止的容器不会被处理。",
246
+ clear: "清除",
199
247
  save: "保存",
200
248
  discard: "放弃",
201
249
  workspacesTitle: "工作区",
202
250
  noContainers: "该工作区还没有容器。",
203
251
  createContainer: "创建容器",
204
- containersTitle: "容器",
205
252
  containerName: "容器",
206
- workspace: "工作区",
207
253
  image: "镜像",
208
254
  status: "状态",
209
255
  created: "创建时间",
210
256
  projects: "项目",
211
257
  remove: "移除",
212
258
  removePod: "移除 Pod",
213
- confirmRemovePod: "移除该工作区的 Pod 及其所有容器?卷和项目数据会保留。",
259
+ confirmRemovePod: "移除工作区“{workspace}”的 Pod 及其所有容器?卷和项目数据会保留。",
214
260
  recreate: "重建",
215
261
  recreateWithImage: "使用镜像重建",
216
262
  imagesTitle: "镜像",
217
263
  imageId: "镜像 ID",
218
- baseImage: "基础镜像",
219
264
  imageTag: "标签",
220
265
  builtAt: "构建时间",
221
266
  packages: "软件包",
@@ -263,15 +308,15 @@ export const zh = {
263
308
  busy: "处理中…",
264
309
  confirmTitle: "确认操作",
265
310
  confirm: "确认",
266
- confirmRemoveContainer: "移除该工作区的默认容器?",
267
- confirmRecreate: "重建该容器?其临时状态将丢失。",
268
- confirmRemoveImage: "移除该镜像?使用它的容器需要用其他镜像重建。",
269
- confirmRebuildImage: "就地重建该镜像?",
311
+ confirmRemoveContainer: "移除工作区“{workspace}”中的容器“{container}”?",
312
+ confirmRecreate: "重建工作区“{workspace}”中的容器“{container}”?其临时状态将丢失。",
313
+ confirmRemoveImage: "移除镜像“{image}”?使用它的容器需要用其他镜像重建。",
314
+ confirmRebuildImage: "就地重建镜像“{image}”?",
270
315
  confirmRebuildAllImages: "按依赖顺序重建全部镜像(先基础镜像)?",
271
- confirmRemoveVolume: "移除该卷及其数据?",
272
- confirmSetSecret: "覆盖该机密的值?",
273
- confirmRemoveSecret: "移除该机密?使用它的容器需先移除注入。",
274
- confirmDetachSecret: "从容器上移除该机密环境变量?",
316
+ confirmRemoveVolume: "移除卷“{volume}”及其数据?",
317
+ confirmSetSecret: "覆盖机密“{secret}”的值?",
318
+ confirmRemoveSecret: "移除机密“{secret}”?使用它的容器需先移除注入。",
319
+ confirmDetachSecret: "从环境变量 {env} 上移除机密“{secret}”?",
275
320
  mountsTitle: "挂载",
276
321
  addMount: "添加挂载",
277
322
  mountKind: "类型",
@@ -301,14 +346,18 @@ export const zh = {
301
346
  remountReject: "拒绝",
302
347
  mountVolume: "卷",
303
348
  mountSecret: "机密",
349
+ mountTmpfs: "tmpfs",
350
+ mountAt: "位于",
304
351
  mountMode: "模式",
305
352
  readOnly: "只读",
306
353
  readWrite: "读写",
354
+ mountReadOnlySuffix: "(只读)",
355
+ mountReadWriteSuffix: "(读写)",
307
356
  remountReadOnly: "重新挂载为只读",
308
357
  remountReadWrite: "重新挂载为读写",
309
- confirmRemountReadOnly: "将该挂载重新挂载为只读并重建容器?",
310
- confirmRemountReadWrite: "将该挂载重新挂载为读写并重建容器?",
311
- confirmRemoveMount: "从容器中移除该挂载并重建容器?",
358
+ confirmRemountReadOnly: "将 {mount} 重新挂载为只读并重建容器?",
359
+ confirmRemountReadWrite: "将 {mount} 重新挂载为读写并重建容器?",
360
+ confirmRemoveMount: "从容器中移除挂载 {mount} 并重建容器?",
312
361
  cachesTitle: "软件包缓存",
313
362
  noCaches: "未配置软件包缓存。",
314
363
  cacheUsage: "{size} · {n} 个文件",
@@ -323,6 +372,7 @@ export const zh = {
323
372
  invalidImageId: "以字母、数字或 '_' 开头,仅可使用字母、数字、'.'、'_'、'-'、'/'、':'(最长 128 个字符)。",
324
373
  terminalSignal: "信号 {signal}",
325
374
  terminalExitCode: "退出码 {code}",
375
+ terminalNoExitCode: "无退出码",
326
376
  terminalRunning: "运行中",
327
377
  terminalFailed: "失败",
328
378
  terminalDone: "已完成",
@@ -367,4 +417,22 @@ export const zh = {
367
417
  toolTitle_daemon_logs: "守护进程日志",
368
418
  toolTitle_daemon_restart: "重启守护进程",
369
419
  toolTitle_daemon_stop: "停止守护进程",
420
+ terminalTabTitle: "终端",
421
+ terminalGuideTitle: "新建终端",
422
+ terminalGuideDescription: "在会话工作区运行命令",
423
+ terminalShortcut: "新建终端",
424
+ terminalShortcutNoSession: "请先选择会话",
425
+ terminalContainer: "容器",
426
+ terminalShell: "Shell",
427
+ terminalDefaultContainer: "默认容器",
428
+ terminalStart: "启动",
429
+ terminalConnect: "连接",
430
+ terminalReconnect: "重新连接",
431
+ terminalStatusConnecting: "正在连接…",
432
+ terminalStatusRunning: "已连接",
433
+ terminalStatusExited: "进程已退出({code})",
434
+ terminalStatusDetached: "已在其他位置打开",
435
+ terminalNoShells: "没有可用的 Shell",
436
+ terminalShellsFailed: "读取 Shell 失败:{message}",
437
+ terminalLoading: "正在加载…",
370
438
  };
@@ -0,0 +1,11 @@
1
+ import type { InjectFace, PropsLocale, PropsRuntime } from "@deepseek-ai/dsh-client-ui-slots";
2
+ import { type ReactNode } from "react";
3
+ import type { ContainerCardFace } from "./container-card-controller.js";
4
+ import { NS } from "./locales.js";
5
+ /** The card snapshot the guide reads; the tab's own actions open the terminal. */
6
+ export interface PodmanTerminalGuideInjected extends ContainerCardFace {
7
+ /** Owning session, used by the shells route and the injection contract. */
8
+ readonly sessionId: string;
9
+ }
10
+ export type PodmanTerminalGuideProps = PropsRuntime<"sidebar.right.tab.guide.entry"> & PropsLocale<typeof NS> & InjectFace<PodmanTerminalGuideInjected>;
11
+ export declare function PodmanTerminalGuide(props: PodmanTerminalGuideProps): ReactNode;
@@ -0,0 +1,208 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
3
+ //
4
+ // SPDX-License-Identifier: MIT
5
+ // The Podman terminal's guide card: pick a container and one of the shells that
6
+ // container really offers, then open a new terminal tab bound to that target in
7
+ // the Session's own workspace. It reads the same settings-card snapshot as the
8
+ // tab body and never asks for a workspace, because each Session has exactly one.
9
+ import { Button, PluginArtworkTerminal, } from "@deepseek-ai/dsh-client-ui-primitives";
10
+ import { useEffect, useState } from "react";
11
+ import { fieldLabel, fieldSelect, hint } from "./container-card-styles.js";
12
+ import { ContainerField } from "./podman-terminal.js";
13
+ import { PODMAN_TERMINAL_KIND } from "./terminal-tab.js";
14
+ import { readTerminalTarget, writeTerminalTarget, } from "./terminal-preference.js";
15
+ import { containerOptions, validContainer, validShell, } from "./terminal-targets.js";
16
+ import { fetchTerminalShells, fetchTerminalTarget, } from "./terminal-transport.js";
17
+ export function PodmanTerminalGuide(props) {
18
+ const { t, sessionId } = props;
19
+ const { tab } = props.useTabInfo();
20
+ const state = props.useContainerCard((snapshot) => snapshot);
21
+ // The host resolves the Session's workspace and reports it when it cannot.
22
+ const [target, setTarget] = useState({ phase: "loading" });
23
+ const workspace = target.phase === "ready"
24
+ ? target.target.workspace
25
+ : undefined;
26
+ const workspaceSlug = target.phase === "ready"
27
+ ? target.target.workspaceSlug
28
+ : undefined;
29
+ const unknownWorkspace = target.phase === "failed";
30
+ const [container, setContainer] = useState(undefined);
31
+ const [shells, setShells] = useState({ phase: "loading" });
32
+ const [shell, setShell] = useState(undefined);
33
+ // The last target this browser started from the card, reused below while it
34
+ // is still valid. Read once: the card shows it, it does not track it.
35
+ const [stored] = useState(() => readTerminalTarget());
36
+ useEffect(() => {
37
+ props.reload();
38
+ }, [props.reload]);
39
+ useEffect(() => {
40
+ const controller = new AbortController();
41
+ setTarget({ phase: "loading" });
42
+ void fetchTerminalTarget(sessionId, controller.signal).then((resolved) => {
43
+ if (!controller.signal.aborted) {
44
+ setTarget({ phase: "ready", target: resolved });
45
+ }
46
+ }, (error) => {
47
+ if (controller.signal.aborted)
48
+ return;
49
+ setTarget({
50
+ phase: "failed",
51
+ message: error instanceof Error ? error.message : String(error),
52
+ });
53
+ });
54
+ return () => {
55
+ controller.abort();
56
+ };
57
+ }, [sessionId]);
58
+ // The empty value means the workspace's default container; the workspace
59
+ // row's own containerName is that container's podman name, which the
60
+ // orchestrator rejects, so it is never used as a target. The choice waits for
61
+ // the first snapshot, otherwise the empty default would pre-empt a remembered
62
+ // named container before the options are known.
63
+ useEffect(() => {
64
+ if (unknownWorkspace || workspace === undefined || container !== undefined) {
65
+ return;
66
+ }
67
+ if (state.busy)
68
+ return;
69
+ setContainer(validContainer(stored?.container, containerOptions(state.containers, workspaceSlug)));
70
+ }, [
71
+ unknownWorkspace,
72
+ workspace,
73
+ container,
74
+ state.busy,
75
+ state.containers,
76
+ workspaceSlug,
77
+ stored,
78
+ ]);
79
+ useEffect(() => {
80
+ if (workspace === undefined || workspace === "" || container === undefined) {
81
+ return;
82
+ }
83
+ const controller = new AbortController();
84
+ setShells({ phase: "loading" });
85
+ void fetchTerminalShells(workspace, container, sessionId, controller.signal).then((list) => {
86
+ if (controller.signal.aborted)
87
+ return;
88
+ setShells({ phase: "ready", shells: list });
89
+ setShell((previous) => previous ?? validShell(stored?.shell, list) ?? list[0]?.path);
90
+ }, (error) => {
91
+ if (controller.signal.aborted)
92
+ return;
93
+ setShells({
94
+ phase: "failed",
95
+ message: error instanceof Error ? error.message : String(error),
96
+ });
97
+ });
98
+ return () => {
99
+ controller.abort();
100
+ };
101
+ }, [workspace, container, sessionId]);
102
+ const shellList = shells.phase === "ready" ? shells.shells : [];
103
+ const ready = !unknownWorkspace && container !== undefined &&
104
+ shell !== undefined &&
105
+ shellList.length > 0;
106
+ return (_jsxs("div", { style: CARD_STYLE, "data-sidebar-right-guide-entry": props.kind, children: [_jsxs("div", { style: HEADER_STYLE, children: [_jsx("span", { style: ICON_STYLE, "aria-hidden": "true", children: _jsx(PluginArtworkTerminal, { size: 22 }) }), _jsxs("span", { style: TEXT_STYLE, children: [_jsx("span", { style: TITLE_STYLE, children: props.title }), props.description === undefined
107
+ ? null
108
+ : _jsx("span", { style: DESCRIPTION_STYLE, children: props.description })] })] }), state.workspaces.length === 0
109
+ ? (_jsx("p", { style: hint, role: "status", children: state.busy ? t("terminalLoading") : t("unavailable") }))
110
+ : (_jsxs(_Fragment, { children: [target.phase === "failed" && (_jsx("p", { style: hint, role: "alert", children: target.message })), _jsxs("div", { style: FIELDS_STYLE, children: [_jsx(ContainerField, { containers: state.containers, workspaceSlug: workspaceSlug, container: container, disabled: unknownWorkspace, label: t("terminalContainer"), defaultLabel: t("terminalDefaultContainer"), selectStyle: fieldSelect, onContainer: (value) => {
111
+ // The new container may not offer the current shell, so the
112
+ // shells effect re-picks one (remembered when still valid).
113
+ setContainer(value);
114
+ setShell(undefined);
115
+ } }), _jsx("span", { style: fieldLabel, children: t("terminalShell") }), _jsx("select", { style: fieldSelect, "aria-label": t("terminalShell"), value: shell ?? "", disabled: unknownWorkspace || shells.phase !== "ready" ||
116
+ shellList.length === 0, onChange: (event) => {
117
+ setShell(event.target.value);
118
+ }, children: shellList.length === 0
119
+ ? (_jsx("option", { value: "", children: unknownWorkspace
120
+ ? ""
121
+ : shells.phase === "loading"
122
+ ? t("terminalLoading")
123
+ : t("terminalNoShells") }))
124
+ : shellList.map((entry) => (_jsx("option", { value: entry.path, children: entry.name }, entry.path))) })] }), !unknownWorkspace && shells.phase === "failed" && (_jsx("p", { style: hint, role: "alert", children: t("terminalShellsFailed", { message: shells.message }) })), !unknownWorkspace && shells.phase === "loading" && (_jsx("p", { style: hint, role: "status", children: t("terminalLoading") })), !unknownWorkspace && shells.phase === "ready" &&
125
+ shellList.length === 0 && (_jsx("p", { style: hint, role: "status", children: t("terminalNoShells") })), _jsx("div", { style: ACTIONS_STYLE, children: _jsx(Button, { variant: "primary", size: "sm", disabled: !ready, onClick: () => {
126
+ if (container === undefined || shell === undefined)
127
+ return;
128
+ writeTerminalTarget({ container, shell });
129
+ // Replace the guide tab in place, exactly like the built-in
130
+ // guide cards, instead of adding a second terminal tab.
131
+ tab.actions.openTab(PODMAN_TERMINAL_KIND, {
132
+ replaceTab: true,
133
+ params: { container, shell },
134
+ });
135
+ }, children: t("terminalStart") }) })] }))] }));
136
+ }
137
+ // The card mirrors the harness guide capsule skin (`GuideBody .entry`): same
138
+ // padding, radius token, border and background as the entries beside it, so the
139
+ // glyph and title line up; the column layout and the internal gaps are ours
140
+ // because this card carries controls rather than being one clickable capsule.
141
+ const CARD_STYLE = {
142
+ display: "flex",
143
+ flexDirection: "column",
144
+ gap: "8px",
145
+ boxSizing: "border-box",
146
+ width: "100%",
147
+ padding: "14px 20px",
148
+ border: "0.5px solid var(--dsw-alias-border-l3)",
149
+ borderRadius: "var(--dsl-guide-entry-radius)",
150
+ background: "var(--dsw-alias-bg-layer-1)",
151
+ };
152
+ const HEADER_STYLE = {
153
+ display: "flex",
154
+ alignItems: "center",
155
+ gap: "14px",
156
+ minWidth: 0,
157
+ };
158
+ const ICON_STYLE = {
159
+ display: "flex",
160
+ flex: "none",
161
+ alignItems: "center",
162
+ justifyContent: "center",
163
+ width: "26px",
164
+ height: "26px",
165
+ color: "var(--dsw-alias-label-secondary)",
166
+ };
167
+ const TEXT_STYLE = {
168
+ display: "flex",
169
+ flex: 1,
170
+ flexDirection: "column",
171
+ gap: "2px",
172
+ minWidth: 0,
173
+ };
174
+ const TITLE_STYLE = {
175
+ overflow: "hidden",
176
+ color: "var(--dsw-alias-label-primary)",
177
+ fontSize: "14px",
178
+ lineHeight: 1.4,
179
+ whiteSpace: "nowrap",
180
+ textOverflow: "ellipsis",
181
+ };
182
+ const DESCRIPTION_STYLE = {
183
+ overflow: "hidden",
184
+ color: "var(--dsw-alias-label-tertiary)",
185
+ fontSize: "11px",
186
+ lineHeight: 1.4,
187
+ whiteSpace: "nowrap",
188
+ textOverflow: "ellipsis",
189
+ };
190
+ // A centred label/select grid: each pair is one row, so a narrow card can never
191
+ // wrap a label away from its control. The auto column sizes to the widest label
192
+ // (right-aligned by `fieldLabel`), the second is capped at the select width so
193
+ // both controls line up, and the pair is centred in the card.
194
+ const FIELDS_STYLE = {
195
+ display: "grid",
196
+ gridTemplateColumns: "auto minmax(0, 160px)",
197
+ gap: "8px",
198
+ alignItems: "center",
199
+ justifyContent: "center",
200
+ width: "100%",
201
+ };
202
+ const ACTIONS_STYLE = {
203
+ display: "flex",
204
+ flexWrap: "wrap",
205
+ justifyContent: "center",
206
+ gap: "8px",
207
+ alignItems: "center",
208
+ };
@@ -0,0 +1,7 @@
1
+ import type { InjectFace, PropsRuntime } from "@deepseek-ai/dsh-client-ui-slots";
2
+ import { type ReactNode } from "react";
3
+ /** Session identity the session-scope title registration injects. */
4
+ export interface PodmanTerminalTitleInjected {
5
+ readonly sessionId: string;
6
+ }
7
+ export declare function PodmanTerminalTitle(props: PropsRuntime<"sidebar.right.pane.tab.title"> & InjectFace<PodmanTerminalTitleInjected>): ReactNode;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useSyncExternalStore } from "react";
3
+ import { shellName } from "./terminal-targets.js";
4
+ import { subscribeTerminalTitles, terminalTitle } from "./terminal-titles.js";
5
+ export function PodmanTerminalTitle(props) {
6
+ const { tab } = props.useTabInfo();
7
+ const params = tab.navigation.params;
8
+ // Only the session-scope identity is available here, so the store is keyed the
9
+ // same way the host retains a terminal.
10
+ const key = `${props.sessionId}:${tab.id}`;
11
+ const fallback = shellName(params?.shell) ?? tab.title;
12
+ const title = useSyncExternalStore(subscribeTerminalTitles, () => terminalTitle(key) ?? fallback);
13
+ return (_jsxs("span", { style: CHIP_STYLE, children: [_jsx(TerminalGlyph, {}), _jsx("span", { style: TITLE_STYLE, children: title })] }));
14
+ }
15
+ // The built-in tab chip's 16px terminal prompt, drawn in the surrounding ink
16
+ // instead of the plugin artwork's fixed brand palette.
17
+ function TerminalGlyph() {
18
+ return (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: [_jsx("path", { d: "M3 4L7 8L3 12", stroke: "currentColor" }), _jsx("path", { d: "M9 12H13", stroke: "currentColor" })] }));
19
+ }
20
+ const CHIP_STYLE = {
21
+ display: "inline-flex",
22
+ alignItems: "center",
23
+ gap: "4px",
24
+ minWidth: 0,
25
+ };
26
+ const TITLE_STYLE = {
27
+ overflow: "hidden",
28
+ whiteSpace: "nowrap",
29
+ textOverflow: "ellipsis",
30
+ };
@@ -0,0 +1,26 @@
1
+ import type { InjectFace, PropsLocale, PropsRuntime } from "@deepseek-ai/dsh-client-ui-slots";
2
+ import { type ReactNode } from "react";
3
+ import type { ContainerView } from "./card-protocol.js";
4
+ import type { ContainerCardFace } from "./container-card-controller.js";
5
+ import { NS } from "./locales.js";
6
+ /** Everything the tab body is given: framework shares plus the injected card face. */
7
+ export interface PodmanTerminalInjected extends ContainerCardFace {
8
+ /** Owning session, injected by the session-scope registration. */
9
+ readonly sessionId: string;
10
+ }
11
+ export type PodmanTerminalProps = PropsRuntime<"sidebar.right.pane.tab"> & PropsLocale<typeof NS> & InjectFace<PodmanTerminalInjected>;
12
+ /** The labelled container picker shared by the body and the guide card. */
13
+ interface ContainerFieldProps {
14
+ readonly containers: readonly ContainerView[];
15
+ readonly workspaceSlug: string | undefined;
16
+ readonly container: string | undefined;
17
+ readonly disabled: boolean;
18
+ readonly label: string;
19
+ readonly defaultLabel: string;
20
+ /** Select skin; stacked cards pass a full-width variant. */
21
+ readonly selectStyle?: React.CSSProperties;
22
+ readonly onContainer: (container: string) => void;
23
+ }
24
+ export declare function ContainerField(props: ContainerFieldProps): ReactNode;
25
+ export declare function PodmanTerminal(props: PodmanTerminalProps): ReactNode;
26
+ export {};