@wavexzore/sandbox 0.1.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 (149) hide show
  1. package/Dockerfile +14 -0
  2. package/LICENSE +661 -0
  3. package/NOTICE +3 -0
  4. package/README.md +153 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.js +9 -0
  7. package/dist/sandbox/cli/install.d.ts +5 -0
  8. package/dist/sandbox/cli/install.js +335 -0
  9. package/dist/sandbox/cli/local-store.d.ts +87 -0
  10. package/dist/sandbox/cli/local-store.js +604 -0
  11. package/dist/sandbox/cli/opencode-config.d.ts +25 -0
  12. package/dist/sandbox/cli/opencode-config.js +240 -0
  13. package/dist/sandbox/cli/path.d.ts +64 -0
  14. package/dist/sandbox/cli/path.js +127 -0
  15. package/dist/sandbox/cli/types.d.ts +145 -0
  16. package/dist/sandbox/cli/types.js +6 -0
  17. package/dist/sandbox/cli/wavexzore-sandbox.d.ts +65 -0
  18. package/dist/sandbox/cli/wavexzore-sandbox.js +577 -0
  19. package/dist/sandbox/core/cli-helper.d.ts +19 -0
  20. package/dist/sandbox/core/cli-helper.js +64 -0
  21. package/dist/sandbox/core/docker-archive-utils.d.ts +3 -0
  22. package/dist/sandbox/core/docker-archive-utils.js +50 -0
  23. package/dist/sandbox/core/docker-sandbox.d.ts +51 -0
  24. package/dist/sandbox/core/docker-sandbox.js +675 -0
  25. package/dist/sandbox/core/edit/filediff.d.ts +16 -0
  26. package/dist/sandbox/core/edit/filediff.js +21 -0
  27. package/dist/sandbox/core/edit/index.d.ts +5 -0
  28. package/dist/sandbox/core/edit/index.js +5 -0
  29. package/dist/sandbox/core/edit/line-endings.d.ts +4 -0
  30. package/dist/sandbox/core/edit/line-endings.js +10 -0
  31. package/dist/sandbox/core/edit/lock.d.ts +1 -0
  32. package/dist/sandbox/core/edit/lock.js +18 -0
  33. package/dist/sandbox/core/edit/replace.d.ts +10 -0
  34. package/dist/sandbox/core/edit/replace.js +14 -0
  35. package/dist/sandbox/core/edit/replacers.d.ts +15 -0
  36. package/dist/sandbox/core/edit/replacers.js +241 -0
  37. package/dist/sandbox/core/logger.d.ts +15 -0
  38. package/dist/sandbox/core/logger.js +59 -0
  39. package/dist/sandbox/core/lsp/client.d.ts +63 -0
  40. package/dist/sandbox/core/lsp/client.js +533 -0
  41. package/dist/sandbox/core/lsp/config.d.ts +13 -0
  42. package/dist/sandbox/core/lsp/config.js +36 -0
  43. package/dist/sandbox/core/lsp/diagnostics.d.ts +12 -0
  44. package/dist/sandbox/core/lsp/diagnostics.js +65 -0
  45. package/dist/sandbox/core/lsp/index.d.ts +4 -0
  46. package/dist/sandbox/core/lsp/index.js +4 -0
  47. package/dist/sandbox/core/lsp/language.d.ts +24 -0
  48. package/dist/sandbox/core/lsp/language.js +249 -0
  49. package/dist/sandbox/core/lsp/manager.d.ts +77 -0
  50. package/dist/sandbox/core/lsp/manager.js +237 -0
  51. package/dist/sandbox/core/lsp/tooling.d.ts +14 -0
  52. package/dist/sandbox/core/lsp/tooling.js +78 -0
  53. package/dist/sandbox/core/patch-parser.d.ts +23 -0
  54. package/dist/sandbox/core/patch-parser.js +248 -0
  55. package/dist/sandbox/core/path-map.d.ts +9 -0
  56. package/dist/sandbox/core/path-map.js +73 -0
  57. package/dist/sandbox/core/project-data-storage.d.ts +42 -0
  58. package/dist/sandbox/core/project-data-storage.js +167 -0
  59. package/dist/sandbox/core/read/binary.d.ts +4 -0
  60. package/dist/sandbox/core/read/binary.js +80 -0
  61. package/dist/sandbox/core/read/format.d.ts +38 -0
  62. package/dist/sandbox/core/read/format.js +85 -0
  63. package/dist/sandbox/core/read/index.d.ts +3 -0
  64. package/dist/sandbox/core/read/index.js +3 -0
  65. package/dist/sandbox/core/read/permissions.d.ts +7 -0
  66. package/dist/sandbox/core/read/permissions.js +13 -0
  67. package/dist/sandbox/core/session-manager.d.ts +29 -0
  68. package/dist/sandbox/core/session-manager.js +338 -0
  69. package/dist/sandbox/core/shell/config.d.ts +7 -0
  70. package/dist/sandbox/core/shell/config.js +82 -0
  71. package/dist/sandbox/core/shell/output.d.ts +35 -0
  72. package/dist/sandbox/core/shell/output.js +80 -0
  73. package/dist/sandbox/core/shell/parser.d.ts +7 -0
  74. package/dist/sandbox/core/shell/parser.js +122 -0
  75. package/dist/sandbox/core/shell/permissions.d.ts +13 -0
  76. package/dist/sandbox/core/shell/permissions.js +33 -0
  77. package/dist/sandbox/core/shell/workdir.d.ts +4 -0
  78. package/dist/sandbox/core/shell/workdir.js +19 -0
  79. package/dist/sandbox/core/stream-utils.d.ts +23 -0
  80. package/dist/sandbox/core/stream-utils.js +97 -0
  81. package/dist/sandbox/core/toast.d.ts +47 -0
  82. package/dist/sandbox/core/toast.js +73 -0
  83. package/dist/sandbox/core/types.d.ts +159 -0
  84. package/dist/sandbox/core/types.js +11 -0
  85. package/dist/sandbox/core/write/bom.d.ts +8 -0
  86. package/dist/sandbox/core/write/bom.js +15 -0
  87. package/dist/sandbox/core/write/config.d.ts +14 -0
  88. package/dist/sandbox/core/write/config.js +188 -0
  89. package/dist/sandbox/core/write/diagnostics.d.ts +19 -0
  90. package/dist/sandbox/core/write/diagnostics.js +120 -0
  91. package/dist/sandbox/core/write/diff.d.ts +7 -0
  92. package/dist/sandbox/core/write/diff.js +21 -0
  93. package/dist/sandbox/core/write/formatter.d.ts +16 -0
  94. package/dist/sandbox/core/write/formatter.js +51 -0
  95. package/dist/sandbox/core/write/index.d.ts +6 -0
  96. package/dist/sandbox/core/write/index.js +5 -0
  97. package/dist/sandbox/core/write/permissions.d.ts +13 -0
  98. package/dist/sandbox/core/write/permissions.js +19 -0
  99. package/dist/sandbox/core/write/pipeline.d.ts +48 -0
  100. package/dist/sandbox/core/write/pipeline.js +229 -0
  101. package/dist/sandbox/core/write/read-tracker.d.ts +13 -0
  102. package/dist/sandbox/core/write/read-tracker.js +30 -0
  103. package/dist/sandbox/git/host-git-manager.d.ts +40 -0
  104. package/dist/sandbox/git/host-git-manager.js +278 -0
  105. package/dist/sandbox/git/index.d.ts +5 -0
  106. package/dist/sandbox/git/index.js +5 -0
  107. package/dist/sandbox/git/sandbox-git-manager.d.ts +14 -0
  108. package/dist/sandbox/git/sandbox-git-manager.js +54 -0
  109. package/dist/sandbox/git/session-git-manager.d.ts +18 -0
  110. package/dist/sandbox/git/session-git-manager.js +85 -0
  111. package/dist/sandbox/index.d.ts +205 -0
  112. package/dist/sandbox/index.js +70 -0
  113. package/dist/sandbox/plugins/custom-tools.d.ts +203 -0
  114. package/dist/sandbox/plugins/custom-tools.js +15 -0
  115. package/dist/sandbox/plugins/session-events.d.ts +10 -0
  116. package/dist/sandbox/plugins/session-events.js +56 -0
  117. package/dist/sandbox/plugins/system-transform.d.ts +10 -0
  118. package/dist/sandbox/plugins/system-transform.js +23 -0
  119. package/dist/sandbox/tools/bash-output.d.ts +17 -0
  120. package/dist/sandbox/tools/bash-output.js +35 -0
  121. package/dist/sandbox/tools/bash-status.d.ts +13 -0
  122. package/dist/sandbox/tools/bash-status.js +29 -0
  123. package/dist/sandbox/tools/bash-stop.d.ts +13 -0
  124. package/dist/sandbox/tools/bash-stop.js +28 -0
  125. package/dist/sandbox/tools/bash.d.ts +26 -0
  126. package/dist/sandbox/tools/bash.js +120 -0
  127. package/dist/sandbox/tools/edit.d.ts +20 -0
  128. package/dist/sandbox/tools/edit.js +87 -0
  129. package/dist/sandbox/tools/get-preview-url.d.ts +17 -0
  130. package/dist/sandbox/tools/get-preview-url.js +16 -0
  131. package/dist/sandbox/tools/glob.d.ts +17 -0
  132. package/dist/sandbox/tools/glob.js +23 -0
  133. package/dist/sandbox/tools/grep.d.ts +17 -0
  134. package/dist/sandbox/tools/grep.js +23 -0
  135. package/dist/sandbox/tools/ls.d.ts +17 -0
  136. package/dist/sandbox/tools/ls.js +21 -0
  137. package/dist/sandbox/tools/lsp.d.ts +41 -0
  138. package/dist/sandbox/tools/lsp.js +198 -0
  139. package/dist/sandbox/tools/multiedit.d.ts +24 -0
  140. package/dist/sandbox/tools/multiedit.js +83 -0
  141. package/dist/sandbox/tools/patch.d.ts +14 -0
  142. package/dist/sandbox/tools/patch.js +260 -0
  143. package/dist/sandbox/tools/read.d.ts +22 -0
  144. package/dist/sandbox/tools/read.js +105 -0
  145. package/dist/sandbox/tools/write.d.ts +16 -0
  146. package/dist/sandbox/tools/write.js +27 -0
  147. package/dist/sandbox/tools.d.ts +200 -0
  148. package/dist/sandbox/tools.js +43 -0
  149. package/package.json +55 -0
