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.
@@ -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
- output(data, globals.json);
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
- output(data, globals.json);
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
- output(data, globals.json);
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
- .requiredOption("--study <id>", "Study ID")
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
- .requiredOption("--study <id>", "Study ID")
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: JSON.parse(opts.detailsJson) }),
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
- output(data, globals.json);
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
- output(data, globals.json);
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
- body.details = JSON.parse(opts.detailsJson);
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
- const data = await client.put(`/iterations/${id}`, body);
69
- output(data, globals.json);
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;