From 56365b21eff007948c9185f7678c69d4cfe892ba Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Thu, 21 Aug 2025 12:59:51 +0200 Subject: [PATCH 1/6] support batch genaration --- README.md | 21 ++++++++++++++++- package.json | 4 ++-- src/cli.ts | 18 +++++++++++---- src/tools/discoveries.ts | 50 ++++++++++++++++++++++++++++++++++++++++ src/url.ts | 5 +++- 5 files changed, 89 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9619df2..b6af791 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ This way even entityIds like environmentIds or testCaseIds will be autocompleted # octomind -Octomind cli tool. Version: 1.3.1. Additional documentation see https://octomind.dev/docs/api-reference/ +Octomind cli tool. Version: 1.3.2. Additional documentation see https://octomind.dev/docs/api-reference/ **Usage:** `octomind [options] [command]` @@ -239,6 +239,25 @@ Create a new test case discovery | `--assigned-tag-ids [ids]` | Comma-separated list of tag IDs | No | | | `--folder-id [id]` | Folder ID | No | | +## Execution + +## batch-generation + +Batch generation + +**Usage:** `batch-generation [options]` + +### Options + +| Option | Description | Required | Default | +|:-------|:----------|:---------|:--------| +| `-j, --json` | Output raw JSON response | No | | +| `-p, --prompt ` | Batch generation prompt | Yes | | +| `-u, --url ` | Start url for generation | Yes | | +| `-e, --environment-id ` | Environment ID | Yes | | +| `-d, --prerequisite-id ` | Prerequisite ID | Yes | | +| `-t, --test-target-id [id]` | Test target ID, if not provided will use the test target id from the config | No | | + ## Notifications ## notifications diff --git a/package.json b/package.json index 374dd2a..fdd812e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@octomind/octomind", - "version": "1.3.1", + "version": "1.3.2", "description": "a command line client for octomind apis", "main": "./dist/index.js", "packageManager": "pnpm@10.13.1", @@ -15,7 +15,7 @@ "gendoc": "tsx scripts/generate-docs.ts > README.md", "lint": "pnpm apigen && npx genversion -des src/version.ts && biome check", "tsc": "tsc --project tsconfig.build.json", - "apigen": "openapi-typescript https://app.octomind.dev/openapi.yaml --output src/api.ts", + "apigen": "openapi-typescript ./openapi.yaml --output src/api.ts", "build": "pnpm apigen && npx genversion -des src/version.ts && pnpm gendoc && tsc --project tsconfig.build.json", "octomind": "pnpm apigen && tsx src/index.ts", "test": "pnpm apigen && npx genversion -des src/version.ts && jest", diff --git a/src/cli.ts b/src/cli.ts index 40900dd..7571f57 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -16,6 +16,7 @@ import { runDebugtopus } from "./debugtopus"; import { promptUser, resolveTestTargetId } from "./helpers"; import { startPrivateLocationWorker, stopPLW } from "./plw"; import { + batchGeneration, CreateDiscoveryBody, createDiscovery, createEnvironment, @@ -257,7 +258,6 @@ export const buildCmd = (): CompletableCommand => { .action(addTestTargetWrapper(deleteEnvironment)); program - .completer(optionsCompleter) .completableCommand("start-private-location") .description( @@ -276,14 +276,12 @@ export const buildCmd = (): CompletableCommand => { .action(startPrivateLocationWorker); program - .completableCommand("stop-private-location") .completer(optionsCompleter) .description( "Stop a private location worker, see https://octomind.dev/docs/proxy/private-location", ) .helpGroup("private-locations") - .action(stopPLW); createCommandWithCommonOptions(program, "notifications") @@ -291,7 +289,6 @@ export const buildCmd = (): CompletableCommand => { .description("Get notifications for a test target") .helpGroup("notifications") .addOption(testTargetIdOption) - .action(addTestTargetWrapper(listNotifications)); createCommandWithCommonOptions(program, "delete-test-case") @@ -328,7 +325,6 @@ export const buildCmd = (): CompletableCommand => { splitter, ) .option("--folder-id [id]", "Folder ID") - .action(addTestTargetWrapper(createDiscovery)); createCommandWithCommonOptions(program, "list-test-cases") @@ -343,6 +339,18 @@ export const buildCmd = (): CompletableCommand => { .helpGroup("test-targets") .action(listTestTargets); + createCommandWithCommonOptions(program, "batch-generation") + .completer(testTargetIdCompleter) + .completer(optionsCompleter) + .description("Batch generation") + .requiredOption("-p, --prompt ", "Batch generation prompt") + .requiredOption("-u, --url ", "Start url for generation") + .option("-e, --environment-id ", "Environment ID") + .option("-d, --prerequisite-id ", "Prerequisite ID") + .helpGroup("execution") + .addOption(testTargetIdOption) + .action(addTestTargetWrapper(batchGeneration)); + program .completableCommand("install-completion") .description("Install tab completion") diff --git a/src/tools/discoveries.ts b/src/tools/discoveries.ts index 585e10b..9d88e7b 100644 --- a/src/tools/discoveries.ts +++ b/src/tools/discoveries.ts @@ -5,6 +5,56 @@ import { client, handleError, ListOptions, logJson } from "./client"; export type CreateDiscoveryBody = components["schemas"]["ExternalDiscoveryBody"]; export type DiscoveryResponse = components["schemas"]["DiscoveryResponse"]; +export type BatchGenerationResponse = + components["schemas"]["BatchGenerationResponse"]; +export type BatchGenerationParams = + components["schemas"]["ExternalBatchGenerationBody"]; +export const batchGeneration = async ( + options: { + environmentId: string; + prompt: string; + prerequisiteId?: string; + testTargetId: string; + url: string; + } & ListOptions, +): Promise => { + const { data, error } = await client.POST( + "/apiKey/v2/test-targets/{testTargetId}/batch-generations", + { + params: { + path: { + testTargetId: options.testTargetId, + }, + }, + body: { + environmentId: options.environmentId, + prompt: options.prompt, + prerequisiteId: options.prerequisiteId, + entryPointUrlPath: options.url, + }, + }, + ); + + handleError(error); + + const response = data as BatchGenerationResponse; + if (options.json) { + logJson(response); + return; + } + if (!response.batchGenerationId) { + throw new Error("Batch generation ID is missing"); + } + + console.log("Batch generation created successfully!"); + console.log(`Batch generation ID: ${response.batchGenerationId}`); + console.log( + `Batch generation URL: ${await getUrl({ + batchGenerationId: response.batchGenerationId, + entityType: "batch-generation", + })}`, + ); +}; export const createDiscovery = async ( options: CreateDiscoveryBody & { testTargetId: string } & ListOptions, diff --git a/src/url.ts b/src/url.ts index de82822..cf04b88 100644 --- a/src/url.ts +++ b/src/url.ts @@ -11,7 +11,8 @@ export const getUrl = async ( testResultId: string; entityType: "test-result"; } - | { testCaseId: string; entityType: "discovery" }, + | { testCaseId: string; entityType: "discovery" } + | { batchGenerationId: string; entityType: "batch-generation" }, ): Promise => { const relevantBaseUrl = new URL(BASE_URL).origin; const config = await loadConfig(); @@ -30,5 +31,7 @@ export const getUrl = async ( return `${relevantBaseUrl}/testtargets/${configuredTestTargetId}/testreports/${input.testReportId}/testresults/${input.testResultId}`; case "discovery": return `${relevantBaseUrl}/testtargets/${configuredTestTargetId}/testcases/${input.testCaseId}`; + case "batch-generation": + return `${relevantBaseUrl}/testtargets/${configuredTestTargetId}/batch-generations/${input.batchGenerationId}`; } }; From 5c66765222f3550598cb6872849aeace590a6a4f Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Thu, 21 Aug 2025 13:03:57 +0200 Subject: [PATCH 2/6] type / readme --- README.md | 4 +--- src/cli.ts | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b6af791..7efc30c 100644 --- a/README.md +++ b/README.md @@ -239,11 +239,9 @@ Create a new test case discovery | `--assigned-tag-ids [ids]` | Comma-separated list of tag IDs | No | | | `--folder-id [id]` | Folder ID | No | | -## Execution - ## batch-generation -Batch generation +Batch generation of test cases **Usage:** `batch-generation [options]` diff --git a/src/cli.ts b/src/cli.ts index 7571f57..3ca9f63 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -342,12 +342,12 @@ export const buildCmd = (): CompletableCommand => { createCommandWithCommonOptions(program, "batch-generation") .completer(testTargetIdCompleter) .completer(optionsCompleter) - .description("Batch generation") + .description("Batch generation of test cases") .requiredOption("-p, --prompt ", "Batch generation prompt") .requiredOption("-u, --url ", "Start url for generation") .option("-e, --environment-id ", "Environment ID") .option("-d, --prerequisite-id ", "Prerequisite ID") - .helpGroup("execution") + .helpGroup("execute") .addOption(testTargetIdOption) .action(addTestTargetWrapper(batchGeneration)); From 58a59b23076c78894bb77015deffdf2ef902b70e Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Thu, 21 Aug 2025 14:03:30 +0200 Subject: [PATCH 3/6] better error message --- src/tools/client.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/client.ts b/src/tools/client.ts index 166eee7..32a2360 100644 --- a/src/tools/client.ts +++ b/src/tools/client.ts @@ -50,6 +50,9 @@ export { client }; export const handleError = (error: ErrorResponse) => { if (error) { console.error(error); + if (typeof error === "string" && error.startsWith("403")) { + console.error("You are not authorized. Check your API key or do a 'octomind init' to set it up."); + } process.exit(1); } }; From 1efb7ffbc143a2872f40222e1591bb8872c6e625 Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Thu, 21 Aug 2025 14:57:05 +0200 Subject: [PATCH 4/6] use preview def --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdd812e..5ffed68 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "gendoc": "tsx scripts/generate-docs.ts > README.md", "lint": "pnpm apigen && npx genversion -des src/version.ts && biome check", "tsc": "tsc --project tsconfig.build.json", - "apigen": "openapi-typescript ./openapi.yaml --output src/api.ts", + "apigen": "openapi-typescript https://preview.octomind.dev/openapi.yaml --output src/api.ts", "build": "pnpm apigen && npx genversion -des src/version.ts && pnpm gendoc && tsc --project tsconfig.build.json", "octomind": "pnpm apigen && tsx src/index.ts", "test": "pnpm apigen && npx genversion -des src/version.ts && jest", From ba93e11859c38edd4c510f454d287abd574d379f Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Thu, 21 Aug 2025 14:58:07 +0200 Subject: [PATCH 5/6] lint --- src/tools/client.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/client.ts b/src/tools/client.ts index 32a2360..18cbc09 100644 --- a/src/tools/client.ts +++ b/src/tools/client.ts @@ -51,7 +51,9 @@ export const handleError = (error: ErrorResponse) => { if (error) { console.error(error); if (typeof error === "string" && error.startsWith("403")) { - console.error("You are not authorized. Check your API key or do a 'octomind init' to set it up."); + console.error( + "You are not authorized. Check your API key or do a 'octomind init' to set it up.", + ); } process.exit(1); } From 026a9f91f7f86472099e4ccec56edca49f6a287a Mon Sep 17 00:00:00 2001 From: Stefan Rinke Date: Tue, 26 Aug 2025 11:36:36 +0200 Subject: [PATCH 6/6] use released api --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ffed68..833e41c 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "gendoc": "tsx scripts/generate-docs.ts > README.md", "lint": "pnpm apigen && npx genversion -des src/version.ts && biome check", "tsc": "tsc --project tsconfig.build.json", - "apigen": "openapi-typescript https://preview.octomind.dev/openapi.yaml --output src/api.ts", + "apigen": "openapi-typescript https://app.octomind.dev/openapi.yaml --output src/api.ts", "build": "pnpm apigen && npx genversion -des src/version.ts && pnpm gendoc && tsc --project tsconfig.build.json", "octomind": "pnpm apigen && tsx src/index.ts", "test": "pnpm apigen && npx genversion -des src/version.ts && jest",