@moxt-ai/cli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/dist/index.js +162 -94
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ moxt file get-url -w <workspace-id> --team-space-id <teamSpaceId> -p <path>
|
|
|
103
103
|
# Resolve URL in a teammate space (by teammate ID)
|
|
104
104
|
moxt file get-url -w <workspace-id> --teammate-id <teammateId> -p <path>
|
|
105
105
|
|
|
106
|
-
# Upload a file
|
|
106
|
+
# Upload a file by path
|
|
107
107
|
moxt file put -w <workspace-id> -p <path> -l <local-path> [-r]
|
|
108
108
|
|
|
109
109
|
# Upload a file to a teamspace (by name or ID)
|
|
@@ -113,6 +113,9 @@ moxt file put -w <workspace-id> --team-space-id <teamSpaceId> -p <path> -l <loca
|
|
|
113
113
|
# Upload a file to a teammate space (by teammate ID)
|
|
114
114
|
moxt file put -w <workspace-id> --teammate-id <teammateId> -p <path> -l <local-path> [-r]
|
|
115
115
|
|
|
116
|
+
# Overwrite an existing file by its Moxt URL
|
|
117
|
+
moxt file put --url <moxt-url> -l <local-path>
|
|
118
|
+
|
|
116
119
|
# Create a directory
|
|
117
120
|
moxt file mkdir -w <workspace-id> -p <path> [-r]
|
|
118
121
|
moxt file mkdir -w <workspace-id> -s <teamspace-name> -p <path> [-r]
|
|
@@ -126,7 +129,7 @@ moxt file del -w <workspace-id> -s <teamspace-name> -p <path>
|
|
|
126
129
|
|
|
127
130
|
| Option | Description |
|
|
128
131
|
|--------|-------------|
|
|
129
|
-
| `-w, --workspace <id>` | Workspace ID (required for
|
|
132
|
+
| `-w, --workspace <id>` | Workspace ID (required for path mode) |
|
|
130
133
|
| `-s, --space <name>` | Space name (`personal` or teamspace name) |
|
|
131
134
|
| `--personal` | Use personal space (default when no space specified) |
|
|
132
135
|
| `--team-space-id <id>` | Team space ID |
|
|
@@ -134,11 +137,12 @@ moxt file del -w <workspace-id> -s <teamspace-name> -p <path>
|
|
|
134
137
|
| `-p, --path <path>` | File or directory path |
|
|
135
138
|
| `-u, --url <url>` | Moxt file URL (e.g., `https://moxt.ai/w/{workspaceId}/{fileId}`) |
|
|
136
139
|
| `-l, --local-path <path>` | Local file path (for upload) |
|
|
137
|
-
| `-r, --recursive` | Create parent directories if needed |
|
|
140
|
+
| `-r, --recursive` | Create parent directories if needed (path mode only) |
|
|
138
141
|
|
|
139
142
|
> **Note**: `-s`, `--personal`, `--team-space-id`, and `--teammate-id` are mutually exclusive.
|
|
140
|
-
> For `file read`, use either `--url` or `--workspace` with `--path`. They are mutually exclusive.
|
|
141
|
-
>
|
|
143
|
+
> For `file read` and `file put`, use either `--url` or `--workspace` with `--path`. They are mutually exclusive.
|
|
144
|
+
> `--url` with `file put` overwrites an existing file identified by the URL; it never creates new files. Use `--recursive` is not allowed in URL mode.
|
|
145
|
+
> `file get-url` returns a stable Moxt URL (e.g., `https://moxt.ai/w/{workspaceId}/{fileId}`) for the given path; the URL is unchanged across writes to the same path and can be fed back into `file read --url` or `file put --url`.
|
|
142
146
|
|
|
143
147
|
## Configuration
|
|
144
148
|
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,118 @@ import updateNotifier from "update-notifier";
|
|
|
7
7
|
// src/commands/file.ts
|
|
8
8
|
import * as fs from "fs";
|
|
9
9
|
|
|
10
|
+
// src/utils/file-selector.ts
|
|
11
|
+
var SpaceOptionsError = class extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "SpaceOptionsError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function resolveSpaceSelector(options) {
|
|
18
|
+
const { space, teamSpaceId, teammateId } = options;
|
|
19
|
+
const personalIsSet = options.personal === true;
|
|
20
|
+
const spaceIsSet = space != null && space !== "";
|
|
21
|
+
const teamSpaceIdIsSet = teamSpaceId != null && teamSpaceId !== "";
|
|
22
|
+
const teammateIdIsSet = teammateId != null && teammateId !== "";
|
|
23
|
+
const selectorCount = (spaceIsSet ? 1 : 0) + (personalIsSet ? 1 : 0) + (teamSpaceIdIsSet ? 1 : 0) + (teammateIdIsSet ? 1 : 0);
|
|
24
|
+
if (selectorCount > 1) {
|
|
25
|
+
throw new SpaceOptionsError(
|
|
26
|
+
"Error: -s, --personal, --team-space-id, and --teammate-id are mutually exclusive."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (teamSpaceId != null && teamSpaceId !== "") {
|
|
30
|
+
return { teamSpaceId };
|
|
31
|
+
}
|
|
32
|
+
if (teammateId != null && teammateId !== "") {
|
|
33
|
+
const parsed = Number.parseInt(teammateId, 10);
|
|
34
|
+
if (!Number.isInteger(parsed) || parsed <= 0 || String(parsed) !== teammateId) {
|
|
35
|
+
throw new SpaceOptionsError(
|
|
36
|
+
`Error: --teammate-id must be a positive integer, got "${teammateId}".`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return { agentId: parsed };
|
|
40
|
+
}
|
|
41
|
+
if (personalIsSet) {
|
|
42
|
+
return { space: "personal" };
|
|
43
|
+
}
|
|
44
|
+
if (space != null && space !== "") {
|
|
45
|
+
return { space };
|
|
46
|
+
}
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
function buildFileQueryString(path, spaceParams) {
|
|
50
|
+
const params = new URLSearchParams();
|
|
51
|
+
if (path != null && path !== "") {
|
|
52
|
+
params.set("path", path);
|
|
53
|
+
}
|
|
54
|
+
if (spaceParams.space) {
|
|
55
|
+
params.set("space", spaceParams.space);
|
|
56
|
+
}
|
|
57
|
+
if (spaceParams.teamSpaceId) {
|
|
58
|
+
params.set("teamSpaceId", spaceParams.teamSpaceId);
|
|
59
|
+
}
|
|
60
|
+
if (spaceParams.agentId != null) {
|
|
61
|
+
params.set("agentId", String(spaceParams.agentId));
|
|
62
|
+
}
|
|
63
|
+
const qs = params.toString();
|
|
64
|
+
return qs ? `?${qs}` : "";
|
|
65
|
+
}
|
|
66
|
+
function isBinaryContent(buffer) {
|
|
67
|
+
const sampleSize = Math.min(buffer.length, 8192);
|
|
68
|
+
for (let i = 0; i < sampleSize; i++) {
|
|
69
|
+
const byte = buffer[i];
|
|
70
|
+
if (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
function resolveReadMode(options) {
|
|
77
|
+
if (options.url && options.workspace) {
|
|
78
|
+
throw new SpaceOptionsError("Error: --url cannot be used with --workspace");
|
|
79
|
+
}
|
|
80
|
+
if (options.url && options.path) {
|
|
81
|
+
throw new SpaceOptionsError("Error: --url cannot be used with --path");
|
|
82
|
+
}
|
|
83
|
+
if (!options.url && !options.workspace) {
|
|
84
|
+
throw new SpaceOptionsError("Error: Either --url or --workspace is required");
|
|
85
|
+
}
|
|
86
|
+
if (!options.url && !options.path) {
|
|
87
|
+
throw new SpaceOptionsError("Error: --path is required when not using --url");
|
|
88
|
+
}
|
|
89
|
+
if (options.url) {
|
|
90
|
+
return { kind: "by-url", url: options.url };
|
|
91
|
+
}
|
|
92
|
+
if (!options.workspace) {
|
|
93
|
+
throw new SpaceOptionsError("Error: Either --url or --workspace is required");
|
|
94
|
+
}
|
|
95
|
+
if (!options.path) {
|
|
96
|
+
throw new SpaceOptionsError("Error: --path is required when not using --url");
|
|
97
|
+
}
|
|
98
|
+
return { kind: "by-path", workspace: options.workspace, path: options.path };
|
|
99
|
+
}
|
|
100
|
+
function resolveWriteMode(options) {
|
|
101
|
+
if (options.url && options.workspace) {
|
|
102
|
+
throw new SpaceOptionsError("Error: --url cannot be used with --workspace");
|
|
103
|
+
}
|
|
104
|
+
if (options.url && options.path) {
|
|
105
|
+
throw new SpaceOptionsError("Error: --url cannot be used with --path");
|
|
106
|
+
}
|
|
107
|
+
if (options.url && options.recursive) {
|
|
108
|
+
throw new SpaceOptionsError("Error: --recursive cannot be used with --url (the file must already exist)");
|
|
109
|
+
}
|
|
110
|
+
if (!options.url && !options.workspace) {
|
|
111
|
+
throw new SpaceOptionsError("Error: Either --url or --workspace is required");
|
|
112
|
+
}
|
|
113
|
+
if (!options.url && !options.path) {
|
|
114
|
+
throw new SpaceOptionsError("Error: --path is required when not using --url");
|
|
115
|
+
}
|
|
116
|
+
if (options.url) {
|
|
117
|
+
return { kind: "by-url", url: options.url };
|
|
118
|
+
}
|
|
119
|
+
return { kind: "by-path", workspace: options.workspace, path: options.path };
|
|
120
|
+
}
|
|
121
|
+
|
|
10
122
|
// src/utils/http.ts
|
|
11
123
|
import { arch, platform } from "os";
|
|
12
124
|
|
|
@@ -32,7 +144,7 @@ function getApiKey() {
|
|
|
32
144
|
|
|
33
145
|
// src/utils/http.ts
|
|
34
146
|
function getUserAgent() {
|
|
35
|
-
return `moxt-cli/${"0.2.
|
|
147
|
+
return `moxt-cli/${"0.2.1"} (${platform()}/${arch()}) node/${process.versions.node}`;
|
|
36
148
|
}
|
|
37
149
|
async function request(method, path, body) {
|
|
38
150
|
const apiKey = getApiKey();
|
|
@@ -117,59 +229,16 @@ function stopSpinner(success, message) {
|
|
|
117
229
|
}
|
|
118
230
|
|
|
119
231
|
// src/commands/file.ts
|
|
120
|
-
function
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
function validateSpaceOptions(options) {
|
|
131
|
-
const mutuallyExclusive = [options.space, options.personal, options.teamSpaceId, options.teammateId].filter(
|
|
132
|
-
Boolean
|
|
133
|
-
).length;
|
|
134
|
-
if (mutuallyExclusive > 1) {
|
|
135
|
-
printError("Error: -s, --personal, --team-space-id, and --teammate-id are mutually exclusive.");
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
if (options.teamSpaceId) {
|
|
139
|
-
return { teamSpaceId: options.teamSpaceId };
|
|
140
|
-
}
|
|
141
|
-
if (options.teammateId) {
|
|
142
|
-
const parsed = Number.parseInt(options.teammateId, 10);
|
|
143
|
-
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
144
|
-
printError(`Error: --teammate-id must be a positive integer, got "${options.teammateId}".`);
|
|
232
|
+
function runOrExit(fn) {
|
|
233
|
+
try {
|
|
234
|
+
return fn();
|
|
235
|
+
} catch (err) {
|
|
236
|
+
if (err instanceof SpaceOptionsError) {
|
|
237
|
+
printError(err.message);
|
|
145
238
|
process.exit(1);
|
|
146
239
|
}
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
if (options.personal) {
|
|
150
|
-
return { space: "personal" };
|
|
151
|
-
}
|
|
152
|
-
if (options.space) {
|
|
153
|
-
return { space: options.space };
|
|
154
|
-
}
|
|
155
|
-
return {};
|
|
156
|
-
}
|
|
157
|
-
function buildFileQueryString(path, spaceParams) {
|
|
158
|
-
const params = new URLSearchParams();
|
|
159
|
-
if (path) {
|
|
160
|
-
params.set("path", path);
|
|
161
|
-
}
|
|
162
|
-
if (spaceParams.space) {
|
|
163
|
-
params.set("space", spaceParams.space);
|
|
240
|
+
throw err;
|
|
164
241
|
}
|
|
165
|
-
if (spaceParams.teamSpaceId) {
|
|
166
|
-
params.set("teamSpaceId", spaceParams.teamSpaceId);
|
|
167
|
-
}
|
|
168
|
-
if (spaceParams.agentId != null) {
|
|
169
|
-
params.set("agentId", String(spaceParams.agentId));
|
|
170
|
-
}
|
|
171
|
-
const qs = params.toString();
|
|
172
|
-
return qs ? `?${qs}` : "";
|
|
173
242
|
}
|
|
174
243
|
function addSpaceOptions(cmd) {
|
|
175
244
|
return cmd.requiredOption("-w, --workspace <workspaceId>", "Workspace ID").option("-s, --space <name>", "Space name (personal or teamspace name)").option("--personal", "Use personal space (default)").option("--team-space-id <teamSpaceId>", "Team space ID").option("--teammate-id <teammateId>", "Teammate ID (teammate space)");
|
|
@@ -179,7 +248,7 @@ function registerFileCommand(program2) {
|
|
|
179
248
|
addSpaceOptions(
|
|
180
249
|
file.command("get-url").description("Resolve the shareable browser URL for a file").requiredOption("-p, --path <path>", "File path")
|
|
181
250
|
).action(async (options) => {
|
|
182
|
-
const spaceParams =
|
|
251
|
+
const spaceParams = runOrExit(() => resolveSpaceSelector(options));
|
|
183
252
|
const qs = buildFileQueryString(options.path, spaceParams);
|
|
184
253
|
startSpinner("Resolving URL...");
|
|
185
254
|
const response = await httpGet(
|
|
@@ -202,7 +271,7 @@ function registerFileCommand(program2) {
|
|
|
202
271
|
addSpaceOptions(
|
|
203
272
|
file.command("list").description("List directory contents").option("-p, --path <path>", "Directory path", "/")
|
|
204
273
|
).action(async (options) => {
|
|
205
|
-
const spaceParams =
|
|
274
|
+
const spaceParams = runOrExit(() => resolveSpaceSelector(options));
|
|
206
275
|
const qs = buildFileQueryString(options.path, spaceParams);
|
|
207
276
|
startSpinner("Listing files...");
|
|
208
277
|
const response = await httpGet(
|
|
@@ -232,36 +301,21 @@ function registerFileCommand(program2) {
|
|
|
232
301
|
}
|
|
233
302
|
});
|
|
234
303
|
file.command("read").description("Read file content").option("-w, --workspace <workspaceId>", "Workspace ID").option("-s, --space <name>", "Space name (personal or teamspace name)").option("--personal", "Use personal space (default)").option("--team-space-id <teamSpaceId>", "Team space ID").option("--teammate-id <teammateId>", "Teammate ID (teammate space)").option("-p, --path <path>", "File path").option("-u, --url <url>", "Moxt file URL (e.g., https://moxt.ai/w/{workspaceId}/{fileId})").action(async (options) => {
|
|
235
|
-
|
|
236
|
-
printError("Error: --url cannot be used with --workspace");
|
|
237
|
-
process.exit(1);
|
|
238
|
-
}
|
|
239
|
-
if (options.url && options.path) {
|
|
240
|
-
printError("Error: --url cannot be used with --path");
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
|
-
if (!options.url && !options.workspace) {
|
|
244
|
-
printError("Error: Either --url or --workspace is required");
|
|
245
|
-
process.exit(1);
|
|
246
|
-
}
|
|
247
|
-
if (!options.url && !options.path) {
|
|
248
|
-
printError("Error: --path is required when not using --url");
|
|
249
|
-
process.exit(1);
|
|
250
|
-
}
|
|
304
|
+
const mode = runOrExit(() => resolveReadMode(options));
|
|
251
305
|
startSpinner("Reading file...");
|
|
252
306
|
let response;
|
|
253
307
|
let displayPath;
|
|
254
|
-
if (
|
|
255
|
-
displayPath =
|
|
308
|
+
if (mode.kind === "by-url") {
|
|
309
|
+
displayPath = mode.url;
|
|
256
310
|
response = await httpGet(
|
|
257
|
-
`/files/read-by-url?url=${encodeURIComponent(
|
|
311
|
+
`/files/read-by-url?url=${encodeURIComponent(mode.url)}`
|
|
258
312
|
);
|
|
259
313
|
} else {
|
|
260
|
-
displayPath =
|
|
261
|
-
const spaceParams =
|
|
262
|
-
const qs = buildFileQueryString(
|
|
314
|
+
displayPath = mode.path;
|
|
315
|
+
const spaceParams = runOrExit(() => resolveSpaceSelector(options));
|
|
316
|
+
const qs = buildFileQueryString(mode.path, spaceParams);
|
|
263
317
|
response = await httpGet(
|
|
264
|
-
`/workspaces/${
|
|
318
|
+
`/workspaces/${mode.workspace}/files/read${qs}`
|
|
265
319
|
);
|
|
266
320
|
}
|
|
267
321
|
if (!response.ok) {
|
|
@@ -282,11 +336,9 @@ function registerFileCommand(program2) {
|
|
|
282
336
|
stopSpinner(true, "Done");
|
|
283
337
|
print(content ?? "");
|
|
284
338
|
});
|
|
285
|
-
|
|
286
|
-
file.command("put").description("Upload a file").requiredOption("-p, --path <path>", "Remote file path").requiredOption("-l, --local-path <localPath>", "Local file path").option("-r, --recursive", "Create parent directories if needed")
|
|
287
|
-
).action(
|
|
339
|
+
file.command("put").description("Upload a file").option("-w, --workspace <workspaceId>", "Workspace ID").option("-s, --space <name>", "Space name (personal or teamspace name)").option("--personal", "Use personal space (default)").option("--team-space-id <teamSpaceId>", "Team space ID").option("--teammate-id <teammateId>", "Teammate ID (teammate space)").option("-p, --path <path>", "Remote file path").option("-u, --url <url>", "Moxt file URL (e.g., https://moxt.ai/w/{workspaceId}/{fileId})").requiredOption("-l, --local-path <localPath>", "Local file path").option("-r, --recursive", "Create parent directories if needed").action(
|
|
288
340
|
async (options) => {
|
|
289
|
-
const
|
|
341
|
+
const mode = runOrExit(() => resolveWriteMode(options));
|
|
290
342
|
if (!fs.existsSync(options.localPath)) {
|
|
291
343
|
print(`${colors.red}\u2620 Local file not found: ${options.localPath}${colors.reset}`);
|
|
292
344
|
process.exit(1);
|
|
@@ -308,19 +360,35 @@ function registerFileCommand(program2) {
|
|
|
308
360
|
}
|
|
309
361
|
const content = buffer.toString("utf8");
|
|
310
362
|
startSpinner("Uploading...");
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
363
|
+
let response;
|
|
364
|
+
let displayPath;
|
|
365
|
+
if (mode.kind === "by-url") {
|
|
366
|
+
displayPath = mode.url;
|
|
367
|
+
response = await httpPut("/files/write-by-url", {
|
|
368
|
+
url: mode.url,
|
|
369
|
+
content
|
|
370
|
+
});
|
|
371
|
+
} else {
|
|
372
|
+
displayPath = mode.path;
|
|
373
|
+
const spaceParams = runOrExit(() => resolveSpaceSelector(options));
|
|
374
|
+
response = await httpPut(
|
|
375
|
+
`/workspaces/${mode.workspace}/files/write`,
|
|
376
|
+
{
|
|
377
|
+
path: mode.path,
|
|
378
|
+
content,
|
|
379
|
+
recursive: options.recursive ?? false,
|
|
380
|
+
...spaceParams
|
|
381
|
+
}
|
|
382
|
+
);
|
|
383
|
+
}
|
|
320
384
|
if (!response.ok) {
|
|
321
385
|
stopSpinner(false, "Failed");
|
|
322
386
|
if (response.status === 404) {
|
|
323
|
-
|
|
387
|
+
if (mode.kind === "by-url") {
|
|
388
|
+
print(`${colors.red}\u2620 ${displayPath} does not exist${colors.reset}`);
|
|
389
|
+
} else {
|
|
390
|
+
print(`${colors.red}\u2620 Parent directory does not exist${colors.reset}`);
|
|
391
|
+
}
|
|
324
392
|
} else if (response.status === 400) {
|
|
325
393
|
printError(`Error: ${JSON.stringify(response.data)}`);
|
|
326
394
|
} else {
|
|
@@ -336,7 +404,7 @@ function registerFileCommand(program2) {
|
|
|
336
404
|
file.command("mkdir").description("Create a directory").requiredOption("-p, --path <path>", "Directory path").option("-r, --recursive", "Create parent directories if needed")
|
|
337
405
|
).action(
|
|
338
406
|
async (options) => {
|
|
339
|
-
const spaceParams =
|
|
407
|
+
const spaceParams = runOrExit(() => resolveSpaceSelector(options));
|
|
340
408
|
startSpinner("Creating directory...");
|
|
341
409
|
const response = await httpPost(
|
|
342
410
|
`/workspaces/${options.workspace}/files/mkdir`,
|
|
@@ -365,7 +433,7 @@ function registerFileCommand(program2) {
|
|
|
365
433
|
file.command("del").description("Delete a file or empty directory").requiredOption("-p, --path <path>", "File or directory path")
|
|
366
434
|
).action(
|
|
367
435
|
async (options) => {
|
|
368
|
-
const spaceParams =
|
|
436
|
+
const spaceParams = runOrExit(() => resolveSpaceSelector(options));
|
|
369
437
|
startSpinner("Deleting...");
|
|
370
438
|
const response = await httpDelete(
|
|
371
439
|
`/workspaces/${options.workspace}/files/delete`,
|
|
@@ -521,10 +589,10 @@ function registerWorkspaceCommand(program2) {
|
|
|
521
589
|
|
|
522
590
|
// src/index.ts
|
|
523
591
|
updateNotifier({
|
|
524
|
-
pkg: { name: "@moxt-ai/cli", version: "0.2.
|
|
592
|
+
pkg: { name: "@moxt-ai/cli", version: "0.2.1" }
|
|
525
593
|
}).notify();
|
|
526
594
|
var program = new Command();
|
|
527
|
-
program.name("moxt").description("Moxt CLI - AI Workspace").version("0.2.
|
|
595
|
+
program.name("moxt").description("Moxt CLI - AI Workspace").version("0.2.1").action(() => {
|
|
528
596
|
program.help();
|
|
529
597
|
});
|
|
530
598
|
registerWhoamiCommand(program);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/file.ts","../src/utils/http.ts","../src/utils/config.ts","../src/utils/output.ts","../src/utils/spinner.ts","../src/commands/whoami.ts","../src/commands/workspace.ts"],"sourcesContent":["import { Command } from 'commander'\nimport updateNotifier from 'update-notifier'\nimport { registerFileCommand } from './commands/file.js'\nimport { registerWhoamiCommand } from './commands/whoami.js'\nimport { registerWorkspaceCommand } from './commands/workspace.js'\n\ndeclare const __CLI_VERSION__: string\n\nupdateNotifier({\n pkg: { name: '@moxt-ai/cli', version: __CLI_VERSION__ },\n}).notify()\n\nconst program = new Command()\n\nprogram\n .name('moxt')\n .description('Moxt CLI - AI Workspace')\n .version(__CLI_VERSION__)\n .action(() => {\n program.help()\n })\n\nregisterWhoamiCommand(program)\nregisterWorkspaceCommand(program)\nregisterFileCommand(program)\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error('CLI Error:', err)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport { Command } from 'commander'\nimport { httpDelete, httpGet, httpPost, httpPut } from '../utils/http.js'\nimport { colors, print, printError } from '../utils/output.js'\nimport { startSpinner, stopSpinner } from '../utils/spinner.js'\n\ninterface FileEntry {\n name: string\n type: 'file' | 'directory'\n size: number | null\n}\n\ninterface FileReadResponse {\n path: string\n type: 'file' | 'directory'\n entries: FileEntry[] | null\n content: string | null\n}\n\ninterface FileWriteResponse {\n path: string\n created: boolean\n}\n\ninterface MkdirResponse {\n path: string\n created: boolean\n}\n\ninterface DeleteResponse {\n path: string\n}\n\ninterface FileUrlResponse {\n path: string\n url: string\n}\n\n/**\n * Detect if a Buffer contains binary content.\n * Text files must not contain control characters (except tab, newline, carriage return).\n */\nfunction isBinaryContent(buffer: Buffer): boolean {\n const sampleSize = Math.min(buffer.length, 8192)\n\n for (let i = 0; i < sampleSize; i++) {\n const byte = buffer[i]\n // control chars except tab=9, newline=10, carriage return=13\n if (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13) {\n return true\n }\n }\n\n return false\n}\n\ninterface SpaceOptions {\n workspace: string\n space?: string\n personal?: boolean\n teamSpaceId?: string\n teammateId?: string\n}\n\ninterface SpaceParams {\n space?: string\n teamSpaceId?: string\n agentId?: number\n}\n\nfunction validateSpaceOptions(options: SpaceOptions): SpaceParams {\n const mutuallyExclusive = [options.space, options.personal, options.teamSpaceId, options.teammateId].filter(\n Boolean,\n ).length\n if (mutuallyExclusive > 1) {\n printError('Error: -s, --personal, --team-space-id, and --teammate-id are mutually exclusive.')\n process.exit(1)\n }\n\n if (options.teamSpaceId) {\n return { teamSpaceId: options.teamSpaceId }\n }\n if (options.teammateId) {\n const parsed = Number.parseInt(options.teammateId, 10)\n if (!Number.isInteger(parsed) || parsed <= 0) {\n printError(`Error: --teammate-id must be a positive integer, got \"${options.teammateId}\".`)\n process.exit(1)\n }\n return { agentId: parsed }\n }\n if (options.personal) {\n return { space: 'personal' }\n }\n if (options.space) {\n return { space: options.space }\n }\n // Default: personal space\n return {}\n}\n\nfunction buildFileQueryString(path: string | undefined, spaceParams: SpaceParams): string {\n const params = new URLSearchParams()\n if (path) {\n params.set('path', path)\n }\n if (spaceParams.space) {\n params.set('space', spaceParams.space)\n }\n if (spaceParams.teamSpaceId) {\n params.set('teamSpaceId', spaceParams.teamSpaceId)\n }\n if (spaceParams.agentId != null) {\n params.set('agentId', String(spaceParams.agentId))\n }\n const qs = params.toString()\n return qs ? `?${qs}` : ''\n}\n\nfunction addSpaceOptions(cmd: Command): Command {\n return cmd\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .option('-s, --space <name>', 'Space name (personal or teamspace name)')\n .option('--personal', 'Use personal space (default)')\n .option('--team-space-id <teamSpaceId>', 'Team space ID')\n .option('--teammate-id <teammateId>', 'Teammate ID (teammate space)')\n}\n\nexport function registerFileCommand(program: Command): void {\n const file = program.command('file').description('File operations')\n\n addSpaceOptions(\n file.command('get-url')\n .description('Resolve the shareable browser URL for a file')\n .requiredOption('-p, --path <path>', 'File path'),\n ).action(async (options: SpaceOptions & { path: string }) => {\n const spaceParams = validateSpaceOptions(options)\n const qs = buildFileQueryString(options.path, spaceParams)\n\n startSpinner('Resolving URL...')\n const response = await httpGet<FileUrlResponse>(\n `/workspaces/${options.workspace}/files/url${qs}`,\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ ${options.path} does not exist${colors.reset}`)\n } else if (response.status === 400) {\n printError(`Error: ${JSON.stringify(response.data)}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n stopSpinner(true, response.data.path)\n print(`${colors.cyan}${response.data.url}${colors.reset}`)\n })\n\n addSpaceOptions(\n file.command('list')\n .description('List directory contents')\n .option('-p, --path <path>', 'Directory path', '/'),\n ).action(async (options: SpaceOptions & { path: string }) => {\n const spaceParams = validateSpaceOptions(options)\n const qs = buildFileQueryString(options.path, spaceParams)\n\n startSpinner('Listing files...')\n const response = await httpGet<FileReadResponse>(\n `/workspaces/${options.workspace}/files/list${qs}`,\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ ${options.path} does not exist${colors.reset}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const { path, entries } = response.data\n\n if (!entries || entries.length === 0) {\n stopSpinner(true, `${path}: empty directory`)\n return\n }\n\n stopSpinner(true, path)\n for (const entry of entries) {\n if (entry.type === 'directory') {\n print(`${colors.blue}${entry.name}/${colors.reset}`)\n } else {\n print(entry.name)\n }\n }\n })\n\n file.command('read')\n .description('Read file content')\n .option('-w, --workspace <workspaceId>', 'Workspace ID')\n .option('-s, --space <name>', 'Space name (personal or teamspace name)')\n .option('--personal', 'Use personal space (default)')\n .option('--team-space-id <teamSpaceId>', 'Team space ID')\n .option('--teammate-id <teammateId>', 'Teammate ID (teammate space)')\n .option('-p, --path <path>', 'File path')\n .option('-u, --url <url>', 'Moxt file URL (e.g., https://moxt.ai/w/{workspaceId}/{fileId})')\n .action(async (options: Partial<SpaceOptions> & { path?: string; url?: string }) => {\n // Validate mutually exclusive options: -u vs -w\n if (options.url && options.workspace) {\n printError('Error: --url cannot be used with --workspace')\n process.exit(1)\n }\n if (options.url && options.path) {\n printError('Error: --url cannot be used with --path')\n process.exit(1)\n }\n if (!options.url && !options.workspace) {\n printError('Error: Either --url or --workspace is required')\n process.exit(1)\n }\n if (!options.url && !options.path) {\n printError('Error: --path is required when not using --url')\n process.exit(1)\n }\n\n startSpinner('Reading file...')\n\n let response: { ok: boolean; status: number; data: FileReadResponse }\n let displayPath: string\n\n if (options.url) {\n displayPath = options.url\n response = await httpGet<FileReadResponse>(\n `/files/read-by-url?url=${encodeURIComponent(options.url)}`,\n )\n } else {\n displayPath = options.path!\n const spaceParams = validateSpaceOptions(options as SpaceOptions)\n const qs = buildFileQueryString(options.path, spaceParams)\n response = await httpGet<FileReadResponse>(\n `/workspaces/${options.workspace}/files/read${qs}`,\n )\n }\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ ${displayPath} does not exist${colors.reset}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const { type, content } = response.data\n\n if (type === 'directory') {\n stopSpinner(false, 'Failed')\n print(`${colors.red}☠ ${displayPath} is a directory${colors.reset}`)\n process.exit(1)\n }\n\n stopSpinner(true, 'Done')\n print(content ?? '')\n })\n\n addSpaceOptions(\n file.command('put')\n .description('Upload a file')\n .requiredOption('-p, --path <path>', 'Remote file path')\n .requiredOption('-l, --local-path <localPath>', 'Local file path')\n .option('-r, --recursive', 'Create parent directories if needed'),\n ).action(\n async (options: SpaceOptions & {\n path: string\n localPath: string\n recursive?: boolean\n }) => {\n const spaceParams = validateSpaceOptions(options)\n\n // check local file exists\n if (!fs.existsSync(options.localPath)) {\n print(`${colors.red}☠ Local file not found: ${options.localPath}${colors.reset}`)\n process.exit(1)\n }\n\n // check it is a file, not a directory\n const stats = fs.statSync(options.localPath)\n if (!stats.isFile()) {\n print(`${colors.red}☠ Not a file: ${options.localPath}${colors.reset}`)\n process.exit(1)\n }\n\n // check file size (10MB limit)\n const maxSize = 10 * 1024 * 1024\n if (stats.size > maxSize) {\n print(`${colors.red}☠ File too large (max 10MB): ${options.localPath}${colors.reset}`)\n process.exit(1)\n }\n\n // read file and check for binary content\n const buffer = fs.readFileSync(options.localPath)\n if (isBinaryContent(buffer)) {\n print(`${colors.red}☠ Binary files are not allowed. Only text files can be uploaded.${colors.reset}`)\n process.exit(1)\n }\n\n const content = buffer.toString('utf8')\n\n startSpinner('Uploading...')\n const response = await httpPut<FileWriteResponse>(\n `/workspaces/${options.workspace}/files/write`,\n {\n path: options.path,\n content,\n recursive: options.recursive ?? false,\n ...spaceParams,\n },\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ Parent directory does not exist${colors.reset}`)\n } else if (response.status === 400) {\n printError(`Error: ${JSON.stringify(response.data)}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const action = response.data.created ? 'Created' : 'Updated'\n stopSpinner(true, `${action}: ${response.data.path}`)\n },\n )\n\n addSpaceOptions(\n file.command('mkdir')\n .description('Create a directory')\n .requiredOption('-p, --path <path>', 'Directory path')\n .option('-r, --recursive', 'Create parent directories if needed'),\n ).action(\n async (options: SpaceOptions & {\n path: string\n recursive?: boolean\n }) => {\n const spaceParams = validateSpaceOptions(options)\n\n startSpinner('Creating directory...')\n const response = await httpPost<MkdirResponse>(\n `/workspaces/${options.workspace}/files/mkdir`,\n {\n path: options.path,\n recursive: options.recursive ?? false,\n ...spaceParams,\n },\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ Parent directory does not exist${colors.reset}`)\n } else if (response.status === 400) {\n printError(`Error: ${JSON.stringify(response.data)}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const action = response.data.created ? 'Created' : 'Already exists'\n stopSpinner(true, `${action}: ${response.data.path}`)\n },\n )\n\n addSpaceOptions(\n file.command('del')\n .description('Delete a file or empty directory')\n .requiredOption('-p, --path <path>', 'File or directory path'),\n ).action(\n async (options: SpaceOptions & {\n path: string\n }) => {\n const spaceParams = validateSpaceOptions(options)\n\n startSpinner('Deleting...')\n const response = await httpDelete<DeleteResponse>(\n `/workspaces/${options.workspace}/files/delete`,\n {\n path: options.path,\n ...spaceParams,\n },\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ Path not found: ${options.path}${colors.reset}`)\n } else if (response.status === 400) {\n print(`${colors.red}☠ Cannot delete non-empty directory${colors.reset}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n stopSpinner(true, `Deleted: ${response.data.path}`)\n },\n )\n}\n","import { arch, platform } from 'os'\nimport { getApiBaseUrl, getApiKey } from './config.js'\n\ndeclare const __CLI_VERSION__: string\n\nexport interface ApiResponse<T> {\n ok: boolean\n status: number\n data: T\n}\n\nfunction getUserAgent(): string {\n return `moxt-cli/${__CLI_VERSION__} (${platform()}/${arch()}) node/${process.versions.node}`\n}\n\nasync function request<T>(method: string, path: string, body?: unknown): Promise<ApiResponse<T>> {\n const apiKey = getApiKey()\n const url = `${getApiBaseUrl()}${path}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n 'User-Agent': getUserAgent(),\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n\n let data: T\n const contentType = response.headers.get('content-type')\n if (contentType?.includes('application/json')) {\n data = (await response.json()) as T\n } else {\n data = (await response.text()) as T\n }\n\n if (response.status === 401) {\n console.error('Authentication failed. Check your MOXT_API_KEY.')\n console.error('Get a new key at: https://moxt.ai')\n process.exit(1)\n }\n\n return {\n ok: response.ok,\n status: response.status,\n data,\n }\n}\n\nexport async function httpGet<T>(path: string): Promise<ApiResponse<T>> {\n return request<T>('GET', path)\n}\n\nexport async function httpPut<T>(path: string, body: unknown): Promise<ApiResponse<T>> {\n return request<T>('PUT', path, body)\n}\n\nexport async function httpPost<T>(path: string, body: unknown): Promise<ApiResponse<T>> {\n return request<T>('POST', path, body)\n}\n\nexport async function httpDelete<T>(path: string, body?: unknown): Promise<ApiResponse<T>> {\n return request<T>('DELETE', path, body)\n}\n","const DEFAULT_HOST = 'api.moxt.ai'\n\nexport function getApiBaseUrl(): string {\n const host = process.env.MOXT_HOST ?? DEFAULT_HOST\n return `https://${host}/openapi/v1`\n}\n\nexport function getApiKey(): string {\n const apiKey = process.env.MOXT_API_KEY\n\n if (!apiKey) {\n console.error('MOXT_API_KEY environment variable is not set.')\n console.error('')\n console.error('Get your API key at: https://moxt.ai')\n console.error('')\n console.error('Then set it:')\n console.error(' export MOXT_API_KEY=moxt_...')\n process.exit(1)\n }\n\n return apiKey\n}\n","// ANSI colors\nexport const colors = {\n bold: '\\x1b[1m',\n blue: '\\x1b[1;34m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n cyan: '\\x1b[36m',\n dim: '\\x1b[2m',\n reset: '\\x1b[0m',\n}\n\nexport function print(message: string): void {\n console.log(message)\n}\n\nexport function printError(message: string): void {\n console.error(`${colors.red}${message}${colors.reset}`)\n}\n","const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']\n\nlet intervalId: ReturnType<typeof setInterval> | null = null\nlet frameIndex = 0\n\nexport function startSpinner(message: string): void {\n frameIndex = 0\n process.stdout.write(`${frames[frameIndex]} ${message}`)\n\n intervalId = setInterval(() => {\n frameIndex = (frameIndex + 1) % frames.length\n process.stdout.write(`\\r${frames[frameIndex]} ${message}`)\n }, 80)\n}\n\nexport function stopSpinner(success: boolean, message?: string): void {\n if (intervalId) {\n clearInterval(intervalId)\n intervalId = null\n }\n\n const symbol = success ? '\\x1b[32m✓\\x1b[0m' : '\\x1b[31m✗\\x1b[0m'\n // \\x1b[2K 清除整行,\\r 回到行首\n process.stdout.write(`\\x1b[2K\\r${symbol} ${message ?? ''}\\n`)\n}\n","import { Command } from 'commander'\nimport { httpGet } from '../utils/http.js'\nimport { colors, print, printError } from '../utils/output.js'\nimport { startSpinner, stopSpinner } from '../utils/spinner.js'\n\ninterface WhoamiResponse {\n nickname: string\n email: string\n}\n\nexport function registerWhoamiCommand(program: Command): void {\n program\n .command('whoami')\n .description('Show current user information')\n .action(async () => {\n startSpinner('Fetching user info...')\n const response = await httpGet<WhoamiResponse>('/users/whoami')\n\n if (response.ok) {\n stopSpinner(true, 'Done')\n print(`${colors.bold}Nickname${colors.reset}: ${response.data.nickname}`)\n print(`${colors.bold}Email${colors.reset}: ${response.data.email}`)\n } else {\n stopSpinner(false, 'Failed')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport { httpGet, httpDelete } from '../utils/http.js'\nimport { colors, print, printError } from '../utils/output.js'\nimport { startSpinner, stopSpinner } from '../utils/spinner.js'\n\ninterface WorkspaceItem {\n workspaceId: string\n name: string\n}\n\ninterface WorkspaceListResponse {\n workspaces: WorkspaceItem[]\n}\n\ninterface MemberItem {\n userId: number\n email: string\n displayName: string | null\n role: string\n}\n\ninterface MembersResponse {\n members: MemberItem[]\n}\n\ninterface SpaceItem {\n type: 'personal' | 'team' | 'teammate'\n name: string\n teamSpaceId: string | null\n agentId: number | null\n}\n\n// Email regex (same as web/src/utils/email.ts)\nconst emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/\n\nfunction isValidEmail(email: string): boolean {\n return emailRegex.test(email)\n}\n\nexport function registerWorkspaceCommand(program: Command): void {\n const workspace = program.command('workspace').description('Workspace management')\n\n workspace\n .command('list')\n .description('List all workspaces you belong to')\n .action(async () => {\n startSpinner('Fetching workspaces...')\n const response = await httpGet<WorkspaceListResponse>('/workspaces')\n\n if (response.ok) {\n const { workspaces } = response.data\n if (workspaces.length === 0) {\n stopSpinner(true, 'No workspaces found.')\n return\n }\n\n stopSpinner(true, `Found ${workspaces.length} workspace(s)`)\n\n for (const ws of workspaces) {\n print(`${colors.bold}${ws.workspaceId}${colors.reset}\\t${ws.name}`)\n }\n } else {\n stopSpinner(false, 'Failed')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n })\n\n const members = program.command('members').description('Manage workspace members')\n\n members\n .command('list')\n .description('List all members in a workspace')\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .action(async (options: { workspace: string }) => {\n const { workspace: workspaceId } = options\n\n startSpinner('Fetching workspace members...')\n const response = await httpGet<MembersResponse>(`/workspaces/${workspaceId}/members`)\n\n if (!response.ok) {\n stopSpinner(false, 'Failed to fetch members')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n\n const { members } = response.data\n if (members.length === 0) {\n stopSpinner(true, 'No members found.')\n return\n }\n\n stopSpinner(true, `Found ${members.length} member(s)`)\n\n for (const member of members) {\n const name = member.displayName || '-'\n print(`${colors.bold}${member.email}${colors.reset}\\t${name}\\t${member.role}`)\n }\n })\n\n members\n .command('remove')\n .description('Remove members from a workspace')\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .argument('<emails>', 'Emails to remove (comma-separated)')\n .action(async (emailsArg: string, options: { workspace: string }) => {\n const { workspace: workspaceId } = options\n\n const emails = emailsArg.split(',').map((e) => e.trim()).filter(Boolean)\n if (emails.length === 0) {\n printError('No valid emails provided')\n process.exit(1)\n }\n\n // Validate email format\n const invalidEmails = emails.filter((e) => !isValidEmail(e))\n if (invalidEmails.length > 0) {\n for (const email of invalidEmails) {\n printError(`Invalid email format: ${email}`)\n }\n process.exit(1)\n }\n\n // Fetch members to get userId by email\n startSpinner('Fetching workspace members...')\n const membersResponse = await httpGet<MembersResponse>(`/workspaces/${workspaceId}/members`)\n\n if (!membersResponse.ok) {\n stopSpinner(false, 'Failed to fetch members')\n printError(`Error [${membersResponse.status}]: ${JSON.stringify(membersResponse.data)}`)\n process.exit(1)\n }\n\n stopSpinner(true, 'Members fetched')\n\n const { members } = membersResponse.data\n const emailToMember = new Map(members.map((m) => [m.email.toLowerCase(), m]))\n\n // Remove each member\n for (const email of emails) {\n const member = emailToMember.get(email.toLowerCase())\n if (!member) {\n print(`${colors.red}✗${colors.reset} ${email} - not found in workspace`)\n continue\n }\n\n const deleteResponse = await httpDelete(`/workspaces/${workspaceId}/members/${member.userId}`)\n\n if (deleteResponse.ok) {\n print(`${colors.green}✓${colors.reset} ${email} - removed`)\n } else {\n print(`${colors.red}✗${colors.reset} ${email} - failed: ${JSON.stringify(deleteResponse.data)}`)\n }\n }\n })\n\n const space = program.command('space').description('Manage spaces')\n\n space\n .command('list')\n .description('List accessible spaces in a workspace')\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .action(async (options: { workspace: string }) => {\n const { workspace: workspaceId } = options\n\n startSpinner('Fetching spaces...')\n const response = await httpGet<{ spaces: SpaceItem[] }>(`/workspaces/${workspaceId}/spaces`)\n\n if (!response.ok) {\n stopSpinner(false, 'Failed to fetch spaces')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n\n const { spaces } = response.data\n if (spaces.length === 0) {\n stopSpinner(true, 'No spaces found.')\n return\n }\n\n stopSpinner(true, `Found ${spaces.length} space(s)`)\n\n print(\n `${colors.bold}TYPE${colors.reset}\\t${colors.bold}TEAM_SPACE_ID${colors.reset}\\t${colors.bold}TEAMMATE_ID${colors.reset}\\t${colors.bold}NAME${colors.reset}`,\n )\n for (const s of spaces) {\n const teamSpaceId = s.teamSpaceId ?? ''\n const teammateId = s.agentId != null ? String(s.agentId) : ''\n print(`${s.type}\\t${teamSpaceId}\\t${teammateId}\\t${s.name}`)\n }\n })\n\n}\n"],"mappings":"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","names":["program","program","program","members"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/file.ts","../src/utils/file-selector.ts","../src/utils/http.ts","../src/utils/config.ts","../src/utils/output.ts","../src/utils/spinner.ts","../src/commands/whoami.ts","../src/commands/workspace.ts"],"sourcesContent":["import { Command } from 'commander'\nimport updateNotifier from 'update-notifier'\nimport { registerFileCommand } from './commands/file.js'\nimport { registerWhoamiCommand } from './commands/whoami.js'\nimport { registerWorkspaceCommand } from './commands/workspace.js'\n\ndeclare const __CLI_VERSION__: string\n\nupdateNotifier({\n pkg: { name: '@moxt-ai/cli', version: __CLI_VERSION__ },\n}).notify()\n\nconst program = new Command()\n\nprogram\n .name('moxt')\n .description('Moxt CLI - AI Workspace')\n .version(__CLI_VERSION__)\n .action(() => {\n program.help()\n })\n\nregisterWhoamiCommand(program)\nregisterWorkspaceCommand(program)\nregisterFileCommand(program)\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error('CLI Error:', err)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport { Command } from 'commander'\nimport {\n buildFileQueryString,\n isBinaryContent,\n resolveReadMode,\n resolveSpaceSelector,\n resolveWriteMode,\n SpaceOptions,\n SpaceOptionsError,\n} from '../utils/file-selector.js'\nimport { httpDelete, httpGet, httpPost, httpPut } from '../utils/http.js'\nimport { colors, print, printError } from '../utils/output.js'\nimport { startSpinner, stopSpinner } from '../utils/spinner.js'\n\n/**\n * Call a pure resolver that may throw SpaceOptionsError; on error, print the\n * message and exit(1). This keeps the CLI's user-facing contract (stderr +\n * exit code 1) identical to the previous inlined implementation, while the\n * resolver itself stays pure and unit-testable.\n */\nfunction runOrExit<T>(fn: () => T): T {\n try {\n return fn()\n } catch (err) {\n if (err instanceof SpaceOptionsError) {\n printError(err.message)\n process.exit(1)\n }\n throw err\n }\n}\n\ninterface FileEntry {\n name: string\n type: 'file' | 'directory'\n size: number | null\n}\n\ninterface FileReadResponse {\n path: string\n type: 'file' | 'directory'\n entries: FileEntry[] | null\n content: string | null\n}\n\ninterface FileWriteResponse {\n path: string\n created: boolean\n}\n\ninterface MkdirResponse {\n path: string\n created: boolean\n}\n\ninterface DeleteResponse {\n path: string\n}\n\ninterface FileUrlResponse {\n path: string\n url: string\n}\n\nfunction addSpaceOptions(cmd: Command): Command {\n return cmd\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .option('-s, --space <name>', 'Space name (personal or teamspace name)')\n .option('--personal', 'Use personal space (default)')\n .option('--team-space-id <teamSpaceId>', 'Team space ID')\n .option('--teammate-id <teammateId>', 'Teammate ID (teammate space)')\n}\n\nexport function registerFileCommand(program: Command): void {\n const file = program.command('file').description('File operations')\n\n addSpaceOptions(\n file.command('get-url')\n .description('Resolve the shareable browser URL for a file')\n .requiredOption('-p, --path <path>', 'File path'),\n ).action(async (options: SpaceOptions & { path: string }) => {\n const spaceParams = runOrExit(() => resolveSpaceSelector(options))\n const qs = buildFileQueryString(options.path, spaceParams)\n\n startSpinner('Resolving URL...')\n const response = await httpGet<FileUrlResponse>(\n `/workspaces/${options.workspace}/files/url${qs}`,\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ ${options.path} does not exist${colors.reset}`)\n } else if (response.status === 400) {\n printError(`Error: ${JSON.stringify(response.data)}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n stopSpinner(true, response.data.path)\n print(`${colors.cyan}${response.data.url}${colors.reset}`)\n })\n\n addSpaceOptions(\n file.command('list')\n .description('List directory contents')\n .option('-p, --path <path>', 'Directory path', '/'),\n ).action(async (options: SpaceOptions & { path: string }) => {\n const spaceParams = runOrExit(() => resolveSpaceSelector(options))\n const qs = buildFileQueryString(options.path, spaceParams)\n\n startSpinner('Listing files...')\n const response = await httpGet<FileReadResponse>(\n `/workspaces/${options.workspace}/files/list${qs}`,\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ ${options.path} does not exist${colors.reset}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const { path, entries } = response.data\n\n if (!entries || entries.length === 0) {\n stopSpinner(true, `${path}: empty directory`)\n return\n }\n\n stopSpinner(true, path)\n for (const entry of entries) {\n if (entry.type === 'directory') {\n print(`${colors.blue}${entry.name}/${colors.reset}`)\n } else {\n print(entry.name)\n }\n }\n })\n\n file.command('read')\n .description('Read file content')\n .option('-w, --workspace <workspaceId>', 'Workspace ID')\n .option('-s, --space <name>', 'Space name (personal or teamspace name)')\n .option('--personal', 'Use personal space (default)')\n .option('--team-space-id <teamSpaceId>', 'Team space ID')\n .option('--teammate-id <teammateId>', 'Teammate ID (teammate space)')\n .option('-p, --path <path>', 'File path')\n .option('-u, --url <url>', 'Moxt file URL (e.g., https://moxt.ai/w/{workspaceId}/{fileId})')\n .action(async (options: Partial<SpaceOptions> & { path?: string; url?: string }) => {\n const mode = runOrExit(() => resolveReadMode(options))\n\n startSpinner('Reading file...')\n\n let response: { ok: boolean; status: number; data: FileReadResponse }\n let displayPath: string\n\n if (mode.kind === 'by-url') {\n displayPath = mode.url\n response = await httpGet<FileReadResponse>(\n `/files/read-by-url?url=${encodeURIComponent(mode.url)}`,\n )\n } else {\n displayPath = mode.path\n const spaceParams = runOrExit(() => resolveSpaceSelector(options as SpaceOptions))\n const qs = buildFileQueryString(mode.path, spaceParams)\n response = await httpGet<FileReadResponse>(\n `/workspaces/${mode.workspace}/files/read${qs}`,\n )\n }\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ ${displayPath} does not exist${colors.reset}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const { type, content } = response.data\n\n if (type === 'directory') {\n stopSpinner(false, 'Failed')\n print(`${colors.red}☠ ${displayPath} is a directory${colors.reset}`)\n process.exit(1)\n }\n\n stopSpinner(true, 'Done')\n print(content ?? '')\n })\n\n file.command('put')\n .description('Upload a file')\n .option('-w, --workspace <workspaceId>', 'Workspace ID')\n .option('-s, --space <name>', 'Space name (personal or teamspace name)')\n .option('--personal', 'Use personal space (default)')\n .option('--team-space-id <teamSpaceId>', 'Team space ID')\n .option('--teammate-id <teammateId>', 'Teammate ID (teammate space)')\n .option('-p, --path <path>', 'Remote file path')\n .option('-u, --url <url>', 'Moxt file URL (e.g., https://moxt.ai/w/{workspaceId}/{fileId})')\n .requiredOption('-l, --local-path <localPath>', 'Local file path')\n .option('-r, --recursive', 'Create parent directories if needed')\n .action(\n async (options: Partial<SpaceOptions> & {\n path?: string\n url?: string\n localPath: string\n recursive?: boolean\n }) => {\n const mode = runOrExit(() => resolveWriteMode(options))\n\n // check local file exists\n if (!fs.existsSync(options.localPath)) {\n print(`${colors.red}☠ Local file not found: ${options.localPath}${colors.reset}`)\n process.exit(1)\n }\n\n // check it is a file, not a directory\n const stats = fs.statSync(options.localPath)\n if (!stats.isFile()) {\n print(`${colors.red}☠ Not a file: ${options.localPath}${colors.reset}`)\n process.exit(1)\n }\n\n // check file size (10MB limit)\n const maxSize = 10 * 1024 * 1024\n if (stats.size > maxSize) {\n print(`${colors.red}☠ File too large (max 10MB): ${options.localPath}${colors.reset}`)\n process.exit(1)\n }\n\n // read file and check for binary content\n const buffer = fs.readFileSync(options.localPath)\n if (isBinaryContent(buffer)) {\n print(`${colors.red}☠ Binary files are not allowed. Only text files can be uploaded.${colors.reset}`)\n process.exit(1)\n }\n\n const content = buffer.toString('utf8')\n\n startSpinner('Uploading...')\n\n let response: { ok: boolean; status: number; data: FileWriteResponse }\n let displayPath: string\n\n if (mode.kind === 'by-url') {\n displayPath = mode.url\n response = await httpPut<FileWriteResponse>('/files/write-by-url', {\n url: mode.url,\n content,\n })\n } else {\n displayPath = mode.path\n const spaceParams = runOrExit(() => resolveSpaceSelector(options as SpaceOptions))\n response = await httpPut<FileWriteResponse>(\n `/workspaces/${mode.workspace}/files/write`,\n {\n path: mode.path,\n content,\n recursive: options.recursive ?? false,\n ...spaceParams,\n },\n )\n }\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n if (mode.kind === 'by-url') {\n print(`${colors.red}☠ ${displayPath} does not exist${colors.reset}`)\n } else {\n print(`${colors.red}☠ Parent directory does not exist${colors.reset}`)\n }\n } else if (response.status === 400) {\n printError(`Error: ${JSON.stringify(response.data)}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const action = response.data.created ? 'Created' : 'Updated'\n stopSpinner(true, `${action}: ${response.data.path}`)\n },\n )\n\n addSpaceOptions(\n file.command('mkdir')\n .description('Create a directory')\n .requiredOption('-p, --path <path>', 'Directory path')\n .option('-r, --recursive', 'Create parent directories if needed'),\n ).action(\n async (options: SpaceOptions & {\n path: string\n recursive?: boolean\n }) => {\n const spaceParams = runOrExit(() => resolveSpaceSelector(options))\n\n startSpinner('Creating directory...')\n const response = await httpPost<MkdirResponse>(\n `/workspaces/${options.workspace}/files/mkdir`,\n {\n path: options.path,\n recursive: options.recursive ?? false,\n ...spaceParams,\n },\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ Parent directory does not exist${colors.reset}`)\n } else if (response.status === 400) {\n printError(`Error: ${JSON.stringify(response.data)}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n const action = response.data.created ? 'Created' : 'Already exists'\n stopSpinner(true, `${action}: ${response.data.path}`)\n },\n )\n\n addSpaceOptions(\n file.command('del')\n .description('Delete a file or empty directory')\n .requiredOption('-p, --path <path>', 'File or directory path'),\n ).action(\n async (options: SpaceOptions & {\n path: string\n }) => {\n const spaceParams = runOrExit(() => resolveSpaceSelector(options))\n\n startSpinner('Deleting...')\n const response = await httpDelete<DeleteResponse>(\n `/workspaces/${options.workspace}/files/delete`,\n {\n path: options.path,\n ...spaceParams,\n },\n )\n\n if (!response.ok) {\n stopSpinner(false, 'Failed')\n if (response.status === 404) {\n print(`${colors.red}☠ Path not found: ${options.path}${colors.reset}`)\n } else if (response.status === 400) {\n print(`${colors.red}☠ Cannot delete non-empty directory${colors.reset}`)\n } else {\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n }\n process.exit(1)\n }\n\n stopSpinner(true, `Deleted: ${response.data.path}`)\n },\n )\n}\n","/**\n * Pure logic for resolving file-command space selectors and building request URLs.\n *\n * These functions are extracted from commands/file.ts so they can be unit tested\n * without spawning the CLI or mocking process.exit. All error conditions are\n * surfaced as thrown Errors; action handlers are responsible for turning them\n * into user-facing output and exit codes.\n */\n\nexport interface SpaceOptions {\n workspace: string\n space?: string\n personal?: boolean\n teamSpaceId?: string\n teammateId?: string\n}\n\nexport interface SpaceParams {\n space?: string\n teamSpaceId?: string\n agentId?: number\n}\n\n/**\n * Error thrown when selector options violate a contract (mutually exclusive,\n * wrong format, etc). Action handlers catch this and print the message before\n * exiting with code 1.\n */\nexport class SpaceOptionsError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SpaceOptionsError'\n }\n}\n\n/**\n * Resolve mutually-exclusive space selector flags into normalized request params.\n *\n * Priority (only one must be set): --team-space-id > --teammate-id > --personal > -s <name>.\n * When none is set, returns empty params (server treats this as personal space).\n */\nexport function resolveSpaceSelector(options: SpaceOptions): SpaceParams {\n // Destructure first so TypeScript's control-flow analysis can narrow each\n // field through the subsequent non-null / non-empty checks without having\n // to re-read options.* at the point of use (which would lose narrowing).\n const { space, teamSpaceId, teammateId } = options\n const personalIsSet = options.personal === true\n\n // Count \"user-set\" selectors explicitly so the mutual-exclusion check\n // reflects intent (\"which flags did the user pass?\") rather than a\n // generic truthiness filter. This keeps the mutual-exclusion check\n // cleanly separated from the downstream format validation (e.g.\n // `parsed <= 0` for teammateId).\n const spaceIsSet = space != null && space !== ''\n const teamSpaceIdIsSet = teamSpaceId != null && teamSpaceId !== ''\n const teammateIdIsSet = teammateId != null && teammateId !== ''\n const selectorCount =\n (spaceIsSet ? 1 : 0) + (personalIsSet ? 1 : 0) + (teamSpaceIdIsSet ? 1 : 0) + (teammateIdIsSet ? 1 : 0)\n if (selectorCount > 1) {\n throw new SpaceOptionsError(\n 'Error: -s, --personal, --team-space-id, and --teammate-id are mutually exclusive.',\n )\n }\n\n // Dispatch via the underlying field checks (not `*IsSet`) so TypeScript\n // narrows each local to `string`, letting us return without `!`.\n if (teamSpaceId != null && teamSpaceId !== '') {\n return { teamSpaceId }\n }\n if (teammateId != null && teammateId !== '') {\n const parsed = Number.parseInt(teammateId, 10)\n if (!Number.isInteger(parsed) || parsed <= 0 || String(parsed) !== teammateId) {\n throw new SpaceOptionsError(\n `Error: --teammate-id must be a positive integer, got \"${teammateId}\".`,\n )\n }\n return { agentId: parsed }\n }\n if (personalIsSet) {\n return { space: 'personal' }\n }\n if (space != null && space !== '') {\n return { space }\n }\n return {}\n}\n\n/**\n * Build the `?path=...&space=...` query string for file endpoints.\n * Returns empty string when no params are set (caller should not append `?`).\n * Values are URL-encoded via URLSearchParams.\n *\n * An empty-string `path` is treated as \"not provided\" and omitted from the query;\n * callers should pass `undefined` rather than `\"\"` when no path is intended.\n */\nexport function buildFileQueryString(path: string | undefined, spaceParams: SpaceParams): string {\n const params = new URLSearchParams()\n if (path != null && path !== '') {\n params.set('path', path)\n }\n if (spaceParams.space) {\n params.set('space', spaceParams.space)\n }\n if (spaceParams.teamSpaceId) {\n params.set('teamSpaceId', spaceParams.teamSpaceId)\n }\n if (spaceParams.agentId != null) {\n params.set('agentId', String(spaceParams.agentId))\n }\n const qs = params.toString()\n return qs ? `?${qs}` : ''\n}\n\n/**\n * Detect if a Buffer contains binary content by sampling the first 8192 bytes.\n * Control characters other than tab (9), LF (10), and CR (13) are treated as binary.\n */\nexport function isBinaryContent(buffer: Buffer): boolean {\n const sampleSize = Math.min(buffer.length, 8192)\n\n for (let i = 0; i < sampleSize; i++) {\n const byte = buffer[i]\n if (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Validate `file read` command's top-level mutually-exclusive options (-u vs -w/-p).\n * Returns the resolved mode ('by-url' or 'by-path'). Throws SpaceOptionsError on conflict.\n *\n * Empty strings are treated as \"not provided\" (commander never passes empty strings\n * for optional flags, but callers outside the CLI context should pass undefined instead\n * of \"\" to avoid unexpected branch behaviour).\n */\nexport type ReadMode = { kind: 'by-url'; url: string } | { kind: 'by-path'; workspace: string; path: string }\n\nexport function resolveReadMode(options: {\n url?: string\n workspace?: string\n path?: string\n}): ReadMode {\n if (options.url && options.workspace) {\n throw new SpaceOptionsError('Error: --url cannot be used with --workspace')\n }\n if (options.url && options.path) {\n throw new SpaceOptionsError('Error: --url cannot be used with --path')\n }\n if (!options.url && !options.workspace) {\n throw new SpaceOptionsError('Error: Either --url or --workspace is required')\n }\n if (!options.url && !options.path) {\n throw new SpaceOptionsError('Error: --path is required when not using --url')\n }\n\n if (options.url) {\n return { kind: 'by-url', url: options.url }\n }\n // At this point both workspace and path are guaranteed non-empty by the guards\n // above. Use explicit checks so TypeScript narrows the types without needing `!`.\n if (!options.workspace) {\n throw new SpaceOptionsError('Error: Either --url or --workspace is required')\n }\n if (!options.path) {\n throw new SpaceOptionsError('Error: --path is required when not using --url')\n }\n return { kind: 'by-path', workspace: options.workspace, path: options.path }\n}\n\n/**\n * Validate `file put` command's top-level mutually-exclusive options (-u vs -w/-p).\n *\n * By-URL puts overwrite an existing file (the URL already identifies it), so\n * `--recursive` is meaningless in that mode and is rejected outright to keep the\n * user's intent unambiguous.\n */\nexport type WriteMode =\n | { kind: 'by-url'; url: string }\n | { kind: 'by-path'; workspace: string; path: string }\n\nexport function resolveWriteMode(options: {\n url?: string\n workspace?: string\n path?: string\n recursive?: boolean\n}): WriteMode {\n if (options.url && options.workspace) {\n throw new SpaceOptionsError('Error: --url cannot be used with --workspace')\n }\n if (options.url && options.path) {\n throw new SpaceOptionsError('Error: --url cannot be used with --path')\n }\n if (options.url && options.recursive) {\n throw new SpaceOptionsError('Error: --recursive cannot be used with --url (the file must already exist)')\n }\n if (!options.url && !options.workspace) {\n throw new SpaceOptionsError('Error: Either --url or --workspace is required')\n }\n if (!options.url && !options.path) {\n throw new SpaceOptionsError('Error: --path is required when not using --url')\n }\n\n if (options.url) {\n return { kind: 'by-url', url: options.url }\n }\n return { kind: 'by-path', workspace: options.workspace!, path: options.path! }\n}\n","import { arch, platform } from 'os'\nimport { getApiBaseUrl, getApiKey } from './config.js'\n\ndeclare const __CLI_VERSION__: string\n\nexport interface ApiResponse<T> {\n ok: boolean\n status: number\n data: T\n}\n\nfunction getUserAgent(): string {\n return `moxt-cli/${__CLI_VERSION__} (${platform()}/${arch()}) node/${process.versions.node}`\n}\n\nasync function request<T>(method: string, path: string, body?: unknown): Promise<ApiResponse<T>> {\n const apiKey = getApiKey()\n const url = `${getApiBaseUrl()}${path}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n 'User-Agent': getUserAgent(),\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n\n let data: T\n const contentType = response.headers.get('content-type')\n if (contentType?.includes('application/json')) {\n data = (await response.json()) as T\n } else {\n data = (await response.text()) as T\n }\n\n if (response.status === 401) {\n console.error('Authentication failed. Check your MOXT_API_KEY.')\n console.error('Get a new key at: https://moxt.ai')\n process.exit(1)\n }\n\n return {\n ok: response.ok,\n status: response.status,\n data,\n }\n}\n\nexport async function httpGet<T>(path: string): Promise<ApiResponse<T>> {\n return request<T>('GET', path)\n}\n\nexport async function httpPut<T>(path: string, body: unknown): Promise<ApiResponse<T>> {\n return request<T>('PUT', path, body)\n}\n\nexport async function httpPost<T>(path: string, body: unknown): Promise<ApiResponse<T>> {\n return request<T>('POST', path, body)\n}\n\nexport async function httpDelete<T>(path: string, body?: unknown): Promise<ApiResponse<T>> {\n return request<T>('DELETE', path, body)\n}\n","const DEFAULT_HOST = 'api.moxt.ai'\n\nexport function getApiBaseUrl(): string {\n const host = process.env.MOXT_HOST ?? DEFAULT_HOST\n return `https://${host}/openapi/v1`\n}\n\nexport function getApiKey(): string {\n const apiKey = process.env.MOXT_API_KEY\n\n if (!apiKey) {\n console.error('MOXT_API_KEY environment variable is not set.')\n console.error('')\n console.error('Get your API key at: https://moxt.ai')\n console.error('')\n console.error('Then set it:')\n console.error(' export MOXT_API_KEY=moxt_...')\n process.exit(1)\n }\n\n return apiKey\n}\n","// ANSI colors\nexport const colors = {\n bold: '\\x1b[1m',\n blue: '\\x1b[1;34m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n cyan: '\\x1b[36m',\n dim: '\\x1b[2m',\n reset: '\\x1b[0m',\n}\n\nexport function print(message: string): void {\n console.log(message)\n}\n\nexport function printError(message: string): void {\n console.error(`${colors.red}${message}${colors.reset}`)\n}\n","const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']\n\nlet intervalId: ReturnType<typeof setInterval> | null = null\nlet frameIndex = 0\n\nexport function startSpinner(message: string): void {\n frameIndex = 0\n process.stdout.write(`${frames[frameIndex]} ${message}`)\n\n intervalId = setInterval(() => {\n frameIndex = (frameIndex + 1) % frames.length\n process.stdout.write(`\\r${frames[frameIndex]} ${message}`)\n }, 80)\n}\n\nexport function stopSpinner(success: boolean, message?: string): void {\n if (intervalId) {\n clearInterval(intervalId)\n intervalId = null\n }\n\n const symbol = success ? '\\x1b[32m✓\\x1b[0m' : '\\x1b[31m✗\\x1b[0m'\n // \\x1b[2K 清除整行,\\r 回到行首\n process.stdout.write(`\\x1b[2K\\r${symbol} ${message ?? ''}\\n`)\n}\n","import { Command } from 'commander'\nimport { httpGet } from '../utils/http.js'\nimport { colors, print, printError } from '../utils/output.js'\nimport { startSpinner, stopSpinner } from '../utils/spinner.js'\n\ninterface WhoamiResponse {\n nickname: string\n email: string\n}\n\nexport function registerWhoamiCommand(program: Command): void {\n program\n .command('whoami')\n .description('Show current user information')\n .action(async () => {\n startSpinner('Fetching user info...')\n const response = await httpGet<WhoamiResponse>('/users/whoami')\n\n if (response.ok) {\n stopSpinner(true, 'Done')\n print(`${colors.bold}Nickname${colors.reset}: ${response.data.nickname}`)\n print(`${colors.bold}Email${colors.reset}: ${response.data.email}`)\n } else {\n stopSpinner(false, 'Failed')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport { httpGet, httpDelete } from '../utils/http.js'\nimport { colors, print, printError } from '../utils/output.js'\nimport { startSpinner, stopSpinner } from '../utils/spinner.js'\n\ninterface WorkspaceItem {\n workspaceId: string\n name: string\n}\n\ninterface WorkspaceListResponse {\n workspaces: WorkspaceItem[]\n}\n\ninterface MemberItem {\n userId: number\n email: string\n displayName: string | null\n role: string\n}\n\ninterface MembersResponse {\n members: MemberItem[]\n}\n\ninterface SpaceItem {\n type: 'personal' | 'team' | 'teammate'\n name: string\n teamSpaceId: string | null\n agentId: number | null\n}\n\n// Email regex (same as web/src/utils/email.ts)\nconst emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/\n\nfunction isValidEmail(email: string): boolean {\n return emailRegex.test(email)\n}\n\nexport function registerWorkspaceCommand(program: Command): void {\n const workspace = program.command('workspace').description('Workspace management')\n\n workspace\n .command('list')\n .description('List all workspaces you belong to')\n .action(async () => {\n startSpinner('Fetching workspaces...')\n const response = await httpGet<WorkspaceListResponse>('/workspaces')\n\n if (response.ok) {\n const { workspaces } = response.data\n if (workspaces.length === 0) {\n stopSpinner(true, 'No workspaces found.')\n return\n }\n\n stopSpinner(true, `Found ${workspaces.length} workspace(s)`)\n\n for (const ws of workspaces) {\n print(`${colors.bold}${ws.workspaceId}${colors.reset}\\t${ws.name}`)\n }\n } else {\n stopSpinner(false, 'Failed')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n })\n\n const members = program.command('members').description('Manage workspace members')\n\n members\n .command('list')\n .description('List all members in a workspace')\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .action(async (options: { workspace: string }) => {\n const { workspace: workspaceId } = options\n\n startSpinner('Fetching workspace members...')\n const response = await httpGet<MembersResponse>(`/workspaces/${workspaceId}/members`)\n\n if (!response.ok) {\n stopSpinner(false, 'Failed to fetch members')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n\n const { members } = response.data\n if (members.length === 0) {\n stopSpinner(true, 'No members found.')\n return\n }\n\n stopSpinner(true, `Found ${members.length} member(s)`)\n\n for (const member of members) {\n const name = member.displayName || '-'\n print(`${colors.bold}${member.email}${colors.reset}\\t${name}\\t${member.role}`)\n }\n })\n\n members\n .command('remove')\n .description('Remove members from a workspace')\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .argument('<emails>', 'Emails to remove (comma-separated)')\n .action(async (emailsArg: string, options: { workspace: string }) => {\n const { workspace: workspaceId } = options\n\n const emails = emailsArg.split(',').map((e) => e.trim()).filter(Boolean)\n if (emails.length === 0) {\n printError('No valid emails provided')\n process.exit(1)\n }\n\n // Validate email format\n const invalidEmails = emails.filter((e) => !isValidEmail(e))\n if (invalidEmails.length > 0) {\n for (const email of invalidEmails) {\n printError(`Invalid email format: ${email}`)\n }\n process.exit(1)\n }\n\n // Fetch members to get userId by email\n startSpinner('Fetching workspace members...')\n const membersResponse = await httpGet<MembersResponse>(`/workspaces/${workspaceId}/members`)\n\n if (!membersResponse.ok) {\n stopSpinner(false, 'Failed to fetch members')\n printError(`Error [${membersResponse.status}]: ${JSON.stringify(membersResponse.data)}`)\n process.exit(1)\n }\n\n stopSpinner(true, 'Members fetched')\n\n const { members } = membersResponse.data\n const emailToMember = new Map(members.map((m) => [m.email.toLowerCase(), m]))\n\n // Remove each member\n for (const email of emails) {\n const member = emailToMember.get(email.toLowerCase())\n if (!member) {\n print(`${colors.red}✗${colors.reset} ${email} - not found in workspace`)\n continue\n }\n\n const deleteResponse = await httpDelete(`/workspaces/${workspaceId}/members/${member.userId}`)\n\n if (deleteResponse.ok) {\n print(`${colors.green}✓${colors.reset} ${email} - removed`)\n } else {\n print(`${colors.red}✗${colors.reset} ${email} - failed: ${JSON.stringify(deleteResponse.data)}`)\n }\n }\n })\n\n const space = program.command('space').description('Manage spaces')\n\n space\n .command('list')\n .description('List accessible spaces in a workspace')\n .requiredOption('-w, --workspace <workspaceId>', 'Workspace ID')\n .action(async (options: { workspace: string }) => {\n const { workspace: workspaceId } = options\n\n startSpinner('Fetching spaces...')\n const response = await httpGet<{ spaces: SpaceItem[] }>(`/workspaces/${workspaceId}/spaces`)\n\n if (!response.ok) {\n stopSpinner(false, 'Failed to fetch spaces')\n printError(`Error [${response.status}]: ${JSON.stringify(response.data)}`)\n process.exit(1)\n }\n\n const { spaces } = response.data\n if (spaces.length === 0) {\n stopSpinner(true, 'No spaces found.')\n return\n }\n\n stopSpinner(true, `Found ${spaces.length} space(s)`)\n\n print(\n `${colors.bold}TYPE${colors.reset}\\t${colors.bold}TEAM_SPACE_ID${colors.reset}\\t${colors.bold}TEAMMATE_ID${colors.reset}\\t${colors.bold}NAME${colors.reset}`,\n )\n for (const s of spaces) {\n const teamSpaceId = s.teamSpaceId ?? ''\n const teammateId = s.agentId != null ? String(s.agentId) : ''\n print(`${s.type}\\t${teamSpaceId}\\t${teammateId}\\t${s.name}`)\n }\n })\n\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,OAAO,oBAAoB;;;ACD3B,YAAY,QAAQ;;;AC4Bb,IAAM,oBAAN,cAAgC,MAAM;AAAA,EACzC,YAAY,SAAiB;AACzB,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EAChB;AACJ;AAQO,SAAS,qBAAqB,SAAoC;AAIrE,QAAM,EAAE,OAAO,aAAa,WAAW,IAAI;AAC3C,QAAM,gBAAgB,QAAQ,aAAa;AAO3C,QAAM,aAAa,SAAS,QAAQ,UAAU;AAC9C,QAAM,mBAAmB,eAAe,QAAQ,gBAAgB;AAChE,QAAM,kBAAkB,cAAc,QAAQ,eAAe;AAC7D,QAAM,iBACD,aAAa,IAAI,MAAM,gBAAgB,IAAI,MAAM,mBAAmB,IAAI,MAAM,kBAAkB,IAAI;AACzG,MAAI,gBAAgB,GAAG;AACnB,UAAM,IAAI;AAAA,MACN;AAAA,IACJ;AAAA,EACJ;AAIA,MAAI,eAAe,QAAQ,gBAAgB,IAAI;AAC3C,WAAO,EAAE,YAAY;AAAA,EACzB;AACA,MAAI,cAAc,QAAQ,eAAe,IAAI;AACzC,UAAM,SAAS,OAAO,SAAS,YAAY,EAAE;AAC7C,QAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,KAAK,OAAO,MAAM,MAAM,YAAY;AAC3E,YAAM,IAAI;AAAA,QACN,yDAAyD,UAAU;AAAA,MACvE;AAAA,IACJ;AACA,WAAO,EAAE,SAAS,OAAO;AAAA,EAC7B;AACA,MAAI,eAAe;AACf,WAAO,EAAE,OAAO,WAAW;AAAA,EAC/B;AACA,MAAI,SAAS,QAAQ,UAAU,IAAI;AAC/B,WAAO,EAAE,MAAM;AAAA,EACnB;AACA,SAAO,CAAC;AACZ;AAUO,SAAS,qBAAqB,MAA0B,aAAkC;AAC7F,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,QAAQ,QAAQ,SAAS,IAAI;AAC7B,WAAO,IAAI,QAAQ,IAAI;AAAA,EAC3B;AACA,MAAI,YAAY,OAAO;AACnB,WAAO,IAAI,SAAS,YAAY,KAAK;AAAA,EACzC;AACA,MAAI,YAAY,aAAa;AACzB,WAAO,IAAI,eAAe,YAAY,WAAW;AAAA,EACrD;AACA,MAAI,YAAY,WAAW,MAAM;AAC7B,WAAO,IAAI,WAAW,OAAO,YAAY,OAAO,CAAC;AAAA,EACrD;AACA,QAAM,KAAK,OAAO,SAAS;AAC3B,SAAO,KAAK,IAAI,EAAE,KAAK;AAC3B;AAMO,SAAS,gBAAgB,QAAyB;AACrD,QAAM,aAAa,KAAK,IAAI,OAAO,QAAQ,IAAI;AAE/C,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACjC,UAAM,OAAO,OAAO,CAAC;AACrB,QAAI,OAAO,MAAM,SAAS,KAAK,SAAS,MAAM,SAAS,IAAI;AACvD,aAAO;AAAA,IACX;AAAA,EACJ;AAEA,SAAO;AACX;AAYO,SAAS,gBAAgB,SAInB;AACT,MAAI,QAAQ,OAAO,QAAQ,WAAW;AAClC,UAAM,IAAI,kBAAkB,8CAA8C;AAAA,EAC9E;AACA,MAAI,QAAQ,OAAO,QAAQ,MAAM;AAC7B,UAAM,IAAI,kBAAkB,yCAAyC;AAAA,EACzE;AACA,MAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,WAAW;AACpC,UAAM,IAAI,kBAAkB,gDAAgD;AAAA,EAChF;AACA,MAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,MAAM;AAC/B,UAAM,IAAI,kBAAkB,gDAAgD;AAAA,EAChF;AAEA,MAAI,QAAQ,KAAK;AACb,WAAO,EAAE,MAAM,UAAU,KAAK,QAAQ,IAAI;AAAA,EAC9C;AAGA,MAAI,CAAC,QAAQ,WAAW;AACpB,UAAM,IAAI,kBAAkB,gDAAgD;AAAA,EAChF;AACA,MAAI,CAAC,QAAQ,MAAM;AACf,UAAM,IAAI,kBAAkB,gDAAgD;AAAA,EAChF;AACA,SAAO,EAAE,MAAM,WAAW,WAAW,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC/E;AAaO,SAAS,iBAAiB,SAKnB;AACV,MAAI,QAAQ,OAAO,QAAQ,WAAW;AAClC,UAAM,IAAI,kBAAkB,8CAA8C;AAAA,EAC9E;AACA,MAAI,QAAQ,OAAO,QAAQ,MAAM;AAC7B,UAAM,IAAI,kBAAkB,yCAAyC;AAAA,EACzE;AACA,MAAI,QAAQ,OAAO,QAAQ,WAAW;AAClC,UAAM,IAAI,kBAAkB,4EAA4E;AAAA,EAC5G;AACA,MAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,WAAW;AACpC,UAAM,IAAI,kBAAkB,gDAAgD;AAAA,EAChF;AACA,MAAI,CAAC,QAAQ,OAAO,CAAC,QAAQ,MAAM;AAC/B,UAAM,IAAI,kBAAkB,gDAAgD;AAAA,EAChF;AAEA,MAAI,QAAQ,KAAK;AACb,WAAO,EAAE,MAAM,UAAU,KAAK,QAAQ,IAAI;AAAA,EAC9C;AACA,SAAO,EAAE,MAAM,WAAW,WAAW,QAAQ,WAAY,MAAM,QAAQ,KAAM;AACjF;;;ACjNA,SAAS,MAAM,gBAAgB;;;ACA/B,IAAM,eAAe;AAEd,SAAS,gBAAwB;AACpC,QAAM,OAAO,QAAQ,IAAI,aAAa;AACtC,SAAO,WAAW,IAAI;AAC1B;AAEO,SAAS,YAAoB;AAChC,QAAM,SAAS,QAAQ,IAAI;AAE3B,MAAI,CAAC,QAAQ;AACT,YAAQ,MAAM,+CAA+C;AAC7D,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,sCAAsC;AACpD,YAAQ,MAAM,EAAE;AAChB,YAAQ,MAAM,cAAc;AAC5B,YAAQ,MAAM,gCAAgC;AAC9C,YAAQ,KAAK,CAAC;AAAA,EAClB;AAEA,SAAO;AACX;;;ADVA,SAAS,eAAuB;AAC5B,SAAO,YAAY,OAAe,KAAK,SAAS,CAAC,IAAI,KAAK,CAAC,UAAU,QAAQ,SAAS,IAAI;AAC9F;AAEA,eAAe,QAAW,QAAgB,MAAc,MAAyC;AAC7F,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,GAAG,cAAc,CAAC,GAAG,IAAI;AAErC,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAC9B;AAAA,IACA,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,eAAe,UAAU,MAAM;AAAA,MAC/B,cAAc,aAAa;AAAA,IAC/B;AAAA,IACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EACxC,CAAC;AAED,MAAI;AACJ,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AACvD,MAAI,aAAa,SAAS,kBAAkB,GAAG;AAC3C,WAAQ,MAAM,SAAS,KAAK;AAAA,EAChC,OAAO;AACH,WAAQ,MAAM,SAAS,KAAK;AAAA,EAChC;AAEA,MAAI,SAAS,WAAW,KAAK;AACzB,YAAQ,MAAM,iDAAiD;AAC/D,YAAQ,MAAM,mCAAmC;AACjD,YAAQ,KAAK,CAAC;AAAA,EAClB;AAEA,SAAO;AAAA,IACH,IAAI,SAAS;AAAA,IACb,QAAQ,SAAS;AAAA,IACjB;AAAA,EACJ;AACJ;AAEA,eAAsB,QAAW,MAAuC;AACpE,SAAO,QAAW,OAAO,IAAI;AACjC;AAEA,eAAsB,QAAW,MAAc,MAAwC;AACnF,SAAO,QAAW,OAAO,MAAM,IAAI;AACvC;AAEA,eAAsB,SAAY,MAAc,MAAwC;AACpF,SAAO,QAAW,QAAQ,MAAM,IAAI;AACxC;AAEA,eAAsB,WAAc,MAAc,MAAyC;AACvF,SAAO,QAAW,UAAU,MAAM,IAAI;AAC1C;;;AE/DO,IAAM,SAAS;AAAA,EAClB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AACX;AAEO,SAAS,MAAM,SAAuB;AACzC,UAAQ,IAAI,OAAO;AACvB;AAEO,SAAS,WAAW,SAAuB;AAC9C,UAAQ,MAAM,GAAG,OAAO,GAAG,GAAG,OAAO,GAAG,OAAO,KAAK,EAAE;AAC1D;;;ACjBA,IAAM,SAAS,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AAEhE,IAAI,aAAoD;AACxD,IAAI,aAAa;AAEV,SAAS,aAAa,SAAuB;AAChD,eAAa;AACb,UAAQ,OAAO,MAAM,GAAG,OAAO,UAAU,CAAC,IAAI,OAAO,EAAE;AAEvD,eAAa,YAAY,MAAM;AAC3B,kBAAc,aAAa,KAAK,OAAO;AACvC,YAAQ,OAAO,MAAM,KAAK,OAAO,UAAU,CAAC,IAAI,OAAO,EAAE;AAAA,EAC7D,GAAG,EAAE;AACT;AAEO,SAAS,YAAY,SAAkB,SAAwB;AAClE,MAAI,YAAY;AACZ,kBAAc,UAAU;AACxB,iBAAa;AAAA,EACjB;AAEA,QAAM,SAAS,UAAU,0BAAqB;AAE9C,UAAQ,OAAO,MAAM,YAAY,MAAM,IAAI,WAAW,EAAE;AAAA,CAAI;AAChE;;;ALHA,SAAS,UAAa,IAAgB;AAClC,MAAI;AACA,WAAO,GAAG;AAAA,EACd,SAAS,KAAK;AACV,QAAI,eAAe,mBAAmB;AAClC,iBAAW,IAAI,OAAO;AACtB,cAAQ,KAAK,CAAC;AAAA,IAClB;AACA,UAAM;AAAA,EACV;AACJ;AAkCA,SAAS,gBAAgB,KAAuB;AAC5C,SAAO,IACF,eAAe,iCAAiC,cAAc,EAC9D,OAAO,sBAAsB,yCAAyC,EACtE,OAAO,cAAc,8BAA8B,EACnD,OAAO,iCAAiC,eAAe,EACvD,OAAO,8BAA8B,8BAA8B;AAC5E;AAEO,SAAS,oBAAoBA,UAAwB;AACxD,QAAM,OAAOA,SAAQ,QAAQ,MAAM,EAAE,YAAY,iBAAiB;AAElE;AAAA,IACI,KAAK,QAAQ,SAAS,EACjB,YAAY,8CAA8C,EAC1D,eAAe,qBAAqB,WAAW;AAAA,EACxD,EAAE,OAAO,OAAO,YAA6C;AACzD,UAAM,cAAc,UAAU,MAAM,qBAAqB,OAAO,CAAC;AACjE,UAAM,KAAK,qBAAqB,QAAQ,MAAM,WAAW;AAEzD,iBAAa,kBAAkB;AAC/B,UAAM,WAAW,MAAM;AAAA,MACnB,eAAe,QAAQ,SAAS,aAAa,EAAE;AAAA,IACnD;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,kBAAY,OAAO,QAAQ;AAC3B,UAAI,SAAS,WAAW,KAAK;AACzB,cAAM,GAAG,OAAO,GAAG,UAAK,QAAQ,IAAI,kBAAkB,OAAO,KAAK,EAAE;AAAA,MACxE,WAAW,SAAS,WAAW,KAAK;AAChC,mBAAW,UAAU,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,MACxD,OAAO;AACH,mBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,MAC7E;AACA,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,gBAAY,MAAM,SAAS,KAAK,IAAI;AACpC,UAAM,GAAG,OAAO,IAAI,GAAG,SAAS,KAAK,GAAG,GAAG,OAAO,KAAK,EAAE;AAAA,EAC7D,CAAC;AAED;AAAA,IACI,KAAK,QAAQ,MAAM,EACd,YAAY,yBAAyB,EACrC,OAAO,qBAAqB,kBAAkB,GAAG;AAAA,EAC1D,EAAE,OAAO,OAAO,YAA6C;AACzD,UAAM,cAAc,UAAU,MAAM,qBAAqB,OAAO,CAAC;AACjE,UAAM,KAAK,qBAAqB,QAAQ,MAAM,WAAW;AAEzD,iBAAa,kBAAkB;AAC/B,UAAM,WAAW,MAAM;AAAA,MACnB,eAAe,QAAQ,SAAS,cAAc,EAAE;AAAA,IACpD;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,kBAAY,OAAO,QAAQ;AAC3B,UAAI,SAAS,WAAW,KAAK;AACzB,cAAM,GAAG,OAAO,GAAG,UAAK,QAAQ,IAAI,kBAAkB,OAAO,KAAK,EAAE;AAAA,MACxE,OAAO;AACH,mBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,MAC7E;AACA,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,SAAS;AAEnC,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AAClC,kBAAY,MAAM,GAAG,IAAI,mBAAmB;AAC5C;AAAA,IACJ;AAEA,gBAAY,MAAM,IAAI;AACtB,eAAW,SAAS,SAAS;AACzB,UAAI,MAAM,SAAS,aAAa;AAC5B,cAAM,GAAG,OAAO,IAAI,GAAG,MAAM,IAAI,IAAI,OAAO,KAAK,EAAE;AAAA,MACvD,OAAO;AACH,cAAM,MAAM,IAAI;AAAA,MACpB;AAAA,IACJ;AAAA,EACJ,CAAC;AAED,OAAK,QAAQ,MAAM,EACd,YAAY,mBAAmB,EAC/B,OAAO,iCAAiC,cAAc,EACtD,OAAO,sBAAsB,yCAAyC,EACtE,OAAO,cAAc,8BAA8B,EACnD,OAAO,iCAAiC,eAAe,EACvD,OAAO,8BAA8B,8BAA8B,EACnE,OAAO,qBAAqB,WAAW,EACvC,OAAO,mBAAmB,gEAAgE,EAC1F,OAAO,OAAO,YAAqE;AAChF,UAAM,OAAO,UAAU,MAAM,gBAAgB,OAAO,CAAC;AAErD,iBAAa,iBAAiB;AAE9B,QAAI;AACJ,QAAI;AAEJ,QAAI,KAAK,SAAS,UAAU;AACxB,oBAAc,KAAK;AACnB,iBAAW,MAAM;AAAA,QACb,0BAA0B,mBAAmB,KAAK,GAAG,CAAC;AAAA,MAC1D;AAAA,IACJ,OAAO;AACH,oBAAc,KAAK;AACnB,YAAM,cAAc,UAAU,MAAM,qBAAqB,OAAuB,CAAC;AACjF,YAAM,KAAK,qBAAqB,KAAK,MAAM,WAAW;AACtD,iBAAW,MAAM;AAAA,QACb,eAAe,KAAK,SAAS,cAAc,EAAE;AAAA,MACjD;AAAA,IACJ;AAEA,QAAI,CAAC,SAAS,IAAI;AACd,kBAAY,OAAO,QAAQ;AAC3B,UAAI,SAAS,WAAW,KAAK;AACzB,cAAM,GAAG,OAAO,GAAG,UAAK,WAAW,kBAAkB,OAAO,KAAK,EAAE;AAAA,MACvE,OAAO;AACH,mBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,MAC7E;AACA,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,SAAS;AAEnC,QAAI,SAAS,aAAa;AACtB,kBAAY,OAAO,QAAQ;AAC3B,YAAM,GAAG,OAAO,GAAG,UAAK,WAAW,kBAAkB,OAAO,KAAK,EAAE;AACnE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,gBAAY,MAAM,MAAM;AACxB,UAAM,WAAW,EAAE;AAAA,EACvB,CAAC;AAEL,OAAK,QAAQ,KAAK,EACb,YAAY,eAAe,EAC3B,OAAO,iCAAiC,cAAc,EACtD,OAAO,sBAAsB,yCAAyC,EACtE,OAAO,cAAc,8BAA8B,EACnD,OAAO,iCAAiC,eAAe,EACvD,OAAO,8BAA8B,8BAA8B,EACnE,OAAO,qBAAqB,kBAAkB,EAC9C,OAAO,mBAAmB,gEAAgE,EAC1F,eAAe,gCAAgC,iBAAiB,EAChE,OAAO,mBAAmB,qCAAqC,EAC/D;AAAA,IACG,OAAO,YAKD;AACF,YAAM,OAAO,UAAU,MAAM,iBAAiB,OAAO,CAAC;AAGtD,UAAI,CAAI,cAAW,QAAQ,SAAS,GAAG;AACnC,cAAM,GAAG,OAAO,GAAG,gCAA2B,QAAQ,SAAS,GAAG,OAAO,KAAK,EAAE;AAChF,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAGA,YAAM,QAAW,YAAS,QAAQ,SAAS;AAC3C,UAAI,CAAC,MAAM,OAAO,GAAG;AACjB,cAAM,GAAG,OAAO,GAAG,sBAAiB,QAAQ,SAAS,GAAG,OAAO,KAAK,EAAE;AACtE,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAGA,YAAM,UAAU,KAAK,OAAO;AAC5B,UAAI,MAAM,OAAO,SAAS;AACtB,cAAM,GAAG,OAAO,GAAG,qCAAgC,QAAQ,SAAS,GAAG,OAAO,KAAK,EAAE;AACrF,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAGA,YAAM,SAAY,gBAAa,QAAQ,SAAS;AAChD,UAAI,gBAAgB,MAAM,GAAG;AACzB,cAAM,GAAG,OAAO,GAAG,wEAAmE,OAAO,KAAK,EAAE;AACpG,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAEA,YAAM,UAAU,OAAO,SAAS,MAAM;AAEtC,mBAAa,cAAc;AAE3B,UAAI;AACJ,UAAI;AAEJ,UAAI,KAAK,SAAS,UAAU;AACxB,sBAAc,KAAK;AACnB,mBAAW,MAAM,QAA2B,uBAAuB;AAAA,UAC/D,KAAK,KAAK;AAAA,UACV;AAAA,QACJ,CAAC;AAAA,MACL,OAAO;AACH,sBAAc,KAAK;AACnB,cAAM,cAAc,UAAU,MAAM,qBAAqB,OAAuB,CAAC;AACjF,mBAAW,MAAM;AAAA,UACb,eAAe,KAAK,SAAS;AAAA,UAC7B;AAAA,YACI,MAAM,KAAK;AAAA,YACX;AAAA,YACA,WAAW,QAAQ,aAAa;AAAA,YAChC,GAAG;AAAA,UACP;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,CAAC,SAAS,IAAI;AACd,oBAAY,OAAO,QAAQ;AAC3B,YAAI,SAAS,WAAW,KAAK;AACzB,cAAI,KAAK,SAAS,UAAU;AACxB,kBAAM,GAAG,OAAO,GAAG,UAAK,WAAW,kBAAkB,OAAO,KAAK,EAAE;AAAA,UACvE,OAAO;AACH,kBAAM,GAAG,OAAO,GAAG,yCAAoC,OAAO,KAAK,EAAE;AAAA,UACzE;AAAA,QACJ,WAAW,SAAS,WAAW,KAAK;AAChC,qBAAW,UAAU,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,QACxD,OAAO;AACH,qBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,QAC7E;AACA,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAEA,YAAM,SAAS,SAAS,KAAK,UAAU,YAAY;AACnD,kBAAY,MAAM,GAAG,MAAM,KAAK,SAAS,KAAK,IAAI,EAAE;AAAA,IACxD;AAAA,EACJ;AAEJ;AAAA,IACI,KAAK,QAAQ,OAAO,EACf,YAAY,oBAAoB,EAChC,eAAe,qBAAqB,gBAAgB,EACpD,OAAO,mBAAmB,qCAAqC;AAAA,EACxE,EAAE;AAAA,IACE,OAAO,YAGD;AACF,YAAM,cAAc,UAAU,MAAM,qBAAqB,OAAO,CAAC;AAEjE,mBAAa,uBAAuB;AACpC,YAAM,WAAW,MAAM;AAAA,QACnB,eAAe,QAAQ,SAAS;AAAA,QAChC;AAAA,UACI,MAAM,QAAQ;AAAA,UACd,WAAW,QAAQ,aAAa;AAAA,UAChC,GAAG;AAAA,QACP;AAAA,MACJ;AAEA,UAAI,CAAC,SAAS,IAAI;AACd,oBAAY,OAAO,QAAQ;AAC3B,YAAI,SAAS,WAAW,KAAK;AACzB,gBAAM,GAAG,OAAO,GAAG,yCAAoC,OAAO,KAAK,EAAE;AAAA,QACzE,WAAW,SAAS,WAAW,KAAK;AAChC,qBAAW,UAAU,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,QACxD,OAAO;AACH,qBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,QAC7E;AACA,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAEA,YAAM,SAAS,SAAS,KAAK,UAAU,YAAY;AACnD,kBAAY,MAAM,GAAG,MAAM,KAAK,SAAS,KAAK,IAAI,EAAE;AAAA,IACxD;AAAA,EACJ;AAEA;AAAA,IACI,KAAK,QAAQ,KAAK,EACb,YAAY,kCAAkC,EAC9C,eAAe,qBAAqB,wBAAwB;AAAA,EACrE,EAAE;AAAA,IACE,OAAO,YAED;AACF,YAAM,cAAc,UAAU,MAAM,qBAAqB,OAAO,CAAC;AAEjE,mBAAa,aAAa;AAC1B,YAAM,WAAW,MAAM;AAAA,QACnB,eAAe,QAAQ,SAAS;AAAA,QAChC;AAAA,UACI,MAAM,QAAQ;AAAA,UACd,GAAG;AAAA,QACP;AAAA,MACJ;AAEA,UAAI,CAAC,SAAS,IAAI;AACd,oBAAY,OAAO,QAAQ;AAC3B,YAAI,SAAS,WAAW,KAAK;AACzB,gBAAM,GAAG,OAAO,GAAG,0BAAqB,QAAQ,IAAI,GAAG,OAAO,KAAK,EAAE;AAAA,QACzE,WAAW,SAAS,WAAW,KAAK;AAChC,gBAAM,GAAG,OAAO,GAAG,2CAAsC,OAAO,KAAK,EAAE;AAAA,QAC3E,OAAO;AACH,qBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AAAA,QAC7E;AACA,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAEA,kBAAY,MAAM,YAAY,SAAS,KAAK,IAAI,EAAE;AAAA,IACtD;AAAA,EACJ;AACJ;;;AMrWO,SAAS,sBAAsBC,UAAwB;AAC1D,EAAAA,SACK,QAAQ,QAAQ,EAChB,YAAY,+BAA+B,EAC3C,OAAO,YAAY;AAChB,iBAAa,uBAAuB;AACpC,UAAM,WAAW,MAAM,QAAwB,eAAe;AAE9D,QAAI,SAAS,IAAI;AACb,kBAAY,MAAM,MAAM;AACxB,YAAM,GAAG,OAAO,IAAI,WAAW,OAAO,KAAK,KAAK,SAAS,KAAK,QAAQ,EAAE;AACxE,YAAM,GAAG,OAAO,IAAI,QAAQ,OAAO,KAAK,KAAK,SAAS,KAAK,KAAK,EAAE;AAAA,IACtE,OAAO;AACH,kBAAY,OAAO,QAAQ;AAC3B,iBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AACzE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACJ,CAAC;AACT;;;ACKA,IAAM,aAAa;AAEnB,SAAS,aAAa,OAAwB;AAC1C,SAAO,WAAW,KAAK,KAAK;AAChC;AAEO,SAAS,yBAAyBC,UAAwB;AAC7D,QAAM,YAAYA,SAAQ,QAAQ,WAAW,EAAE,YAAY,sBAAsB;AAEjF,YACK,QAAQ,MAAM,EACd,YAAY,mCAAmC,EAC/C,OAAO,YAAY;AAChB,iBAAa,wBAAwB;AACrC,UAAM,WAAW,MAAM,QAA+B,aAAa;AAEnE,QAAI,SAAS,IAAI;AACb,YAAM,EAAE,WAAW,IAAI,SAAS;AAChC,UAAI,WAAW,WAAW,GAAG;AACzB,oBAAY,MAAM,sBAAsB;AACxC;AAAA,MACJ;AAEA,kBAAY,MAAM,SAAS,WAAW,MAAM,eAAe;AAE3D,iBAAW,MAAM,YAAY;AACzB,cAAM,GAAG,OAAO,IAAI,GAAG,GAAG,WAAW,GAAG,OAAO,KAAK,IAAK,GAAG,IAAI,EAAE;AAAA,MACtE;AAAA,IACJ,OAAO;AACH,kBAAY,OAAO,QAAQ;AAC3B,iBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AACzE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACJ,CAAC;AAEL,QAAM,UAAUA,SAAQ,QAAQ,SAAS,EAAE,YAAY,0BAA0B;AAEjF,UACK,QAAQ,MAAM,EACd,YAAY,iCAAiC,EAC7C,eAAe,iCAAiC,cAAc,EAC9D,OAAO,OAAO,YAAmC;AAC9C,UAAM,EAAE,WAAW,YAAY,IAAI;AAEnC,iBAAa,+BAA+B;AAC5C,UAAM,WAAW,MAAM,QAAyB,eAAe,WAAW,UAAU;AAEpF,QAAI,CAAC,SAAS,IAAI;AACd,kBAAY,OAAO,yBAAyB;AAC5C,iBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AACzE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,UAAM,EAAE,SAAAC,SAAQ,IAAI,SAAS;AAC7B,QAAIA,SAAQ,WAAW,GAAG;AACtB,kBAAY,MAAM,mBAAmB;AACrC;AAAA,IACJ;AAEA,gBAAY,MAAM,SAASA,SAAQ,MAAM,YAAY;AAErD,eAAW,UAAUA,UAAS;AAC1B,YAAM,OAAO,OAAO,eAAe;AACnC,YAAM,GAAG,OAAO,IAAI,GAAG,OAAO,KAAK,GAAG,OAAO,KAAK,IAAK,IAAI,IAAK,OAAO,IAAI,EAAE;AAAA,IACjF;AAAA,EACJ,CAAC;AAEL,UACK,QAAQ,QAAQ,EAChB,YAAY,iCAAiC,EAC7C,eAAe,iCAAiC,cAAc,EAC9D,SAAS,YAAY,oCAAoC,EACzD,OAAO,OAAO,WAAmB,YAAmC;AACjE,UAAM,EAAE,WAAW,YAAY,IAAI;AAEnC,UAAM,SAAS,UAAU,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACvE,QAAI,OAAO,WAAW,GAAG;AACrB,iBAAW,0BAA0B;AACrC,cAAQ,KAAK,CAAC;AAAA,IAClB;AAGA,UAAM,gBAAgB,OAAO,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAC3D,QAAI,cAAc,SAAS,GAAG;AAC1B,iBAAW,SAAS,eAAe;AAC/B,mBAAW,yBAAyB,KAAK,EAAE;AAAA,MAC/C;AACA,cAAQ,KAAK,CAAC;AAAA,IAClB;AAGA,iBAAa,+BAA+B;AAC5C,UAAM,kBAAkB,MAAM,QAAyB,eAAe,WAAW,UAAU;AAE3F,QAAI,CAAC,gBAAgB,IAAI;AACrB,kBAAY,OAAO,yBAAyB;AAC5C,iBAAW,UAAU,gBAAgB,MAAM,MAAM,KAAK,UAAU,gBAAgB,IAAI,CAAC,EAAE;AACvF,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,gBAAY,MAAM,iBAAiB;AAEnC,UAAM,EAAE,SAAAA,SAAQ,IAAI,gBAAgB;AACpC,UAAM,gBAAgB,IAAI,IAAIA,SAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC;AAG5E,eAAW,SAAS,QAAQ;AACxB,YAAM,SAAS,cAAc,IAAI,MAAM,YAAY,CAAC;AACpD,UAAI,CAAC,QAAQ;AACT,cAAM,GAAG,OAAO,GAAG,SAAI,OAAO,KAAK,IAAI,KAAK,2BAA2B;AACvE;AAAA,MACJ;AAEA,YAAM,iBAAiB,MAAM,WAAW,eAAe,WAAW,YAAY,OAAO,MAAM,EAAE;AAE7F,UAAI,eAAe,IAAI;AACnB,cAAM,GAAG,OAAO,KAAK,SAAI,OAAO,KAAK,IAAI,KAAK,YAAY;AAAA,MAC9D,OAAO;AACH,cAAM,GAAG,OAAO,GAAG,SAAI,OAAO,KAAK,IAAI,KAAK,cAAc,KAAK,UAAU,eAAe,IAAI,CAAC,EAAE;AAAA,MACnG;AAAA,IACJ;AAAA,EACJ,CAAC;AAEL,QAAM,QAAQD,SAAQ,QAAQ,OAAO,EAAE,YAAY,eAAe;AAElE,QACK,QAAQ,MAAM,EACd,YAAY,uCAAuC,EACnD,eAAe,iCAAiC,cAAc,EAC9D,OAAO,OAAO,YAAmC;AAC9C,UAAM,EAAE,WAAW,YAAY,IAAI;AAEnC,iBAAa,oBAAoB;AACjC,UAAM,WAAW,MAAM,QAAiC,eAAe,WAAW,SAAS;AAE3F,QAAI,CAAC,SAAS,IAAI;AACd,kBAAY,OAAO,wBAAwB;AAC3C,iBAAW,UAAU,SAAS,MAAM,MAAM,KAAK,UAAU,SAAS,IAAI,CAAC,EAAE;AACzE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,UAAM,EAAE,OAAO,IAAI,SAAS;AAC5B,QAAI,OAAO,WAAW,GAAG;AACrB,kBAAY,MAAM,kBAAkB;AACpC;AAAA,IACJ;AAEA,gBAAY,MAAM,SAAS,OAAO,MAAM,WAAW;AAEnD;AAAA,MACI,GAAG,OAAO,IAAI,OAAO,OAAO,KAAK,IAAK,OAAO,IAAI,gBAAgB,OAAO,KAAK,IAAK,OAAO,IAAI,cAAc,OAAO,KAAK,IAAK,OAAO,IAAI,OAAO,OAAO,KAAK;AAAA,IAC9J;AACA,eAAW,KAAK,QAAQ;AACpB,YAAM,cAAc,EAAE,eAAe;AACrC,YAAM,aAAa,EAAE,WAAW,OAAO,OAAO,EAAE,OAAO,IAAI;AAC3D,YAAM,GAAG,EAAE,IAAI,IAAK,WAAW,IAAK,UAAU,IAAK,EAAE,IAAI,EAAE;AAAA,IAC/D;AAAA,EACJ,CAAC;AAET;;;ARxLA,eAAe;AAAA,EACX,KAAK,EAAE,MAAM,gBAAgB,SAAS,QAAgB;AAC1D,CAAC,EAAE,OAAO;AAEV,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACK,KAAK,MAAM,EACX,YAAY,yBAAyB,EACrC,QAAQ,OAAe,EACvB,OAAO,MAAM;AACV,UAAQ,KAAK;AACjB,CAAC;AAEL,sBAAsB,OAAO;AAC7B,yBAAyB,OAAO;AAChC,oBAAoB,OAAO;AAE3B,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,QAAiB;AACrD,UAAQ,MAAM,cAAc,GAAG;AAC/B,UAAQ,KAAK,CAAC;AAClB,CAAC;","names":["program","program","program","members"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moxt-ai/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Moxt - The Agent-Native Workspace",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"build": "tsup",
|
|
15
15
|
"dev": "tsup --watch",
|
|
16
16
|
"test": "vitest run",
|
|
17
|
+
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
18
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
|
17
19
|
"prepublishOnly": "pnpm build",
|
|
18
20
|
"release": "pnpm build && npm publish --access public"
|
|
19
21
|
},
|