@exagone313/dsh-podman 0.2.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/README.zh.md +41 -0
  4. package/cordis.patch.yml +17 -0
  5. package/dist/approval-reasons.d.ts +129 -0
  6. package/dist/approval-reasons.js +253 -0
  7. package/dist/approval-reasons.test.d.ts +1 -0
  8. package/dist/approval-reasons.test.js +115 -0
  9. package/dist/approval.d.ts +29 -0
  10. package/dist/approval.js +412 -0
  11. package/dist/approval.test.d.ts +1 -0
  12. package/dist/approval.test.js +462 -0
  13. package/dist/card-route.d.ts +15 -0
  14. package/dist/card-route.js +478 -0
  15. package/dist/card-route.test.d.ts +1 -0
  16. package/dist/card-route.test.js +181 -0
  17. package/dist/card-test-support.d.ts +15 -0
  18. package/dist/card-test-support.js +160 -0
  19. package/dist/client/ContainerCard.d.ts +6 -0
  20. package/dist/client/ContainerCard.js +79 -0
  21. package/dist/client/card-client.d.ts +6 -0
  22. package/dist/client/card-client.js +47 -0
  23. package/dist/client/card-protocol.d.ts +101 -0
  24. package/dist/client/card-protocol.js +10 -0
  25. package/dist/client/container-card-caches.d.ts +10 -0
  26. package/dist/client/container-card-caches.js +31 -0
  27. package/dist/client/container-card-controller.d.ts +107 -0
  28. package/dist/client/container-card-controller.js +207 -0
  29. package/dist/client/container-card-create-modal.d.ts +24 -0
  30. package/dist/client/container-card-create-modal.js +109 -0
  31. package/dist/client/container-card-directory-styles.d.ts +5 -0
  32. package/dist/client/container-card-directory-styles.js +246 -0
  33. package/dist/client/container-card-directory.d.ts +12 -0
  34. package/dist/client/container-card-directory.js +144 -0
  35. package/dist/client/container-card-editors.d.ts +30 -0
  36. package/dist/client/container-card-editors.js +116 -0
  37. package/dist/client/container-card-images.d.ts +37 -0
  38. package/dist/client/container-card-images.js +35 -0
  39. package/dist/client/container-card-paths.d.ts +20 -0
  40. package/dist/client/container-card-paths.js +88 -0
  41. package/dist/client/container-card-row.d.ts +30 -0
  42. package/dist/client/container-card-row.js +54 -0
  43. package/dist/client/container-card-secrets.d.ts +21 -0
  44. package/dist/client/container-card-secrets.js +71 -0
  45. package/dist/client/container-card-shared.d.ts +55 -0
  46. package/dist/client/container-card-shared.js +152 -0
  47. package/dist/client/container-card-styles.d.ts +21 -0
  48. package/dist/client/container-card-styles.js +143 -0
  49. package/dist/client/container-card-volumes.d.ts +12 -0
  50. package/dist/client/container-card-volumes.js +37 -0
  51. package/dist/client/container-card-workspace.d.ts +31 -0
  52. package/dist/client/container-card-workspace.js +24 -0
  53. package/dist/client/directory-picker.d.ts +12 -0
  54. package/dist/client/directory-picker.js +30 -0
  55. package/dist/client/index.d.ts +5 -0
  56. package/dist/client/index.js +4419 -0
  57. package/dist/client/locales.d.ts +9 -0
  58. package/dist/client/locales.js +370 -0
  59. package/dist/client/read-only-approval.d.ts +8 -0
  60. package/dist/client/read-only-approval.js +63 -0
  61. package/dist/client/slot-contract.d.ts +12 -0
  62. package/dist/client/slot-contract.js +4 -0
  63. package/dist/client/terminal-styles.d.ts +5 -0
  64. package/dist/client/terminal-styles.js +31 -0
  65. package/dist/client/tool-views.d.ts +8 -0
  66. package/dist/client/tool-views.js +241 -0
  67. package/dist/containers.test.d.ts +1 -0
  68. package/dist/containers.test.js +443 -0
  69. package/dist/daemons.test.d.ts +1 -0
  70. package/dist/daemons.test.js +153 -0
  71. package/dist/fs-provider.d.ts +23 -0
  72. package/dist/fs-provider.js +184 -0
  73. package/dist/fs-provider.test.d.ts +1 -0
  74. package/dist/fs-provider.test.js +260 -0
  75. package/dist/generated/version.d.ts +2 -0
  76. package/dist/generated/version.js +6 -0
  77. package/dist/grpc/proto/dshctl/v1/control.proto +133 -0
  78. package/dist/grpc/proto/dshguest/v1/guest.proto +79 -0
  79. package/dist/grpc/runtime-client.d.ts +5 -0
  80. package/dist/grpc/runtime-client.js +43 -0
  81. package/dist/guest-rpc.d.ts +62 -0
  82. package/dist/guest-rpc.js +391 -0
  83. package/dist/images.test.d.ts +1 -0
  84. package/dist/images.test.js +79 -0
  85. package/dist/index.d.ts +22 -0
  86. package/dist/index.js +140 -0
  87. package/dist/misc.test.d.ts +1 -0
  88. package/dist/misc.test.js +141 -0
  89. package/dist/mount-enums.d.ts +22 -0
  90. package/dist/mount-enums.js +81 -0
  91. package/dist/mount-input.d.ts +14 -0
  92. package/dist/mount-input.js +64 -0
  93. package/dist/mounts.test.d.ts +1 -0
  94. package/dist/mounts.test.js +408 -0
  95. package/dist/output-reader.d.ts +34 -0
  96. package/dist/output-reader.js +87 -0
  97. package/dist/paths.test.d.ts +1 -0
  98. package/dist/paths.test.js +74 -0
  99. package/dist/preferences.d.ts +6 -0
  100. package/dist/preferences.js +27 -0
  101. package/dist/project-path.d.ts +6 -0
  102. package/dist/project-path.js +73 -0
  103. package/dist/project-path.test.d.ts +1 -0
  104. package/dist/project-path.test.js +52 -0
  105. package/dist/prompts.d.ts +13 -0
  106. package/dist/prompts.js +149 -0
  107. package/dist/public.d.ts +4 -0
  108. package/dist/public.js +63 -0
  109. package/dist/read-only-shell.d.ts +14 -0
  110. package/dist/read-only-shell.js +150 -0
  111. package/dist/read-only-shell.test.d.ts +1 -0
  112. package/dist/read-only-shell.test.js +127 -0
  113. package/dist/secrets.test.d.ts +1 -0
  114. package/dist/secrets.test.js +181 -0
  115. package/dist/settings-commands.test.d.ts +1 -0
  116. package/dist/settings-commands.test.js +549 -0
  117. package/dist/settings-create.test.d.ts +1 -0
  118. package/dist/settings-create.test.js +394 -0
  119. package/dist/settings-mounts.test.d.ts +1 -0
  120. package/dist/settings-mounts.test.js +467 -0
  121. package/dist/settings-paths.test.d.ts +1 -0
  122. package/dist/settings-paths.test.js +65 -0
  123. package/dist/settings-schema.d.ts +14 -0
  124. package/dist/settings-schema.js +14 -0
  125. package/dist/settings-workspaces.test.d.ts +1 -0
  126. package/dist/settings-workspaces.test.js +265 -0
  127. package/dist/spill-store.d.ts +17 -0
  128. package/dist/spill-store.js +54 -0
  129. package/dist/spill-store.test.d.ts +1 -0
  130. package/dist/spill-store.test.js +59 -0
  131. package/dist/subprocess.d.ts +9 -0
  132. package/dist/subprocess.js +369 -0
  133. package/dist/subprocess.test.d.ts +1 -0
  134. package/dist/subprocess.test.js +234 -0
  135. package/dist/test-support.d.ts +328 -0
  136. package/dist/test-support.js +437 -0
  137. package/dist/tool-defs.d.ts +26 -0
  138. package/dist/tool-defs.js +188 -0
  139. package/dist/tool-handlers.d.ts +2 -0
  140. package/dist/tool-handlers.js +546 -0
  141. package/dist/tool-params.d.ts +803 -0
  142. package/dist/tool-params.js +494 -0
  143. package/dist/tool-schemas.d.ts +2 -0
  144. package/dist/tool-schemas.js +5 -0
  145. package/dist/tool-views.d.ts +2 -0
  146. package/dist/tool-views.js +56 -0
  147. package/dist/views.test.d.ts +1 -0
  148. package/dist/views.test.js +23 -0
  149. package/dist/volumes.test.d.ts +1 -0
  150. package/dist/volumes.test.js +40 -0
  151. package/dist/workspace-binding.d.ts +40 -0
  152. package/dist/workspace-binding.js +275 -0
  153. package/dist/workspace-binding.test.d.ts +1 -0
  154. package/dist/workspace-binding.test.js +337 -0
  155. package/docs/architecture.md +173 -0
  156. package/docs/architecture.zh.md +129 -0
  157. package/docs/configuration.md +160 -0
  158. package/docs/configuration.zh.md +147 -0
  159. package/docs/development.md +142 -0
  160. package/docs/development.zh.md +135 -0
  161. package/docs/install-dsh-and-dsh-podman.md +165 -0
  162. package/docs/install-dsh-and-dsh-podman.zh.md +145 -0
  163. package/docs/usage.md +393 -0
  164. package/docs/usage.zh.md +315 -0
  165. package/package.json +119 -0
