diff --git a/.github/linters/comments.md b/.github/linters/comments.md new file mode 100644 index 0000000000..d7cf730de0 --- /dev/null +++ b/.github/linters/comments.md @@ -0,0 +1,3 @@ +Make sure the code is well-commented and easy to understand. Use comments to explain complex logic, provide context, and clarify the purpose of functions and classes. Avoid redundant comments that restate the code. Use docstrings for public methods and classes to describe their purpose, parameters, and return values. +Use inline comments sparingly and only when necessary. Comments should be in English and follow proper grammar and punctuation rules. Use consistent formatting for comments throughout the codebase. +Avoid using comments to disable code or leave TODOs. Instead, use version control systems to track changes and create issues for tasks that need to be addressed later. If you need to leave a comment, make sure it is clear and actionable. diff --git a/.github/workflows/genai-linters.yml b/.github/workflows/genai-linters.yml new file mode 100644 index 0000000000..7b53ac3a8a --- /dev/null +++ b/.github/workflows/genai-linters.yml @@ -0,0 +1,51 @@ +name: genai linters +on: + workflow_dispatch: + pull_request: + types: [opened, ready_for_review, reopened] + paths: + - yarn.lock + - "packages/core/**/*" + - "packages/cli/**/*" + - "packages/samples/**/*" +concurrency: + group: linters-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +env: + GENAISCRIPT_DEFAULT_REASONING_MODEL: ${{ vars.GENAISCRIPT_DEFAULT_REASONING_MODEL }} + GENAISCRIPT_DEFAULT_REASONING_SMALL_MODEL: ${{ vars.GENAISCRIPT_DEFAULT_REASONING_SMALL_MODEL }} + GENAISCRIPT_DEFAULT_MODEL: ${{ vars.GENAISCRIPT_DEFAULT_MODEL }} + GENAISCRIPT_DEFAULT_SMALL_MODEL: ${{ vars.GENAISCRIPT_DEFAULT_SMALL_MODEL }} + GENAISCRIPT_DEFAULT_VISION_MODEL: ${{ vars.GENAISCRIPT_DEFAULT_VISION_MODEL }} +jobs: + build: + runs-on: ubuntu-latest + permissions: + pull-requests: write + models: read + steps: + - uses: actions/checkout@v4 + with: + submodules: "recursive" + fetch-depth: 10 + - uses: actions/setup-node@v4 + with: + node-version: "20" + cache: yarn + - run: yarn install --frozen-lockfile + - name: compile + run: yarn compile + - name: git stuff + run: git fetch origin && git pull origin dev:dev + - name: genaiscript + run: node packages/cli/built/genaiscript.cjs run linters --out ./temp/genai/linters -prc -m reasoning --out-trace $GITHUB_STEP_SUMMARY --vars defaultBranch=dev + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_COMMIT_SHA: ${{ github.event.pull_request.base.sha}} + - name: Archive genai results + if: always() + uses: actions/upload-artifact@v4 + with: + name: genai-results + path: ./temp/genai/** diff --git a/.github/workflows/genai-pr-review.yml b/.github/workflows/genai-pr-review.yml index 8df0fe4ba9..a97938624c 100644 --- a/.github/workflows/genai-pr-review.yml +++ b/.github/workflows/genai-pr-review.yml @@ -9,7 +9,7 @@ on: - "packages/cli/**/*" - "packages/samples/**/*" concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: pr-review-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: GENAISCRIPT_DEFAULT_REASONING_MODEL: ${{ vars.GENAISCRIPT_DEFAULT_REASONING_MODEL }} diff --git a/genaisrc/linters.genai.mts b/genaisrc/linters.genai.mts new file mode 100644 index 0000000000..fdc0d42745 --- /dev/null +++ b/genaisrc/linters.genai.mts @@ -0,0 +1,66 @@ +script({ + title: "Linters", + systemSafety: false, + system: ["system", "system.assistant", "system.annotations"], + responseType: "text", + tools: ["agent_fs", "agent_git"], + parameters: { + base: { + type: "string", + description: "The base commit to compare against.", + default: "HEAD^", + }, + }, +}) + +const base = env.vars.base || (await git.defaultBranch()) +const changes = await git.diff({ + base, + ignoreSpaceChange: true, +}) +def("GIT_DIFF", changes, { + maxTokens: 14000, + detectPromptInjection: "available", +}) + +const { vars, dbg, output } = env + +const linters = await workspace.findFiles(".github/linters/*.md") +if (!linters) cancel("no linters found in .github/linters/*.md") +dbg(`found %d linters`, linters.length) + +const diff = await git.diff({ + base, + llmify: true, + ignoreSpaceChange: true, +}) +if (!diff) cancel("nothing changed") +def("DIFF", diff, { language: "diff", maxTokens: 7000 }) +dbg(diff) + +$`You are an expert in code linting. + +You will be provided a list of linters and you will apply them +to the code in the variable using the strategy below. + +## Strategy + +for each linter: + read the linter description + apply the linter to the code in + report any errors or warnings using annotations format. Use the linter name as the code. + +## Linters + +`.role("system") +for (const linter of linters) { + const name = path.basename(linter.filename) + const content = MD.content(linter) + + $`### ${name}`.role("system") + writeText(content, { role: "system" }) +} + +$`## Output +You will output the results of the linting process using the annotation format. +`.role("system") diff --git a/packages/core/src/githubclient.ts b/packages/core/src/githubclient.ts index 7e63c92e85..0a36823e1b 100644 --- a/packages/core/src/githubclient.ts +++ b/packages/core/src/githubclient.ts @@ -314,7 +314,7 @@ export function generatedByFooter( info: { runUrl?: string }, code?: string ) { - return `\n\n> AI-generated content by ${link(script.id, info.runUrl)}${code ? ` \`${code}\` ` : ""} may be incorrect\n\n` + return `\n\n> AI-generated content by ${link(script.id, info.runUrl)}${code ? ` \`${code}\` ` : ""} may be incorrect. Use 👍👎 to eval.\n\n` } /**