speqs 0.5.0 → 0.6.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.
- package/dist/commands/config.js +16 -6
- package/dist/commands/iteration.js +67 -15
- package/dist/commands/simulation.d.ts +1 -1
- package/dist/commands/simulation.js +404 -128
- package/dist/commands/study.js +180 -28
- package/dist/commands/tester-profile.js +20 -6
- package/dist/commands/tester.js +17 -7
- package/dist/commands/workspace.js +56 -9
- package/dist/config.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/lib/alias-store.d.ts +49 -0
- package/dist/lib/alias-store.js +138 -0
- package/dist/lib/api-client.d.ts +1 -0
- package/dist/lib/api-client.js +67 -27
- package/dist/lib/auth.js +4 -1
- package/dist/lib/command-helpers.d.ts +4 -0
- package/dist/lib/command-helpers.js +41 -4
- package/dist/lib/output.d.ts +16 -1
- package/dist/lib/output.js +273 -56
- package/dist/lib/types.d.ts +7 -30
- package/dist/lib/types.js +9 -1
- package/dist/lib/upload.d.ts +47 -0
- package/dist/lib/upload.js +178 -0
- package/package.json +1 -1
package/dist/commands/config.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* speqs config — Manage simulation configs.
|
|
3
3
|
*/
|
|
4
4
|
import { withClient, readJsonFileOrStdin } from "../lib/command-helpers.js";
|
|
5
|
+
import { resolveId, tagAlias, ALIAS_PREFIX } from "../lib/alias-store.js";
|
|
5
6
|
import { output, formatConfigList } from "../lib/output.js";
|
|
6
7
|
export function registerConfigCommands(program) {
|
|
7
8
|
const config = program
|
|
@@ -25,7 +26,10 @@ export function registerConfigCommands(program) {
|
|
|
25
26
|
await withClient(cmd, async (client, globals) => {
|
|
26
27
|
const body = await readJsonFileOrStdin(opts.file);
|
|
27
28
|
const data = await client.post("/dev/simulation-configs", body);
|
|
28
|
-
|
|
29
|
+
const result = data;
|
|
30
|
+
if (result.id)
|
|
31
|
+
result.alias = tagAlias(ALIAS_PREFIX.config, String(result.id));
|
|
32
|
+
output(result, globals.json);
|
|
29
33
|
});
|
|
30
34
|
});
|
|
31
35
|
config
|
|
@@ -34,8 +38,11 @@ export function registerConfigCommands(program) {
|
|
|
34
38
|
.argument("<id>", "Config ID")
|
|
35
39
|
.action(async (id, _opts, cmd) => {
|
|
36
40
|
await withClient(cmd, async (client, globals) => {
|
|
37
|
-
const data = await client.get(`/dev/simulation-configs/${id}`);
|
|
38
|
-
|
|
41
|
+
const data = await client.get(`/dev/simulation-configs/${resolveId(id)}`);
|
|
42
|
+
const result = data;
|
|
43
|
+
if (result.id)
|
|
44
|
+
result.alias = tagAlias(ALIAS_PREFIX.config, String(result.id));
|
|
45
|
+
output(result, globals.json);
|
|
39
46
|
});
|
|
40
47
|
});
|
|
41
48
|
config
|
|
@@ -55,8 +62,11 @@ export function registerConfigCommands(program) {
|
|
|
55
62
|
.action(async (id, opts, cmd) => {
|
|
56
63
|
await withClient(cmd, async (client, globals) => {
|
|
57
64
|
const body = await readJsonFileOrStdin(opts.file);
|
|
58
|
-
const data = await client.put(`/dev/simulation-configs/${id}`, body);
|
|
59
|
-
|
|
65
|
+
const data = await client.put(`/dev/simulation-configs/${resolveId(id)}`, body);
|
|
66
|
+
const result = data;
|
|
67
|
+
if (result.id)
|
|
68
|
+
result.alias = tagAlias(ALIAS_PREFIX.config, String(result.id));
|
|
69
|
+
output(result, globals.json);
|
|
60
70
|
});
|
|
61
71
|
});
|
|
62
72
|
config
|
|
@@ -65,7 +75,7 @@ export function registerConfigCommands(program) {
|
|
|
65
75
|
.argument("<id>", "Config ID")
|
|
66
76
|
.action(async (id, _opts, cmd) => {
|
|
67
77
|
await withClient(cmd, async (client, globals) => {
|
|
68
|
-
await client.del(`/dev/simulation-configs/${id}`);
|
|
78
|
+
await client.del(`/dev/simulation-configs/${resolveId(id)}`);
|
|
69
79
|
output({ message: "Config deleted" }, globals.json);
|
|
70
80
|
});
|
|
71
81
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* speqs iteration — Manage iterations (usually created via `simulation run`).
|
|
3
3
|
*/
|
|
4
|
-
import { withClient } from "../lib/command-helpers.js";
|
|
4
|
+
import { withClient, resolveStudy } from "../lib/command-helpers.js";
|
|
5
|
+
import { resolveId, tagAlias, ALIAS_PREFIX } from "../lib/alias-store.js";
|
|
5
6
|
import { output, formatIterationList } from "../lib/output.js";
|
|
6
7
|
export function registerIterationCommands(program) {
|
|
7
8
|
const iteration = program
|
|
@@ -10,40 +11,76 @@ export function registerIterationCommands(program) {
|
|
|
10
11
|
iteration
|
|
11
12
|
.command("list")
|
|
12
13
|
.description("List iterations for a study")
|
|
13
|
-
.
|
|
14
|
+
.option("--study <id>", "Study ID")
|
|
14
15
|
.addHelpText("after", "\nExamples:\n $ speqs iteration list --study <id>\n $ speqs iteration list --study <id> --json")
|
|
15
16
|
.action(async (opts, cmd) => {
|
|
16
17
|
await withClient(cmd, async (client, globals) => {
|
|
17
|
-
const data = await client.get(`/studies/${opts.study}/iterations`);
|
|
18
|
+
const data = await client.get(`/studies/${resolveStudy(opts.study)}/iterations`);
|
|
18
19
|
formatIterationList(data, globals.json);
|
|
19
20
|
});
|
|
20
21
|
});
|
|
21
22
|
iteration
|
|
22
23
|
.command("create")
|
|
23
24
|
.description("Create a new iteration (low-level)")
|
|
24
|
-
.
|
|
25
|
+
.option("--study <id>", "Study ID")
|
|
25
26
|
.requiredOption("--name <name>", "Iteration name")
|
|
26
27
|
.option("--description <description>", "Iteration description")
|
|
27
28
|
.option("--details-json <json>", "Iteration details as JSON string")
|
|
29
|
+
.addHelpText("after", `
|
|
30
|
+
Examples:
|
|
31
|
+
# Interactive:
|
|
32
|
+
$ speqs iteration create --study S --name "v1" \\
|
|
33
|
+
--details-json '{"type":"interactive","platform":"browser","url":"https://example.com","screen_format":"desktop"}'
|
|
34
|
+
|
|
35
|
+
# Text/email:
|
|
36
|
+
$ speqs iteration create --study S --name "v1" \\
|
|
37
|
+
--details-json '{"type":"text","content_text":"Your email content here","title":"Newsletter"}'
|
|
38
|
+
|
|
39
|
+
# Video:
|
|
40
|
+
$ speqs iteration create --study S --name "v1" \\
|
|
41
|
+
--details-json '{"type":"video","content_url":"https://cdn.example.com/video.mp4","mime_type":"video/mp4"}'
|
|
42
|
+
|
|
43
|
+
# Image:
|
|
44
|
+
$ speqs iteration create --study S --name "v1" \\
|
|
45
|
+
--details-json '{"type":"image","image_urls":["https://cdn.example.com/a.png","https://cdn.example.com/b.png"]}'
|
|
46
|
+
|
|
47
|
+
# Document (PDF):
|
|
48
|
+
$ speqs iteration create --study S --name "v1" \\
|
|
49
|
+
--details-json '{"type":"document","content_url":"https://cdn.example.com/report.pdf","mime_type":"application/pdf"}'
|
|
50
|
+
|
|
51
|
+
Note: For local file uploads, use \`speqs simulation run\` which automatically
|
|
52
|
+
uploads files and resolves URLs (e.g. --content-url ./video.mp4).`)
|
|
28
53
|
.action(async (opts, cmd) => {
|
|
29
54
|
await withClient(cmd, async (client, globals) => {
|
|
30
55
|
const body = {
|
|
31
56
|
name: opts.name,
|
|
32
|
-
...(opts.description && { description: opts.description }),
|
|
33
|
-
...(opts.detailsJson && { details:
|
|
57
|
+
...(opts.description !== undefined && { description: opts.description }),
|
|
58
|
+
...(opts.detailsJson && { details: (() => { try {
|
|
59
|
+
return JSON.parse(opts.detailsJson);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
throw new Error("Invalid --details-json: expected valid JSON string");
|
|
63
|
+
} })() }),
|
|
34
64
|
};
|
|
35
|
-
const data = await client.post(`/studies/${opts.study}/iterations`, body);
|
|
36
|
-
|
|
65
|
+
const data = await client.post(`/studies/${resolveStudy(opts.study)}/iterations`, body);
|
|
66
|
+
const result = data;
|
|
67
|
+
if (result.id)
|
|
68
|
+
result.alias = tagAlias(ALIAS_PREFIX.iteration, String(result.id));
|
|
69
|
+
output(result, globals.json);
|
|
37
70
|
});
|
|
38
71
|
});
|
|
39
72
|
iteration
|
|
40
73
|
.command("get")
|
|
41
74
|
.description("Get iteration details")
|
|
42
75
|
.argument("<id>", "Iteration ID")
|
|
76
|
+
.addHelpText("after", "\nExamples:\n $ speqs iteration get <id>\n $ speqs iteration get <id> --json")
|
|
43
77
|
.action(async (id, _opts, cmd) => {
|
|
44
78
|
await withClient(cmd, async (client, globals) => {
|
|
45
|
-
const data = await client.get(`/iterations/${id}`);
|
|
46
|
-
|
|
79
|
+
const data = await client.get(`/iterations/${resolveId(id)}`);
|
|
80
|
+
const result = data;
|
|
81
|
+
if (result.id)
|
|
82
|
+
result.alias = tagAlias(ALIAS_PREFIX.iteration, String(result.id));
|
|
83
|
+
output(result, globals.json);
|
|
47
84
|
});
|
|
48
85
|
});
|
|
49
86
|
iteration
|
|
@@ -54,6 +91,7 @@ export function registerIterationCommands(program) {
|
|
|
54
91
|
.option("--description <description>", "Iteration description")
|
|
55
92
|
.option("--details-json <json>", "Iteration details as JSON string")
|
|
56
93
|
.option("--label <label>", "Iteration label (uppercase letters)")
|
|
94
|
+
.addHelpText("after", "\nExamples:\n $ speqs iteration update <id> --name \"v2\"\n $ speqs iteration update <id> --label B --json")
|
|
57
95
|
.action(async (id, opts, cmd) => {
|
|
58
96
|
await withClient(cmd, async (client, globals) => {
|
|
59
97
|
const body = {};
|
|
@@ -61,21 +99,35 @@ export function registerIterationCommands(program) {
|
|
|
61
99
|
body.name = opts.name;
|
|
62
100
|
if (opts.description !== undefined)
|
|
63
101
|
body.description = opts.description;
|
|
64
|
-
if (opts.detailsJson !== undefined)
|
|
65
|
-
|
|
102
|
+
if (opts.detailsJson !== undefined) {
|
|
103
|
+
try {
|
|
104
|
+
body.details = JSON.parse(opts.detailsJson);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new Error("Invalid --details-json: expected valid JSON string");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
66
110
|
if (opts.label !== undefined)
|
|
67
111
|
body.label = opts.label;
|
|
68
|
-
|
|
69
|
-
|
|
112
|
+
if (Object.keys(body).length === 0) {
|
|
113
|
+
console.error("No update flags provided. Run `speqs iteration update --help` for options.");
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const data = await client.put(`/iterations/${resolveId(id)}`, body);
|
|
117
|
+
const result = data;
|
|
118
|
+
if (result.id)
|
|
119
|
+
result.alias = tagAlias(ALIAS_PREFIX.iteration, String(result.id));
|
|
120
|
+
output(result, globals.json);
|
|
70
121
|
});
|
|
71
122
|
});
|
|
72
123
|
iteration
|
|
73
124
|
.command("delete")
|
|
74
125
|
.description("Delete an iteration")
|
|
75
126
|
.argument("<id>", "Iteration ID")
|
|
127
|
+
.addHelpText("after", "\nExamples:\n $ speqs iteration delete <id>")
|
|
76
128
|
.action(async (id, _opts, cmd) => {
|
|
77
129
|
await withClient(cmd, async (client, globals) => {
|
|
78
|
-
await client.del(`/iterations/${id}`);
|
|
130
|
+
await client.del(`/iterations/${resolveId(id)}`);
|
|
79
131
|
output({ message: "Iteration deleted" }, globals.json);
|
|
80
132
|
});
|
|
81
133
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Primary command: `speqs simulation run` — orchestrates the full flow:
|
|
5
5
|
* 1. Creates iteration (if not provided)
|
|
6
6
|
* 2. Creates testers from profiles
|
|
7
|
-
* 3. Starts simulations
|
|
7
|
+
* 3. Starts simulations (interactive or media, based on study modality)
|
|
8
8
|
*/
|
|
9
9
|
import type { Command } from "commander";
|
|
10
10
|
export declare function registerSimulationCommands(program: Command): void;
|