@@ -0,0 +1,577 @@
1
+ #!/usr/bin/env node
2
+ import { realpathSync } from 'fs';
3
+ import { isAbsolute, resolve } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { doctorWavexzoreSandbox, installWavexzoreSandbox, setupWavexzoreSandboxPathCommand, uninstallWavexzoreSandbox, } from './install.js';
6
+ export const WAVEXZORE_SANDBOX_CLI_HELP = `wavexzore-sandbox CLI
7
+
8
+ Usage:
9
+ wavexzore-sandbox install [path] [--root <path>] [--scope <user|project>] [--home-dir <path>] [--store-dir <path>] [--bin-dir <path>] [--config-path <file>] [--config-dir <path>] [--package-root <path>] [--json] [--dry-run] [--no-bin] [--setup-path]
10
+ wavexzore-sandbox uninstall [path] [--root <path>] [--scope <user|project>] [--home-dir <path>] [--store-dir <path>] [--bin-dir <path>] [--config-path <file>] [--config-dir <path>] [--json] [--dry-run] [--keep-config] [--keep-store] [--keep-bin] [--remove-path]
11
+ wavexzore-sandbox doctor [--scope <user|project>] [--home-dir <path>] [--store-dir <path>] [--bin-dir <path>] [--config-path <file>] [--config-dir <path>] [--project-root <path>] [--json]
12
+ wavexzore-sandbox setup-path [--scope <user|project>] [--home-dir <path>] [--store-dir <path>] [--bin-dir <path>] [--json] [--dry-run]
13
+ wavexzore-sandbox help
14
+
15
+ Commands:
16
+ install Deploy @wavexzore/sandbox into a durable local store and configure OpenCode with a file:// plugin loader
17
+ uninstall Remove Wavexzore Sandbox from OpenCode config and delete the local store by default
18
+ doctor Validate OpenCode config, local loader, manifest, active version, plugin import, and OpenCode helper
19
+ setup-path Explicitly add the Wavexzore Sandbox bin directory to PATH/profile
20
+ help Show this help message
21
+
22
+ Options:
23
+ --root <path> Invocation workspace. Used for --scope project and relative paths.
24
+ --scope <value> user (default) or project. Project scope writes <root>/.wavexzore/opencode/sandbox.
25
+ --home-dir <path> Product home. Default: ~/.wavexzore/opencode or WAVEXZORE_SANDBOX_HOME.
26
+ --store-dir <path> Explicit local store directory. Default: ~/.wavexzore/opencode/sandbox.
27
+ --bin-dir <path> Internal helper directory. Default: ~/.wavexzore/opencode/bin.
28
+ --config-path <file> Exact OpenCode config file. Otherwise honors OPENCODE_CONFIG for user scope.
29
+ --config-dir <path> OpenCode config directory for user scope.
30
+ --package-root <path> Install only: package root override for development/testing.
31
+ --no-bin Install only: do not create or repair the internal helper/shims under --bin-dir.
32
+ --setup-path Install only: explicitly add --bin-dir to PATH/profile.
33
+ --no-path-hint Install only: suppress PATH hint output after an explicit --setup-path attempt.
34
+ --dry-run Report changes without writing files where supported.
35
+ --keep-config Uninstall only: keep OpenCode config unchanged.
36
+ --keep-store Uninstall only: keep ~/.wavexzore/opencode/sandbox or --store-dir.
37
+ --keep-bin Uninstall only: keep ~/.wavexzore/opencode/bin helper/shims or --bin-dir.
38
+ --remove-path Uninstall only: remove the managed PATH/profile marker or Windows user Path entry.
39
+ --json Print machine-readable output.
40
+ -h, --help Show command help.
41
+ `;
42
+ function writeLine(stream, value = '') {
43
+ stream.write(`${value}\n`);
44
+ }
45
+ function nextValue(args, index, flag) {
46
+ const value = args[index + 1];
47
+ if (!value)
48
+ return { error: `Missing value for ${flag}` };
49
+ return { value };
50
+ }
51
+ function parseScope(value) {
52
+ return value === 'user' || value === 'project' ? value : undefined;
53
+ }
54
+ export function parseInstallArgs(args) {
55
+ const parsed = {
56
+ root: '.',
57
+ scope: 'user',
58
+ json: false,
59
+ dryRun: false,
60
+ noBin: false,
61
+ setupPath: false,
62
+ noPathHint: false,
63
+ help: false,
64
+ };
65
+ for (let index = 0; index < args.length; index += 1) {
66
+ const arg = args[index] ?? '';
67
+ if (arg === '--json')
68
+ parsed.json = true;
69
+ else if (arg === '--dry-run')
70
+ parsed.dryRun = true;
71
+ else if (arg === '--no-bin')
72
+ parsed.noBin = true;
73
+ else if (arg === '--setup-path')
74
+ parsed.setupPath = true;
75
+ else if (arg === '--no-path-hint')
76
+ parsed.noPathHint = true;
77
+ else if (arg === '--help' || arg === '-h')
78
+ parsed.help = true;
79
+ else if (arg === '--root') {
80
+ const next = nextValue(args, index, arg);
81
+ if (next.error)
82
+ return { ...parsed, error: next.error };
83
+ parsed.root = next.value ?? '';
84
+ index += 1;
85
+ }
86
+ else if (arg === '--scope') {
87
+ const next = nextValue(args, index, arg);
88
+ if (next.error)
89
+ return { ...parsed, error: next.error };
90
+ const scope = parseScope(next.value ?? '');
91
+ if (!scope)
92
+ return { ...parsed, error: '--scope must be user or project' };
93
+ parsed.scope = scope;
94
+ index += 1;
95
+ }
96
+ else if (arg === '--home-dir') {
97
+ const next = nextValue(args, index, arg);
98
+ if (next.error)
99
+ return { ...parsed, error: next.error };
100
+ parsed.homeDir = next.value;
101
+ index += 1;
102
+ }
103
+ else if (arg === '--bin-dir') {
104
+ const next = nextValue(args, index, arg);
105
+ if (next.error)
106
+ return { ...parsed, error: next.error };
107
+ parsed.binDir = next.value;
108
+ index += 1;
109
+ }
110
+ else if (arg === '--store-dir') {
111
+ const next = nextValue(args, index, arg);
112
+ if (next.error)
113
+ return { ...parsed, error: next.error };
114
+ parsed.storeDir = next.value;
115
+ index += 1;
116
+ }
117
+ else if (arg === '--config-dir') {
118
+ const next = nextValue(args, index, arg);
119
+ if (next.error)
120
+ return { ...parsed, error: next.error };
121
+ parsed.configDir = next.value;
122
+ index += 1;
123
+ }
124
+ else if (arg === '--config-path') {
125
+ const next = nextValue(args, index, arg);
126
+ if (next.error)
127
+ return { ...parsed, error: next.error };
128
+ parsed.configPath = next.value;
129
+ index += 1;
130
+ }
131
+ else if (arg === '--package-root') {
132
+ const next = nextValue(args, index, arg);
133
+ if (next.error)
134
+ return { ...parsed, error: next.error };
135
+ parsed.packageRoot = next.value;
136
+ index += 1;
137
+ }
138
+ else if (arg.startsWith('-')) {
139
+ return { ...parsed, error: `Unknown option: ${arg}` };
140
+ }
141
+ else {
142
+ parsed.root = arg;
143
+ }
144
+ }
145
+ return parsed;
146
+ }
147
+ export function parseUninstallArgs(args) {
148
+ const parsed = {
149
+ root: '.',
150
+ scope: 'user',
151
+ json: false,
152
+ dryRun: false,
153
+ keepConfig: false,
154
+ keepStore: false,
155
+ keepBin: false,
156
+ removePath: false,
157
+ help: false,
158
+ };
159
+ for (let index = 0; index < args.length; index += 1) {
160
+ const arg = args[index] ?? '';
161
+ if (arg === '--json')
162
+ parsed.json = true;
163
+ else if (arg === '--dry-run')
164
+ parsed.dryRun = true;
165
+ else if (arg === '--keep-config')
166
+ parsed.keepConfig = true;
167
+ else if (arg === '--keep-store')
168
+ parsed.keepStore = true;
169
+ else if (arg === '--keep-bin')
170
+ parsed.keepBin = true;
171
+ else if (arg === '--remove-path')
172
+ parsed.removePath = true;
173
+ else if (arg === '--help' || arg === '-h')
174
+ parsed.help = true;
175
+ else if (arg === '--root') {
176
+ const next = nextValue(args, index, arg);
177
+ if (next.error)
178
+ return { ...parsed, error: next.error };
179
+ parsed.root = next.value ?? '';
180
+ index += 1;
181
+ }
182
+ else if (arg === '--scope') {
183
+ const next = nextValue(args, index, arg);
184
+ if (next.error)
185
+ return { ...parsed, error: next.error };
186
+ const scope = parseScope(next.value ?? '');
187
+ if (!scope)
188
+ return { ...parsed, error: '--scope must be user or project' };
189
+ parsed.scope = scope;
190
+ index += 1;
191
+ }
192
+ else if (arg === '--home-dir') {
193
+ const next = nextValue(args, index, arg);
194
+ if (next.error)
195
+ return { ...parsed, error: next.error };
196
+ parsed.homeDir = next.value;
197
+ index += 1;
198
+ }
199
+ else if (arg === '--bin-dir') {
200
+ const next = nextValue(args, index, arg);
201
+ if (next.error)
202
+ return { ...parsed, error: next.error };
203
+ parsed.binDir = next.value;
204
+ index += 1;
205
+ }
206
+ else if (arg === '--store-dir') {
207
+ const next = nextValue(args, index, arg);
208
+ if (next.error)
209
+ return { ...parsed, error: next.error };
210
+ parsed.storeDir = next.value;
211
+ index += 1;
212
+ }
213
+ else if (arg === '--config-dir') {
214
+ const next = nextValue(args, index, arg);
215
+ if (next.error)
216
+ return { ...parsed, error: next.error };
217
+ parsed.configDir = next.value;
218
+ index += 1;
219
+ }
220
+ else if (arg === '--config-path') {
221
+ const next = nextValue(args, index, arg);
222
+ if (next.error)
223
+ return { ...parsed, error: next.error };
224
+ parsed.configPath = next.value;
225
+ index += 1;
226
+ }
227
+ else if (arg.startsWith('-')) {
228
+ return { ...parsed, error: `Unknown option: ${arg}` };
229
+ }
230
+ else {
231
+ parsed.root = arg;
232
+ }
233
+ }
234
+ return parsed;
235
+ }
236
+ export function parseDoctorArgs(args) {
237
+ const parsed = { scope: 'user', json: false, help: false };
238
+ for (let index = 0; index < args.length; index += 1) {
239
+ const arg = args[index] ?? '';
240
+ if (arg === '--json')
241
+ parsed.json = true;
242
+ else if (arg === '--help' || arg === '-h')
243
+ parsed.help = true;
244
+ else if (arg === '--scope') {
245
+ const next = nextValue(args, index, arg);
246
+ if (next.error)
247
+ return { ...parsed, error: next.error };
248
+ const scope = parseScope(next.value ?? '');
249
+ if (!scope)
250
+ return { ...parsed, error: '--scope must be user or project' };
251
+ parsed.scope = scope;
252
+ index += 1;
253
+ }
254
+ else if (arg === '--home-dir') {
255
+ const next = nextValue(args, index, arg);
256
+ if (next.error)
257
+ return { ...parsed, error: next.error };
258
+ parsed.homeDir = next.value;
259
+ index += 1;
260
+ }
261
+ else if (arg === '--bin-dir') {
262
+ const next = nextValue(args, index, arg);
263
+ if (next.error)
264
+ return { ...parsed, error: next.error };
265
+ parsed.binDir = next.value;
266
+ index += 1;
267
+ }
268
+ else if (arg === '--store-dir') {
269
+ const next = nextValue(args, index, arg);
270
+ if (next.error)
271
+ return { ...parsed, error: next.error };
272
+ parsed.storeDir = next.value;
273
+ index += 1;
274
+ }
275
+ else if (arg === '--config-dir') {
276
+ const next = nextValue(args, index, arg);
277
+ if (next.error)
278
+ return { ...parsed, error: next.error };
279
+ parsed.configDir = next.value;
280
+ index += 1;
281
+ }
282
+ else if (arg === '--config-path') {
283
+ const next = nextValue(args, index, arg);
284
+ if (next.error)
285
+ return { ...parsed, error: next.error };
286
+ parsed.configPath = next.value;
287
+ index += 1;
288
+ }
289
+ else if (arg === '--project-root' || arg === '--root') {
290
+ const next = nextValue(args, index, arg);
291
+ if (next.error)
292
+ return { ...parsed, error: next.error };
293
+ parsed.projectRoot = next.value;
294
+ index += 1;
295
+ }
296
+ else if (arg.startsWith('-')) {
297
+ return { ...parsed, error: `Unknown option: ${arg}` };
298
+ }
299
+ else {
300
+ return { ...parsed, error: `Unexpected positional argument for doctor: ${arg}` };
301
+ }
302
+ }
303
+ return parsed;
304
+ }
305
+ export function parseSetupPathArgs(args) {
306
+ const parsed = { scope: 'user', json: false, dryRun: false, help: false };
307
+ for (let index = 0; index < args.length; index += 1) {
308
+ const arg = args[index] ?? '';
309
+ if (arg === '--json')
310
+ parsed.json = true;
311
+ else if (arg === '--dry-run')
312
+ parsed.dryRun = true;
313
+ else if (arg === '--help' || arg === '-h')
314
+ parsed.help = true;
315
+ else if (arg === '--scope') {
316
+ const next = nextValue(args, index, arg);
317
+ if (next.error)
318
+ return { ...parsed, error: next.error };
319
+ const scope = parseScope(next.value ?? '');
320
+ if (!scope)
321
+ return { ...parsed, error: '--scope must be user or project' };
322
+ parsed.scope = scope;
323
+ index += 1;
324
+ }
325
+ else if (arg === '--home-dir') {
326
+ const next = nextValue(args, index, arg);
327
+ if (next.error)
328
+ return { ...parsed, error: next.error };
329
+ parsed.homeDir = next.value;
330
+ index += 1;
331
+ }
332
+ else if (arg === '--bin-dir') {
333
+ const next = nextValue(args, index, arg);
334
+ if (next.error)
335
+ return { ...parsed, error: next.error };
336
+ parsed.binDir = next.value;
337
+ index += 1;
338
+ }
339
+ else if (arg === '--store-dir') {
340
+ const next = nextValue(args, index, arg);
341
+ if (next.error)
342
+ return { ...parsed, error: next.error };
343
+ parsed.storeDir = next.value;
344
+ index += 1;
345
+ }
346
+ else if (arg.startsWith('-')) {
347
+ return { ...parsed, error: `Unknown option: ${arg}` };
348
+ }
349
+ else {
350
+ return { ...parsed, error: `Unexpected positional argument for setup-path: ${arg}` };
351
+ }
352
+ }
353
+ return parsed;
354
+ }
355
+ function safeErrorMessage(error) {
356
+ return error instanceof Error ? error.message : String(error);
357
+ }
358
+ function resolvePath(cwd, value) {
359
+ if (!value)
360
+ return undefined;
361
+ return isAbsolute(value) || value.startsWith('\\\\') || /^[A-Za-z]:[\\/]/.test(value) ? value : resolve(cwd, value);
362
+ }
363
+ function printInstallSummary(stream, result, showPathHint = true) {
364
+ writeLine(stream, 'Wavexzore Sandbox installation complete');
365
+ writeLine(stream, `workspace: ${result.root}`);
366
+ writeLine(stream, `scope: ${result.scope}`);
367
+ writeLine(stream, `home: ${result.homeDir}`);
368
+ writeLine(stream, `store: ${result.storeDir}`);
369
+ writeLine(stream, `bin: ${result.binDir} (${result.binStatus})`);
370
+ writeLine(stream, `opencode-helper: ${result.cliPath}`);
371
+ writeLine(stream, `active-version: ${result.activeVersion} (${result.versionStatus})`);
372
+ writeLine(stream, `loader: ${result.loaderDir} (${result.loaderStatus})`);
373
+ writeLine(stream, `manifest: ${result.manifestPath} (${result.manifestStatus})`);
374
+ writeLine(stream, `config: ${result.configPath} (${result.configStatus})`);
375
+ writeLine(stream, `plugin: ${result.pluginEntry} (${result.pluginStatus})`);
376
+ writeLine(stream, `path: ${result.pathStatus}`);
377
+ if (result.pathConfigPath)
378
+ writeLine(stream, `path-config: ${result.pathConfigPath}`);
379
+ if (showPathHint && result.pathStatus === 'missing')
380
+ writeLine(stream, `path-hint: ${result.pathHint}`);
381
+ if (result.dryRun)
382
+ writeLine(stream, 'dry-run: no changes were made');
383
+ if (result.removedPluginEntries.length > 0)
384
+ writeLine(stream, `removed stale plugin entries: ${result.removedPluginEntries.join(', ')}`);
385
+ }
386
+ function printUninstallSummary(stream, result) {
387
+ writeLine(stream, 'Wavexzore Sandbox uninstall complete');
388
+ writeLine(stream, `workspace: ${result.root}`);
389
+ writeLine(stream, `scope: ${result.scope}`);
390
+ if (result.dryRun)
391
+ writeLine(stream, 'dry-run: no changes were made');
392
+ writeLine(stream, `config: ${result.configPath} (${result.configStatus})`);
393
+ writeLine(stream, `store: ${result.storeDir} (${result.storeStatus})`);
394
+ writeLine(stream, `bin: ${result.binDir} (${result.binStatus})`);
395
+ writeLine(stream, `path: ${result.pathStatus}`);
396
+ if (result.pathConfigPath)
397
+ writeLine(stream, `path-config: ${result.pathConfigPath}`);
398
+ if (result.removedPluginEntries.length > 0)
399
+ writeLine(stream, `removed plugin entries: ${result.removedPluginEntries.join(', ')}`);
400
+ }
401
+ function printDoctorSummary(stream, result) {
402
+ writeLine(stream, `Wavexzore Sandbox doctor ${result.status}`);
403
+ writeLine(stream, `home: ${result.homeDir}`);
404
+ writeLine(stream, `store: ${result.storeDir}`);
405
+ writeLine(stream, `bin: ${result.binDir}`);
406
+ writeLine(stream, `opencode-helper: ${result.cliPath}`);
407
+ writeLine(stream, `config: ${result.configPath}`);
408
+ writeLine(stream, `plugin: ${result.pluginEntry}`);
409
+ if (result.activeVersion)
410
+ writeLine(stream, `active-version: ${result.activeVersion}`);
411
+ for (const check of result.checks) {
412
+ writeLine(stream, `${check.status.toUpperCase()} ${check.name}: ${check.message}${check.path ? ` (${check.path})` : ''}`);
413
+ }
414
+ }
415
+ function printPathSummary(stream, result) {
416
+ writeLine(stream, `Wavexzore Sandbox setup-path ${result.pathStatus}`);
417
+ writeLine(stream, `home: ${result.homeDir}`);
418
+ writeLine(stream, `bin: ${result.binDir}`);
419
+ if (result.pathConfigPath)
420
+ writeLine(stream, `path-config: ${result.pathConfigPath}`);
421
+ if (result.pathStatus !== 'present')
422
+ writeLine(stream, `path-hint: ${result.pathHint}`);
423
+ }
424
+ export async function runWavexzoreSandboxCli(argv, options = {}) {
425
+ const cwd = options.cwd ?? process.cwd();
426
+ const stdout = options.stdout ?? process.stdout;
427
+ const stderr = options.stderr ?? process.stderr;
428
+ const [command = 'help', ...rest] = argv;
429
+ if (command === 'help' || command === '--help' || command === '-h') {
430
+ writeLine(stdout, WAVEXZORE_SANDBOX_CLI_HELP.trimEnd());
431
+ return 0;
432
+ }
433
+ if (command === 'install') {
434
+ const parsed = parseInstallArgs(rest);
435
+ if (parsed.error) {
436
+ writeLine(stderr, parsed.error);
437
+ return 1;
438
+ }
439
+ if (parsed.help) {
440
+ writeLine(stdout, WAVEXZORE_SANDBOX_CLI_HELP.trimEnd());
441
+ return 0;
442
+ }
443
+ const root = resolvePath(cwd, parsed.root) ?? cwd;
444
+ try {
445
+ const result = installWavexzoreSandbox(root, {
446
+ scope: parsed.scope,
447
+ homeDir: resolvePath(cwd, parsed.homeDir),
448
+ storeDir: resolvePath(cwd, parsed.storeDir),
449
+ binDir: resolvePath(cwd, parsed.binDir),
450
+ configPath: resolvePath(cwd, parsed.configPath),
451
+ configDir: resolvePath(cwd, parsed.configDir),
452
+ packageRoot: resolvePath(cwd, parsed.packageRoot),
453
+ dryRun: parsed.dryRun,
454
+ installBin: !parsed.noBin,
455
+ setupPath: parsed.setupPath,
456
+ });
457
+ if (parsed.json)
458
+ writeLine(stdout, JSON.stringify(result, null, 2));
459
+ else
460
+ printInstallSummary(stdout, result, parsed.setupPath && !parsed.noPathHint);
461
+ return 0;
462
+ }
463
+ catch (error) {
464
+ const message = safeErrorMessage(error);
465
+ if (parsed.json)
466
+ writeLine(stdout, JSON.stringify({ root, status: 'failed', error: message }, null, 2));
467
+ else
468
+ writeLine(stderr, `Wavexzore Sandbox installation failed: ${message}`);
469
+ return 1;
470
+ }
471
+ }
472
+ if (command === 'uninstall') {
473
+ const parsed = parseUninstallArgs(rest);
474
+ if (parsed.error) {
475
+ writeLine(stderr, parsed.error);
476
+ return 1;
477
+ }
478
+ if (parsed.help) {
479
+ writeLine(stdout, WAVEXZORE_SANDBOX_CLI_HELP.trimEnd());
480
+ return 0;
481
+ }
482
+ const root = resolvePath(cwd, parsed.root) ?? cwd;
483
+ const result = uninstallWavexzoreSandbox(root, {
484
+ scope: parsed.scope,
485
+ homeDir: resolvePath(cwd, parsed.homeDir),
486
+ storeDir: resolvePath(cwd, parsed.storeDir),
487
+ binDir: resolvePath(cwd, parsed.binDir),
488
+ configPath: resolvePath(cwd, parsed.configPath),
489
+ configDir: resolvePath(cwd, parsed.configDir),
490
+ dryRun: parsed.dryRun,
491
+ keepConfig: parsed.keepConfig,
492
+ keepStore: parsed.keepStore,
493
+ keepBin: parsed.keepBin,
494
+ removePath: parsed.removePath,
495
+ });
496
+ if (parsed.json)
497
+ writeLine(stdout, JSON.stringify(result, null, 2));
498
+ else
499
+ printUninstallSummary(stdout, result);
500
+ return 0;
501
+ }
502
+ if (command === 'doctor') {
503
+ const parsed = parseDoctorArgs(rest);
504
+ if (parsed.error) {
505
+ writeLine(stderr, parsed.error);
506
+ return 1;
507
+ }
508
+ if (parsed.help) {
509
+ writeLine(stdout, WAVEXZORE_SANDBOX_CLI_HELP.trimEnd());
510
+ return 0;
511
+ }
512
+ const result = await doctorWavexzoreSandbox({
513
+ scope: parsed.scope,
514
+ homeDir: resolvePath(cwd, parsed.homeDir),
515
+ storeDir: resolvePath(cwd, parsed.storeDir),
516
+ binDir: resolvePath(cwd, parsed.binDir),
517
+ configPath: resolvePath(cwd, parsed.configPath),
518
+ configDir: resolvePath(cwd, parsed.configDir),
519
+ projectRoot: resolvePath(cwd, parsed.projectRoot),
520
+ });
521
+ if (parsed.json)
522
+ writeLine(stdout, JSON.stringify(result, null, 2));
523
+ else
524
+ printDoctorSummary(result.status === 'failed' ? stderr : stdout, result);
525
+ return result.status === 'failed' ? 1 : 0;
526
+ }
527
+ if (command === 'setup-path') {
528
+ const parsed = parseSetupPathArgs(rest);
529
+ if (parsed.error) {
530
+ writeLine(stderr, parsed.error);
531
+ return 1;
532
+ }
533
+ if (parsed.help) {
534
+ writeLine(stdout, WAVEXZORE_SANDBOX_CLI_HELP.trimEnd());
535
+ return 0;
536
+ }
537
+ const result = setupWavexzoreSandboxPathCommand({
538
+ scope: parsed.scope,
539
+ homeDir: resolvePath(cwd, parsed.homeDir),
540
+ storeDir: resolvePath(cwd, parsed.storeDir),
541
+ binDir: resolvePath(cwd, parsed.binDir),
542
+ dryRun: parsed.dryRun,
543
+ });
544
+ if (parsed.json)
545
+ writeLine(stdout, JSON.stringify(result, null, 2));
546
+ else
547
+ printPathSummary(stdout, result);
548
+ return 0;
549
+ }
550
+ writeLine(stderr, `Unknown command: ${command}`);
551
+ writeLine(stderr, WAVEXZORE_SANDBOX_CLI_HELP.trimEnd());
552
+ return 1;
553
+ }
554
+ export function isMainModule(metaUrl = import.meta.url, argv1 = process.argv[1]) {
555
+ if (!argv1)
556
+ return false;
557
+ const modulePath = fileURLToPath(metaUrl);
558
+ const scriptPath = resolve(argv1);
559
+ if (modulePath === scriptPath)
560
+ return true;
561
+ try {
562
+ return realpathSync(modulePath) === realpathSync(scriptPath);
563
+ }
564
+ catch {
565
+ return false;
566
+ }
567
+ }
568
+ if (isMainModule()) {
569
+ runWavexzoreSandboxCli(process.argv.slice(2))
570
+ .then((code) => {
571
+ process.exitCode = code;
572
+ })
573
+ .catch((error) => {
574
+ console.error(error instanceof Error ? error.message : String(error));
575
+ process.exitCode = 1;
576
+ });
577
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright Daytona Platforms Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ export type CliHelperState = {
6
+ manifestPath: string;
7
+ cliPath: string;
8
+ available: boolean;
9
+ activeVersion?: string;
10
+ error?: string;
11
+ };
12
+ export type CliHelperDoctorResult = CliHelperState & {
13
+ ok: boolean;
14
+ stdout?: string;
15
+ stderr?: string;
16
+ status?: number | null;
17
+ };
18
+ export declare function resolveCliHelperState(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): CliHelperState;
19
+ export declare function doctorCliHelper(): CliHelperDoctorResult;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Copyright Daytona Platforms Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { spawnSync } from 'child_process';
6
+ import { existsSync, readFileSync } from 'fs';
7
+ import { homedir } from 'os';
8
+ import { join } from 'path';
9
+ function defaultHome(env) {
10
+ return env.WAVEXZORE_SANDBOX_HOME || join(homedir(), '.wavexzore', 'opencode');
11
+ }
12
+ function helperName(platform) {
13
+ return platform === 'win32' ? 'wavexzore-sandbox-helper.cmd' : 'wavexzore-sandbox-helper';
14
+ }
15
+ function readManifest(manifestPath) {
16
+ if (!existsSync(manifestPath))
17
+ return undefined;
18
+ return JSON.parse(readFileSync(manifestPath, 'utf8'));
19
+ }
20
+ export function resolveCliHelperState(env = process.env, platform = process.platform) {
21
+ const home = defaultHome(env);
22
+ const manifestPath = join(home, 'sandbox', 'manifest.json');
23
+ const fallbackCliPath = join(home, 'bin', helperName(platform));
24
+ try {
25
+ const manifest = readManifest(manifestPath);
26
+ const cliPath = manifest?.cliPath || fallbackCliPath;
27
+ return {
28
+ manifestPath,
29
+ cliPath,
30
+ available: existsSync(cliPath),
31
+ activeVersion: manifest?.activeVersion,
32
+ };
33
+ }
34
+ catch (error) {
35
+ return {
36
+ manifestPath,
37
+ cliPath: fallbackCliPath,
38
+ available: existsSync(fallbackCliPath),
39
+ error: error instanceof Error ? error.message : String(error),
40
+ };
41
+ }
42
+ }
43
+ export function doctorCliHelper() {
44
+ const state = resolveCliHelperState();
45
+ if (!state.available)
46
+ return { ...state, ok: false, error: state.error || 'OpenCode helper is not installed' };
47
+ const result = spawnSync(state.cliPath, ['opencode', 'doctor', '--json'], {
48
+ encoding: 'utf8',
49
+ shell: false,
50
+ timeout: 5000,
51
+ });
52
+ return {
53
+ ...state,
54
+ ok: result.status === 0,
55
+ status: result.status,
56
+ stdout: result.stdout,
57
+ stderr: result.stderr,
58
+ error: result.error
59
+ ? result.error.message
60
+ : result.status === 0
61
+ ? state.error
62
+ : result.stderr || result.stdout || 'OpenCode helper doctor failed',
63
+ };
64
+ }
@@ -0,0 +1,3 @@
1
+ import type Dockerode from 'dockerode';
2
+ export declare function getFileFromContainer(container: Dockerode.Container, filePath: string): Promise<Buffer>;
3
+ export declare function putFileToContainer(container: Dockerode.Container, filePath: string, content: Buffer): Promise<void>;