@@ -0,0 +1,494 @@
1
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
2
+ //
3
+ // SPDX-License-Identifier: MIT
4
+ const containerParam = {
5
+ type: "string",
6
+ description: 'Logical container name; use "default" for the default workspace container.',
7
+ };
8
+ const imageIdParam = { type: "string", description: "Image short name." };
9
+ const packageListParam = {
10
+ type: "array",
11
+ items: { type: "string" },
12
+ description: "Package names to install.",
13
+ };
14
+ const mountModeParam = {
15
+ type: "string",
16
+ enum: ["read_only", "read_write"],
17
+ description: "Read mode of the mount. Defaults to read_only, except for tmpfs mounts, which are always read_write.",
18
+ };
19
+ const mountKindParam = {
20
+ type: "string",
21
+ enum: ["project", "tmpfs", "volume", "secret"],
22
+ description: "Kind of mount: a project bind, a tmpfs, a named volume, or a named secret.",
23
+ };
24
+ // A project mount names a path under the projects root, so it may include
25
+ // subdirectories: `team` mounts the project, `team/src` a directory inside it.
26
+ const projectPathDescription = 'Project path under the projects root to mount, e.g. "team" or "team/src".';
27
+ const projectMountItemParam = {
28
+ type: "object",
29
+ additionalProperties: false,
30
+ properties: {
31
+ project: { type: "string", description: projectPathDescription },
32
+ mode: mountModeParam,
33
+ destination: {
34
+ type: "string",
35
+ description: "Destination path inside the container (volume, tmpfs, and secret mounts only; project mounts always mount at their project root).",
36
+ },
37
+ kind: mountKindParam,
38
+ volume: { type: "string", description: "Volume name to mount." },
39
+ secret: { type: "string", description: "Secret name to mount as a file." },
40
+ },
41
+ required: [],
42
+ };
43
+ const mountsParam = {
44
+ type: "array",
45
+ items: projectMountItemParam,
46
+ description: "Optional mounts to apply: a project bind, a tmpfs, a named volume, or a secret.",
47
+ };
48
+ export const envParam = {
49
+ type: "object",
50
+ additionalProperties: { type: "string" },
51
+ description: "Environment variables.",
52
+ };
53
+ // The complete PATH-addition list, shared by the tools that set it outright.
54
+ const pathsParam = {
55
+ type: "array",
56
+ items: {
57
+ type: "string",
58
+ description: "Absolute directory to prepend to the container's PATH (no ':', NUL, or newline).",
59
+ },
60
+ description: "Complete ordered list of PATH additions, highest priority first. Replaces the current list; an empty list clears it.",
61
+ };
62
+ // The optional process identity a tool may request, shared by the tools that
63
+ // can run a process as another user.
64
+ const uidParam = {
65
+ type: "integer",
66
+ minimum: 0,
67
+ description: "Run the process as this uid (defaults to the container user).",
68
+ };
69
+ const gidParam = {
70
+ type: "integer",
71
+ minimum: 0,
72
+ description: "Run the process as this gid. Defaults to the uid when uid is set.",
73
+ };
74
+ const groupsParam = {
75
+ type: "array",
76
+ items: { type: "integer", minimum: 0 },
77
+ description: "Supplementary group ids; replaces the process's whole supplementary set.",
78
+ };
79
+ const descriptionParam = {
80
+ type: "string",
81
+ description: "Clear, concise description of what this command does in active voice, 5-10 words.",
82
+ };
83
+ const timeoutMsParam = {
84
+ type: "number",
85
+ description: "Timeout in milliseconds; the command is killed when it expires.",
86
+ };
87
+ export const imageListParameters = {
88
+ type: "object",
89
+ properties: {},
90
+ required: [],
91
+ };
92
+ export const imageGetParameters = {
93
+ type: "object",
94
+ properties: { imageId: imageIdParam },
95
+ required: ["imageId"],
96
+ };
97
+ export const imageBuildParameters = {
98
+ type: "object",
99
+ properties: {
100
+ imageId: imageIdParam,
101
+ parent: {
102
+ type: "string",
103
+ description: "Short name of the parent image (a base like archlinux/ubuntu/alpine, or an existing custom image).",
104
+ },
105
+ packages: packageListParam,
106
+ },
107
+ required: ["imageId", "parent", "packages"],
108
+ };
109
+ export const imageRebuildParameters = {
110
+ type: "object",
111
+ properties: { imageId: imageIdParam },
112
+ required: ["imageId"],
113
+ };
114
+ export const imageRebuildAllParameters = {
115
+ type: "object",
116
+ properties: {},
117
+ required: [],
118
+ };
119
+ export const imageRemoveParameters = {
120
+ type: "object",
121
+ properties: { imageId: imageIdParam },
122
+ required: ["imageId"],
123
+ };
124
+ export const containerListParameters = {
125
+ type: "object",
126
+ properties: {},
127
+ required: [],
128
+ };
129
+ export const containerStartParameters = {
130
+ type: "object",
131
+ properties: {
132
+ container: containerParam,
133
+ image: {
134
+ type: "string",
135
+ description: "Image short name (base or custom).",
136
+ },
137
+ mounts: mountsParam,
138
+ env: envParam,
139
+ secretEnv: { type: "object", additionalProperties: { type: "string" }, description: "Secret environment variables (env var name to secret short name)." },
140
+ paths: pathsParam,
141
+ },
142
+ required: ["container"],
143
+ };
144
+ export const containerRecreateParameters = {
145
+ type: "object",
146
+ properties: {
147
+ container: containerParam,
148
+ image: {
149
+ type: "string",
150
+ description: "Image ID to recreate the container with; defaults to the container's current image.",
151
+ },
152
+ mounts: mountsParam,
153
+ env: envParam,
154
+ secretEnv: { type: "object", additionalProperties: { type: "string" }, description: "Secret environment variables (env var name to secret short name)." },
155
+ paths: pathsParam,
156
+ },
157
+ required: ["container"],
158
+ };
159
+ export const containerMountListParameters = {
160
+ type: "object",
161
+ properties: { container: containerParam },
162
+ required: ["container"],
163
+ };
164
+ export const containerMountAddParameters = {
165
+ type: "object",
166
+ properties: {
167
+ container: containerParam,
168
+ kind: mountKindParam,
169
+ project: { type: "string", description: projectPathDescription },
170
+ destination: {
171
+ type: "string",
172
+ description: "Destination path inside the container (volume, tmpfs, and secret mounts only; project mounts always mount at their project root).",
173
+ },
174
+ mode: mountModeParam,
175
+ volume: { type: "string", description: "Named volume to mount." },
176
+ secret: { type: "string", description: "Named secret to mount." },
177
+ },
178
+ required: ["container"],
179
+ };
180
+ export const containerMountRemoveParameters = {
181
+ type: "object",
182
+ properties: {
183
+ container: containerParam,
184
+ kind: {
185
+ type: "string",
186
+ enum: ["project", "tmpfs", "volume", "secret"],
187
+ description: "Kind of mount to remove; inferred from secret or volume when omitted, otherwise project. Pass tmpfs explicitly: it has no name to infer from.",
188
+ },
189
+ project: {
190
+ type: "string",
191
+ description: "Project path of the project mount to remove.",
192
+ },
193
+ volume: {
194
+ type: "string",
195
+ description: "Named volume to remove; identifies the mount, so pass destination as well when the volume is mounted more than once.",
196
+ },
197
+ secret: {
198
+ type: "string",
199
+ description: "Named secret the removed mount must use; identifies the mount, so pass destination as well when the secret is mounted more than once.",
200
+ },
201
+ destination: {
202
+ type: "string",
203
+ description: "Destination path inside the container. Required for tmpfs; for a volume or secret it identifies the mount (and disambiguates one mounted more than once); not applicable to project mounts.",
204
+ },
205
+ },
206
+ required: ["container"],
207
+ };
208
+ export const containerMountUpdateParameters = {
209
+ type: "object",
210
+ properties: {
211
+ container: containerParam,
212
+ kind: {
213
+ type: "string",
214
+ enum: ["project", "volume"],
215
+ description: "Kind of mount to update; inferred from volume when omitted, otherwise project. Only project and volume mounts carry a mode.",
216
+ },
217
+ project: {
218
+ type: "string",
219
+ description: "Project path of the project mount to update.",
220
+ },
221
+ volume: {
222
+ type: "string",
223
+ description: "Named volume to update; identifies the mount, so pass destination as well when the volume is mounted more than once.",
224
+ },
225
+ destination: {
226
+ type: "string",
227
+ description: "Destination path inside the container; for a volume it identifies the mount (and disambiguates one mounted more than once); not applicable to project mounts.",
228
+ },
229
+ mode: mountModeParam,
230
+ },
231
+ required: ["container", "mode"],
232
+ };
233
+ export const containerPathSetParameters = {
234
+ type: "object",
235
+ properties: {
236
+ container: containerParam,
237
+ paths: pathsParam,
238
+ },
239
+ required: ["container", "paths"],
240
+ };
241
+ export const containerPathAddParameters = {
242
+ type: "object",
243
+ properties: {
244
+ container: containerParam,
245
+ path: {
246
+ type: "string",
247
+ description: "Absolute directory to prepend to the container's PATH (no ':', NUL, or newline). An existing entry is moved to the front.",
248
+ },
249
+ },
250
+ required: ["container", "path"],
251
+ };
252
+ export const containerPathRemoveParameters = {
253
+ type: "object",
254
+ properties: {
255
+ container: containerParam,
256
+ path: {
257
+ type: "string",
258
+ description: "PATH addition to remove. A directory that is only part of the container's default PATH cannot be removed.",
259
+ },
260
+ },
261
+ required: ["container", "path"],
262
+ };
263
+ export const containerRemoveParameters = {
264
+ type: "object",
265
+ properties: { container: containerParam },
266
+ required: ["container"],
267
+ };
268
+ export const volumeListParameters = {
269
+ type: "object",
270
+ properties: {},
271
+ required: [],
272
+ };
273
+ export const volumeCreateParameters = {
274
+ type: "object",
275
+ properties: { name: { type: "string", description: "Volume name to create." } },
276
+ required: ["name"],
277
+ };
278
+ export const volumeRemoveParameters = {
279
+ type: "object",
280
+ properties: { name: { type: "string", description: "Volume name to remove." } },
281
+ required: ["name"],
282
+ };
283
+ export const secretListParameters = {
284
+ type: "object",
285
+ properties: {},
286
+ required: [],
287
+ };
288
+ export const secretCreateParameters = {
289
+ type: "object",
290
+ properties: {
291
+ name: { type: "string", description: "Secret name to create." },
292
+ length: {
293
+ type: "integer",
294
+ minimum: 1,
295
+ description: "Length of the generated random value (default 32).",
296
+ },
297
+ charset: {
298
+ type: "string",
299
+ enum: ["alphanumeric", "hex", "base64url"],
300
+ description: "Character set for the generated random value.",
301
+ },
302
+ },
303
+ required: ["name"],
304
+ };
305
+ export const secretRemoveParameters = {
306
+ type: "object",
307
+ properties: { name: { type: "string", description: "Secret name to remove." } },
308
+ required: ["name"],
309
+ };
310
+ export const containerSecretAddParameters = {
311
+ type: "object",
312
+ properties: {
313
+ container: containerParam,
314
+ env: { type: "string", description: "Environment variable name." },
315
+ secret: { type: "string", description: "Named secret to inject." },
316
+ },
317
+ required: ["container", "env", "secret"],
318
+ };
319
+ export const containerSecretRemoveParameters = {
320
+ type: "object",
321
+ properties: {
322
+ container: containerParam,
323
+ env: { type: "string", description: "Environment variable name." },
324
+ },
325
+ required: ["container", "env"],
326
+ };
327
+ export const containerBashParameters = {
328
+ type: "object",
329
+ properties: {
330
+ container: containerParam,
331
+ command: { type: "string", description: "The shell command to execute." },
332
+ description: descriptionParam,
333
+ workdir: { type: "string", description: "Working directory." },
334
+ timeoutMs: timeoutMsParam,
335
+ env: envParam,
336
+ uid: uidParam,
337
+ gid: gidParam,
338
+ groups: groupsParam,
339
+ },
340
+ required: ["container", "command", "description"],
341
+ };
342
+ export const containerExecParameters = {
343
+ type: "object",
344
+ properties: {
345
+ container: containerParam,
346
+ argv: {
347
+ type: "array",
348
+ items: { type: "string" },
349
+ description: "The program and arguments to execute.",
350
+ },
351
+ description: descriptionParam,
352
+ workdir: { type: "string", description: "Working directory." },
353
+ timeoutMs: timeoutMsParam,
354
+ env: envParam,
355
+ uid: uidParam,
356
+ gid: gidParam,
357
+ groups: groupsParam,
358
+ },
359
+ required: ["container", "argv", "description"],
360
+ };
361
+ export const containerReadParameters = {
362
+ type: "object",
363
+ properties: {
364
+ container: containerParam,
365
+ file_path: {
366
+ type: "string",
367
+ description: "Path to read, resolved against the session working directory.",
368
+ },
369
+ offset: {
370
+ type: "integer",
371
+ minimum: 1,
372
+ description: "1-based first line to return. Defaults to 1.",
373
+ },
374
+ limit: {
375
+ type: "integer",
376
+ minimum: 1,
377
+ description: "Maximum number of lines to return. Defaults to 2000.",
378
+ },
379
+ },
380
+ required: ["container", "file_path"],
381
+ };
382
+ export const containerWriteParameters = {
383
+ type: "object",
384
+ properties: {
385
+ container: containerParam,
386
+ file_path: {
387
+ type: "string",
388
+ description: "Path to write, resolved against the session working directory.",
389
+ },
390
+ content: { type: "string", description: "Content to write." },
391
+ },
392
+ required: ["container", "file_path", "content"],
393
+ };
394
+ export const containerEditParameters = {
395
+ type: "object",
396
+ properties: {
397
+ container: containerParam,
398
+ file_path: {
399
+ type: "string",
400
+ description: "Path to edit, resolved against the session working directory.",
401
+ },
402
+ old_string: { type: "string", description: "Literal text to replace." },
403
+ new_string: { type: "string", description: "Replacement text." },
404
+ replace_all: {
405
+ type: "boolean",
406
+ description: "Replace every occurrence. Defaults to false; when false, old_string must appear exactly once.",
407
+ },
408
+ },
409
+ required: ["container", "file_path", "old_string", "new_string"],
410
+ };
411
+ export const containerGlobParameters = {
412
+ type: "object",
413
+ properties: {
414
+ container: containerParam,
415
+ pattern: { type: "string", description: "File pattern." },
416
+ path: {
417
+ type: "string",
418
+ description: "Directory to search in. Defaults to the session working directory.",
419
+ },
420
+ },
421
+ required: ["container", "pattern"],
422
+ };
423
+ export const containerGrepParameters = {
424
+ type: "object",
425
+ properties: {
426
+ container: containerParam,
427
+ pattern: { type: "string", description: "Regex to search for." },
428
+ path: {
429
+ type: "string",
430
+ description: "File or directory to search. Defaults to the session working directory.",
431
+ },
432
+ include: {
433
+ type: "string",
434
+ description: 'One glob filter for which files to search (e.g. "*.ts").',
435
+ },
436
+ },
437
+ required: ["container", "pattern"],
438
+ };
439
+ export const daemonStartParameters = {
440
+ type: "object",
441
+ properties: {
442
+ container: containerParam,
443
+ name: { type: "string", description: "Daemon name." },
444
+ argv: {
445
+ type: "array",
446
+ items: { type: "string" },
447
+ description: "Command to run as a daemon.",
448
+ },
449
+ cwd: { type: "string", description: "Working directory." },
450
+ env: envParam,
451
+ uid: uidParam,
452
+ gid: gidParam,
453
+ groups: groupsParam,
454
+ inheritEnv: {
455
+ type: "boolean",
456
+ description: "Inherit the container's environment (default true). When false the daemon receives only PATH and HOME plus env, so container and secret environment variables are not visible.",
457
+ },
458
+ },
459
+ required: ["container", "name", "argv"],
460
+ };
461
+ export const daemonListParameters = {
462
+ type: "object",
463
+ properties: { container: containerParam },
464
+ required: ["container"],
465
+ };
466
+ export const daemonStopParameters = {
467
+ type: "object",
468
+ properties: {
469
+ container: containerParam,
470
+ name: { type: "string", description: "Daemon name to stop." },
471
+ signal: { type: "string", description: 'Signal to send (e.g. "SIGTERM").' },
472
+ },
473
+ required: ["container", "name"],
474
+ };
475
+ export const daemonRestartParameters = {
476
+ type: "object",
477
+ properties: {
478
+ container: containerParam,
479
+ name: { type: "string", description: "Daemon name to restart." },
480
+ },
481
+ required: ["container", "name"],
482
+ };
483
+ export const daemonLogsParameters = {
484
+ type: "object",
485
+ properties: {
486
+ container: containerParam,
487
+ name: { type: "string", description: "Daemon name to read logs for." },
488
+ tailBytes: {
489
+ type: "integer",
490
+ description: "Maximum trailing bytes to retain per stream.",
491
+ },
492
+ },
493
+ required: ["container", "name"],
494
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./tool-params.js";
2
+ export * from "./tool-defs.js";
@@ -0,0 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
2
+ //
3
+ // SPDX-License-Identifier: MIT
4
+ export * from "./tool-params.js";
5
+ export * from "./tool-defs.js";
@@ -0,0 +1,2 @@
1
+ export declare function toolCallView(name: string, args: any): unknown;
2
+ export declare function toolResultView(name: string, _args: any, result: any): unknown;
@@ -0,0 +1,56 @@
1
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
2
+ //
3
+ // SPDX-License-Identifier: MIT
4
+ import { TOOL_UI } from "./tool-schemas.js";
5
+ // The command tools render as terminal cards; every other tool gets a generic
6
+ // card with its UI title. Views are recomputed on each delivery and never
7
+ // persisted (see the harness tool-presentation contract).
8
+ export function toolCallView(name, args) {
9
+ if (name === "container_bash" || name === "container_exec") {
10
+ const command = name === "container_bash"
11
+ ? String(args?.command ?? "")
12
+ : Array.isArray(args?.argv)
13
+ ? args.argv.map((item) => String(item)).join(" ")
14
+ : "";
15
+ return {
16
+ card: "terminal",
17
+ title: command,
18
+ ...(typeof args?.description === "string" && args.description !== ""
19
+ ? { description: args.description }
20
+ : {}),
21
+ };
22
+ }
23
+ const ui = TOOL_UI[name];
24
+ if (ui === undefined)
25
+ return undefined;
26
+ return { card: "generic", title: ui.title, kind: ui.kind };
27
+ }
28
+ export function toolResultView(name, _args, result) {
29
+ if (result?.isError)
30
+ return undefined;
31
+ if (name !== "container_bash" && name !== "container_exec")
32
+ return undefined;
33
+ const text = (result?.content ?? [])
34
+ .filter((block) => block?.type === "text")
35
+ .map((block) => block.text)
36
+ .join("");
37
+ let data;
38
+ try {
39
+ data = JSON.parse(text);
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ if (data === null || typeof data !== "object")
45
+ return undefined;
46
+ const output = [data.stdout, data.stderr]
47
+ .filter((value) => typeof value === "string" && value !== "")
48
+ .join("");
49
+ return {
50
+ card: "terminal",
51
+ output,
52
+ ...(data.signal
53
+ ? { signal: String(data.signal) }
54
+ : { exitCode: Number(data.exitCode ?? 0) }),
55
+ };
56
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
2
+ //
3
+ // SPDX-License-Identifier: MIT
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { SECRET_BEARING_CONTAINER } from "./test-support.js";
7
+ import { publicContainer } from "./index.js";
8
+ test("publicContainer rebuilds a safe object from an API row", () => {
9
+ const out = publicContainer(SECRET_BEARING_CONTAINER);
10
+ assert.deepEqual(Object.keys(out).sort(), [
11
+ "containerName",
12
+ "env",
13
+ "imageId",
14
+ "mounts",
15
+ "paths",
16
+ "secretEnv",
17
+ "status",
18
+ ]);
19
+ assert.deepEqual(out.mounts, [
20
+ { projectName: "team", mode: "read_write", kind: "project" },
21
+ ]);
22
+ assert.deepEqual(out.env, { PATH: "/bin", DB_PASSWORD: "hunter2" });
23
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ // SPDX-FileCopyrightText: 2026 Elouan Martinet <exa@elou.world>
2
+ //
3
+ // SPDX-License-Identifier: MIT
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { VOLUME_TOOLS } from "./test-support.js";
7
+ import { TOOLS, toolHandlers } from "./index.js";
8
+ test("volume tools are registered with the expected schemas", () => {
9
+ for (const name of VOLUME_TOOLS) {
10
+ const tool = TOOLS.find((entry) => entry.name === name);
11
+ assert.ok(tool, `${name} registered`);
12
+ if (name === "volume_remove") {
13
+ assert.equal(tool.approval, true, "volume_remove must require approval");
14
+ }
15
+ else {
16
+ assert.notEqual(tool.approval, true, `${name} must not require approval`);
17
+ }
18
+ assert.equal(tool.parameters.type, "object", `${name} type`);
19
+ assert.equal(typeof tool.parameters.properties, "object");
20
+ assert.ok(Array.isArray(tool.parameters.required));
21
+ }
22
+ const listTool = TOOLS.find((entry) => entry.name === "volume_list");
23
+ assert.deepEqual(listTool.parameters.required, []);
24
+ const createTool = TOOLS.find((entry) => entry.name === "volume_create");
25
+ assert.deepEqual(createTool.parameters.required, ["name"]);
26
+ assert.equal(createTool.parameters.properties.name.type, "string");
27
+ const removeTool = TOOLS.find((entry) => entry.name === "volume_remove");
28
+ assert.deepEqual(removeTool.parameters.required, ["name"]);
29
+ assert.equal(removeTool.parameters.properties.name.type, "string");
30
+ });
31
+ test("volume_list and secret_list return name objects", async () => {
32
+ const volumeResolver = {
33
+ control: async () => ({ volumes: [{ name: "myvol" }] }),
34
+ };
35
+ assert.deepEqual(await toolHandlers.volume_list(volumeResolver, {}, {}), [{ name: "myvol" }]);
36
+ const secretResolver = {
37
+ control: async () => ({ secrets: [{ name: "dbpass" }] }),
38
+ };
39
+ assert.deepEqual(await toolHandlers.secret_list(secretResolver, {}, {}), [{ name: "dbpass" }]);
40
+ });
@@ -0,0 +1,40 @@
1
+ import { grpc } from "./grpc/runtime-client.js";
2
+ export interface WorkspaceBinding {
3
+ guest: grpc.Client;
4
+ token: string;
5
+ socket: string;
6
+ defaultCwd?: string;
7
+ }
8
+ export interface BindingConfig {
9
+ socketsRoot: string;
10
+ defaultImage: string;
11
+ projectsRoot: string;
12
+ controlToken: string;
13
+ readyTimeoutMs?: number;
14
+ }
15
+ export declare class WorkspaceResolver {
16
+ private readonly config;
17
+ private readonly registry;
18
+ private readonly bindings;
19
+ constructor(config: BindingConfig, registry: any);
20
+ setConfig(patch: Partial<BindingConfig>): void;
21
+ getConfig(): Readonly<BindingConfig>;
22
+ resolve(cwd: unknown): Promise<WorkspaceBinding>;
23
+ resolveForPath(path: string, cwd: unknown): Promise<WorkspaceBinding>;
24
+ private containingWorkspace;
25
+ private workspaceForCwd;
26
+ resolveSlug(key: string): Promise<WorkspaceBinding>;
27
+ containerBinding(cwd: unknown, container: string): Promise<WorkspaceBinding>;
28
+ private ready;
29
+ private readyTimeoutMs;
30
+ private ensureReady;
31
+ private recoverContainer;
32
+ private resolveBinding;
33
+ private create;
34
+ control<T>(method: string, request: unknown): Promise<T>;
35
+ }
36
+ export declare function containerNotFound(container: string, slug?: string): Error;
37
+ export declare function normalizeToolError(error: unknown): Error;
38
+ export declare function workspaceSlug(id: unknown): string;
39
+ export declare function containerRowFor(containers: any[], slug: string, container: string): any | undefined;
40
+ export declare function metadata(token: string): grpc.Metadata;