Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/.github/workflows/auto-dev-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
4 changes: 2 additions & 2 deletions cli/.github/workflows/npm-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
cache: 'npm'
cache-dependency-path: package-lock.json

- run: npm install
- run: npm ci
- run: npm test

publish-npm:
Expand All @@ -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}}
Expand Down
8 changes: 8 additions & 0 deletions cli/scripts/bump-sync-version-core.js
Original file line number Diff line number Diff line change
@@ -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");
Expand All @@ -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");
Expand Down
3 changes: 2 additions & 1 deletion cli/src/cli/builder/TestEditor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions cli/src/cli/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});

Expand Down
30 changes: 15 additions & 15 deletions cli/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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`, {
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions common/src/ai.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
2 changes: 1 addition & 1 deletion common/src/refineStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
29 changes: 28 additions & 1 deletion common/src/schemas/output_schemas/sourceLocation_v3.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -100,7 +127,7 @@
"originalText": "[example link](https://example.com)",
"isInline": true,
"isAutoDetected": true,
"commentFormat": "htmlComment"
"commentFormat": "linkReference"
}
]
}