@test-lab-ai/cli 0.2.16 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/testlab.mjs +33 -1
  2. package/package.json +1 -1
package/bin/testlab.mjs CHANGED
@@ -40,6 +40,9 @@ Usage:
40
40
  (credentials, labels, fixtures, plans)
41
41
  testlab plans list List your test plans
42
42
  testlab plans create -f plan.json Create one plan from JSON
43
+ testlab plans update <id> [-f patch.json] [--prompt P] [--name N]
44
+ Update an existing plan; only the
45
+ fields you pass change
43
46
  testlab projects list List your projects
44
47
  testlab credentials set <key> --value <value> Set a credential ({{credentials.<key>}})
45
48
  testlab credentials list List credential keys (values never shown)
@@ -216,6 +219,34 @@ async function cmdPlansCreate(flags) {
216
219
  log(`✓ Created plan #${r.json.testPlan.id}: ${r.json.testPlan.name}`)
217
220
  }
218
221
 
222
+ async function cmdPlansUpdate(flags, args) {
223
+ const { apiKey, apiUrl } = requireAuth(flags)
224
+ const planId = parsePlanIdArg(args[2] ?? flags.plan)
225
+ if (!Number.isInteger(planId)) {
226
+ errExit("usage: testlab plans update <id> [-f patch.json] [--prompt P] [--name N] (numeric plan id; see `testlab plans list`)")
227
+ }
228
+ // Build a partial patch. A JSON file is the full surface (name, prompt,
229
+ // testType, agentType, devices, paused, projectId); --prompt / --name are
230
+ // quick overrides for the two common edits. Only the fields present are sent,
231
+ // and the server changes only those.
232
+ let patch = {}
233
+ if (flags.file) {
234
+ try {
235
+ patch = JSON.parse(fs.readFileSync(flags.file, "utf8"))
236
+ } catch (e) {
237
+ errExit(`could not read ${flags.file}: ${e.message}`)
238
+ }
239
+ }
240
+ if (flags.prompt !== undefined) patch.prompt = flags.prompt
241
+ if (flags.name !== undefined) patch.name = flags.name
242
+ if (Object.keys(patch).length === 0) {
243
+ errExit("nothing to update: pass -f <patch.json> and/or --prompt / --name. Editable fields: name, prompt, testType, agentType, devices, paused, projectId")
244
+ }
245
+ const r = await apiFetch(apiUrl, apiKey, "PUT", `/api/v1/test-plans/${planId}`, patch)
246
+ if (!r.ok) errExit(`${r.status}: ${r.json?.error || ""}`)
247
+ log(`✓ Updated plan #${r.json.testPlan.id}: ${r.json.testPlan.name}`)
248
+ }
249
+
219
250
  async function cmdCredentialsSet(flags, args) {
220
251
  const { apiKey, apiUrl } = requireAuth(flags)
221
252
  const key = args[2]
@@ -639,7 +670,8 @@ async function main() {
639
670
  case "plans":
640
671
  if (args[1] === "list") return cmdPlansList(flags)
641
672
  if (args[1] === "create") return cmdPlansCreate(flags)
642
- return errExit("usage: testlab plans <list|create>")
673
+ if (args[1] === "update") return cmdPlansUpdate(flags, args)
674
+ return errExit("usage: testlab plans <list|create|update>")
643
675
  case "projects":
644
676
  if (args[1] === "list") return cmdProjectsList(flags)
645
677
  return errExit("usage: testlab projects list")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@test-lab-ai/cli",
3
- "version": "0.2.16",
3
+ "version": "0.2.17",
4
4
  "description": "Import existing test plans into test-lab.ai from the command line (or an AI agent).",
5
5
  "type": "module",
6
6
  "bin": {