From 99bc0c001e4db60f342d86f73dbd5c6552a8ec37 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:00:47 +0000 Subject: [PATCH 1/3] Initial plan From 21467ae296b68d720eccba02a5821aa9e8829b36 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:19:01 +0000 Subject: [PATCH 2/3] Fix CI workflows, log function signature, and add guards Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- cli/.github/workflows/auto-dev-release.yml | 2 +- cli/.github/workflows/npm-test.yaml | 4 +-- cli/scripts/bump-sync-version-core.js | 8 ++++++ cli/src/cli/builder/TestEditor.mjs | 3 ++- cli/src/cli/runner.js | 6 ++--- cli/src/utils.js | 30 +++++++++++----------- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/cli/.github/workflows/auto-dev-release.yml b/cli/.github/workflows/auto-dev-release.yml index c7a4c07..f3e33f0 100644 --- a/cli/.github/workflows/auto-dev-release.yml +++ b/cli/.github/workflows/auto-dev-release.yml @@ -90,7 +90,7 @@ jobs: - name: Install dependencies if: steps.check_changes.outputs.skip_release == 'false' - run: npm install + run: npm ci - name: Run tests if: steps.check_changes.outputs.skip_release == 'false' diff --git a/cli/.github/workflows/npm-test.yaml b/cli/.github/workflows/npm-test.yaml index 3afe1e3..bcc9968 100644 --- a/cli/.github/workflows/npm-test.yaml +++ b/cli/.github/workflows/npm-test.yaml @@ -40,7 +40,7 @@ jobs: cache: 'npm' cache-dependency-path: package-lock.json - - run: npm install + - run: npm ci - run: npm test publish-npm: @@ -57,7 +57,7 @@ jobs: cache-dependency-path: package-lock.json registry-url: https://registry.npmjs.org/ - - run: npm install + - run: npm ci - run: npm publish env: NODE_AUTH_TOKEN: ${{secrets.npm_token}} diff --git a/cli/scripts/bump-sync-version-core.js b/cli/scripts/bump-sync-version-core.js index 5fe86e9..92bafac 100755 --- a/cli/scripts/bump-sync-version-core.js +++ b/cli/scripts/bump-sync-version-core.js @@ -1,4 +1,6 @@ #!/usr/bin/env node +// This script is intended for GitHub Actions automation only. +// It performs destructive operations (git checkout, git clean) and should not be run locally. const { execSync } = require("child_process"); const fs = require("fs"); @@ -19,6 +21,12 @@ function execCommand(command, options = {}) { } function main() { + // Prevent accidental local execution + if (!process.env.CI) { + console.error("Error: This script is intended for CI/CD environments only."); + process.exit(1); + } + // Clean git state execCommand("git checkout -- ."); execCommand("git clean -fd"); diff --git a/cli/src/cli/builder/TestEditor.mjs b/cli/src/cli/builder/TestEditor.mjs index dc4ccb2..63e68ae 100644 --- a/cli/src/cli/builder/TestEditor.mjs +++ b/cli/src/cli/builder/TestEditor.mjs @@ -157,7 +157,8 @@ const TestEditor = ({ // Add step view if (view === 'addStep') { // Create new step with step editor (it will prompt for type) - const newStep = createDefaultStep(); + // Default to goTo step as a reasonable starting point + const newStep = createDefaultStep('goTo'); return React.createElement(StepEditor, { step: newStep, diff --git a/cli/src/cli/runner.js b/cli/src/cli/runner.js index ebda73f..4659db9 100644 --- a/cli/src/cli/runner.js +++ b/cli/src/cli/runner.js @@ -69,10 +69,10 @@ async function runWithUI(config, options = {}) { })); // Wait for React to flush the completed state to the screen - // Uses requestAnimationFrame to ensure the paint cycle completes + // Use setImmediate to allow React/Ink to flush updates await new Promise((resolve) => { - requestAnimationFrame(() => { - requestAnimationFrame(resolve); + setImmediate(() => { + setImmediate(resolve); }); }); diff --git a/cli/src/utils.js b/cli/src/utils.js index c808a88..405fc97 100644 --- a/cli/src/utils.js +++ b/cli/src/utils.js @@ -18,7 +18,7 @@ exports.getResolvedTestsFromEnv = getResolvedTestsFromEnv; exports.reportResults = reportResults; // Log function that respects logLevel -function log(config = {}, level = "info", message) { +function log(message, level = "info", config = {}) { const logLevels = ["silent", "error", "warning", "info", "debug"]; const currentLevel = config.logLevel || "info"; const currentLevelIndex = logLevels.indexOf(currentLevel); @@ -86,14 +86,14 @@ async function getResolvedTestsFromEnv(config = {}) { // Validate the structure: { accountId, url, token, contextIds } if (!apiConfig.accountId || !apiConfig.url || !apiConfig.token || !apiConfig.contextIds) { log( - config, + "Invalid DOC_DETECTIVE_API: must contain 'accountId', 'url', 'token', and 'contextIds' properties", "error", - "Invalid DOC_DETECTIVE_API: must contain 'accountId', 'url', 'token', and 'contextIds' properties" + config ); process.exit(1); } - log(config, "debug", `CLI:Fetching resolved tests from ${apiConfig.url}/resolved-tests`); + log(`CLI:Fetching resolved tests from ${apiConfig.url}/resolved-tests`, "debug", config); // Make GET request to the specified URL with token in header const response = await axios.get(`${apiConfig.url}/resolved-tests`, { @@ -113,9 +113,9 @@ async function getResolvedTestsFromEnv(config = {}) { if (!validation.valid) { log( - config, + "Invalid resolvedTests from API response. " + validation.errors, "error", - "Invalid resolvedTests from API response. " + validation.errors + config ); process.exit(1); } @@ -132,15 +132,15 @@ async function getResolvedTestsFromEnv(config = {}) { } log( - config, + `CLI:RESOLVED_TESTS:\n${JSON.stringify(resolvedTests, null, 2)}`, "debug", - `CLI:RESOLVED_TESTS:\n${JSON.stringify(resolvedTests, null, 2)}` + config ); } catch (error) { log( - config, + `Error fetching resolved tests from DOC_DETECTIVE_API: ${error.message}`, "error", - `Error fetching resolved tests from DOC_DETECTIVE_API: ${error.message}` + config ); process.exit(1); } @@ -165,19 +165,19 @@ async function getConfigFromEnv() { if (!envValidation.valid) { log( - envConfig, + `Invalid config from DOC_DETECTIVE_CONFIG environment variable. ${envValidation.errors}`, "error", - `Invalid config from DOC_DETECTIVE_CONFIG environment variable. ${envValidation.errors}` + {} ); process.exit(1); } - log(envConfig, "debug", `CLI:ENV_CONFIG:\n${JSON.stringify(envConfig, null, 2)}`); + log(`CLI:ENV_CONFIG:\n${JSON.stringify(envConfig, null, 2)}`, "debug", envConfig); } catch (error) { log( - {}, + `Error parsing DOC_DETECTIVE_CONFIG environment variable: ${error.message}`, "error", - `Error parsing DOC_DETECTIVE_CONFIG environment variable: ${error.message}` + {} ); process.exit(1); } From fa2e1e2b30e5dc588b84f16afc4022dc4c35f2c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:21:04 +0000 Subject: [PATCH 3/3] Fix OpenAI naming, aiConfig initialization, and schema validation Co-authored-by: hawkeyexl <5209367+hawkeyexl@users.noreply.github.com> --- common/src/ai.js | 4 +-- common/src/refineStep.js | 2 +- .../sourceLocation_v3.schema.json | 29 ++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/common/src/ai.js b/common/src/ai.js index 9a0782f..ab93ffb 100644 --- a/common/src/ai.js +++ b/common/src/ai.js @@ -592,9 +592,9 @@ const getApiKey = (config, provider) => { if ( provider === "openai" && - (process.env.OPENAI_API_KEY || config.integrations.openai) + (process.env.OPENAI_API_KEY || config.integrations?.openAi) ) { - return process.env.OPENAI_API_KEY || config.integrations.openai.apiKey; + return process.env.OPENAI_API_KEY || config.integrations.openAi.apiKey; } if ( diff --git a/common/src/refineStep.js b/common/src/refineStep.js index b346256..93fbfd0 100644 --- a/common/src/refineStep.js +++ b/common/src/refineStep.js @@ -234,7 +234,7 @@ const refineStep = async ({ } // Extract AI configuration (support both legacy config.ai and new config.integrations) - const aiConfig = {}; + const aiConfig = config?.ai || {}; const resolvedModel = model || aiConfig.model; const baseURL = aiConfig.baseURL; diff --git a/common/src/schemas/output_schemas/sourceLocation_v3.schema.json b/common/src/schemas/output_schemas/sourceLocation_v3.schema.json index a94b9b3..6de10cc 100644 --- a/common/src/schemas/output_schemas/sourceLocation_v3.schema.json +++ b/common/src/schemas/output_schemas/sourceLocation_v3.schema.json @@ -5,6 +5,18 @@ "type": "object", "readOnly": true, "additionalProperties": false, + "required": [ + "file", + "startLine", + "endLine", + "startColumn", + "endColumn", + "startOffset", + "endOffset", + "originalText", + "isInline", + "isAutoDetected" + ], "properties": { "file": { "type": "string", @@ -75,6 +87,21 @@ "readOnly": true } }, + "allOf": [ + { + "if": { + "properties": { + "isInline": { + "const": true + } + }, + "required": ["isInline"] + }, + "then": { + "required": ["commentFormat"] + } + } + ], "examples": [ { "file": "/path/to/docs/getting-started.md", @@ -100,7 +127,7 @@ "originalText": "[example link](https://example.com)", "isInline": true, "isAutoDetected": true, - "commentFormat": "htmlComment" + "commentFormat": "linkReference" } ] } \ No newline at end of file