mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-07 17:09:13 -10:00
fix(action): reserve output for complete reasoning-model reviews (CW-6869) [skip ci]
Live run 40830663408 reached DeepSeek but used all 4000 automatically allowed output tokens and returned no review. Publication was skipped. Generate an explicit 16384-token allowance, configurable with --max-output-tokens, and retain sanitized reasoning counts. Recognize the released CLI infrastructure/not_produced envelope as incomplete without logging raw provider/model errors. Local verification: existing review checks 8 passed, 0 failed; direct failure-envelope classification and actionlint pass. The running workflow still references the prior reviewed Action commit; the next source pin update carries this repair.
This commit is contained in:
1 parent
43d8faead7
commit
f4c2ce3a6e
4 files changed
+16
-4
No files matched your search
@@ -41,6 +41,7 @@ jobs:
|
||||
version: 'v0.10.2'
|
||||
provider: 'deepseek'
|
||||
model: 'deepseek-flash'
|
||||
max-output-tokens: '16384'
|
||||
pr-number: ${{ inputs.pr-number }}
|
||||
trigger-phrase: '@codewhale'
|
||||
allow-forks: 'true'
|
||||
|
||||
@@ -32,9 +32,12 @@ Ubuntu runner provides the review tools. No server or GitHub App is required.
|
||||
|
||||
Select your own provider and exact model ID. The generator pins both
|
||||
Codewhale actions to the source checkout's full commit and the CLI to
|
||||
`v0.10.2`. It refuses to overwrite an existing workflow. Use `--print` to
|
||||
`v0.10.2`, with a 16384-token output allowance for the completed review.
|
||||
It refuses to overwrite an existing workflow. Use `--print` to
|
||||
inspect the YAML, `--version vX.Y.Z` to choose another released CLI, or
|
||||
`--action-ref FULL_COMMIT_SHA` with a separately downloaded `setup.mjs`.
|
||||
`--max-output-tokens N` changes the explicit output allowance. Reasoning
|
||||
models can exhaust smaller automatic allowances before writing findings.
|
||||
The generated workflow is `.github/workflows/codewhale-review.yml`.
|
||||
|
||||
2. Store only the selected provider's API key as a repository Actions secret:
|
||||
|
||||
@@ -133,7 +133,7 @@ export function classify(result, head, post, base) {
|
||||
const publication = ['not_requested', 'not_attempted', 'uncertain', 'posted'].includes(data?.publication)
|
||||
? data.publication : 'unknown';
|
||||
const usage = {};
|
||||
for (const key of ['input_tokens', 'output_tokens', 'cache_read_input_tokens', 'cache_creation_input_tokens']) {
|
||||
for (const key of ['input_tokens', 'output_tokens', 'reasoning_tokens', 'cache_read_input_tokens', 'cache_creation_input_tokens']) {
|
||||
if (Number.isSafeInteger(data?.usage?.[key]) && data.usage[key] >= 0) usage[key] = data.usage[key];
|
||||
}
|
||||
const evidence = { publication, usage };
|
||||
@@ -144,6 +144,10 @@ export function classify(result, head, post, base) {
|
||||
if (data?.success === true && data.complete === false) {
|
||||
return { ...evidence, outcome: 'incomplete', reason: 'coverage_incomplete' };
|
||||
}
|
||||
if (data?.mode === 'review' && data.success === false && data.complete === false
|
||||
&& data.outcome === 'infrastructure' && data.review_verdict === 'not_produced') {
|
||||
return { ...evidence, outcome: 'incomplete', reason: 'review_not_produced' };
|
||||
}
|
||||
if (result.status !== 0 || data?.mode !== 'review' || data.success !== true || data.complete !== true
|
||||
|| data.pr?.head_sha !== head || !Array.isArray(data.review?.issues)
|
||||
|| !Number.isSafeInteger(data.review_passes) || data.review_passes < 1
|
||||
|
||||
@@ -21,6 +21,7 @@ const HELP = `Create a Codewhale review bot workflow in your repository.
|
||||
--action-ref SHA Reviewed Action commit (default: this clean source checkout)
|
||||
--trigger-phrase NAME Mention to listen for (default: @codewhale)
|
||||
--app-login LOGIN Optional existing GitHub App login, including [bot]
|
||||
--max-output-tokens N Review output allowance (default: 16384; minimum: 8192)
|
||||
--print Print YAML without writing files
|
||||
--help Show this help
|
||||
|
||||
@@ -30,7 +31,7 @@ Automatic reviews cover same-repository PRs. Maintainers can review fork PRs
|
||||
with a manual run or an @codewhale review comment; PR code is never executed.
|
||||
`;
|
||||
|
||||
export function workflow({ provider, model, version = 'v0.10.2', actionRef, triggerPhrase = '@codewhale', appLogin }) {
|
||||
export function workflow({ provider, model, version = 'v0.10.2', actionRef, triggerPhrase = '@codewhale', appLogin, maxOutputTokens = '16384' }) {
|
||||
if (!Object.hasOwn(KEYS, provider)) throw new Error('Choose a supported --provider.');
|
||||
if (!/^[A-Za-z0-9][A-Za-z0-9_./:@+-]{0,199}$/.test(model || '')
|
||||
|| (provider === 'codewhale' && !/^[A-Za-z0-9_.-]+\/.+/.test(model))) throw new Error('Choose an exact --model ID.');
|
||||
@@ -38,6 +39,7 @@ export function workflow({ provider, model, version = 'v0.10.2', actionRef, trig
|
||||
if (!/^[a-f0-9]{40}$/i.test(actionRef || '')) throw new Error('--action-ref must be a full reviewed commit SHA.');
|
||||
if (!/^@[A-Za-z0-9][A-Za-z0-9-]{0,38}$/.test(triggerPhrase)) throw new Error('--trigger-phrase must be @ followed by a GitHub-style name.');
|
||||
if (appLogin && !/^[a-zA-Z0-9][a-zA-Z0-9-]{0,99}\[bot\]$/.test(appLogin)) throw new Error('--app-login must include [bot].');
|
||||
if (!/^[1-9][0-9]*$/.test(String(maxOutputTokens)) || Number(maxOutputTokens) < 8192 || Number(maxOutputTokens) > 1000000) throw new Error('--max-output-tokens must be between 8192 and 1000000.');
|
||||
const action = `codewhale-hq/Codewhale@${actionRef}`;
|
||||
const secret = KEYS[provider];
|
||||
const expression = value => '${{ ' + value + ' }}';
|
||||
@@ -84,6 +86,7 @@ jobs:
|
||||
version: '${version}'
|
||||
provider: '${provider}'
|
||||
model: '${model}'
|
||||
max-output-tokens: '${maxOutputTokens}'
|
||||
pr-number: ${expression('inputs.pr-number')}
|
||||
trigger-phrase: '${triggerPhrase}'
|
||||
allow-forks: 'true'
|
||||
@@ -151,6 +154,7 @@ export function setup(args = process.argv.slice(2)) {
|
||||
provider: { type: 'string' }, model: { type: 'string' }, directory: { type: 'string' },
|
||||
version: { type: 'string' }, 'action-ref': { type: 'string' }, 'trigger-phrase': { type: 'string' },
|
||||
'app-login': { type: 'string' }, print: { type: 'boolean' }, help: { type: 'boolean' },
|
||||
'max-output-tokens': { type: 'string' },
|
||||
} });
|
||||
if (values.help) { console.log(HELP); return; }
|
||||
let actionRef = values['action-ref'];
|
||||
@@ -164,7 +168,7 @@ export function setup(args = process.argv.slice(2)) {
|
||||
actionRef = head.stdout.trim();
|
||||
}
|
||||
const yaml = workflow({ provider: values.provider, model: values.model, version: values.version,
|
||||
actionRef, triggerPhrase: values['trigger-phrase'], appLogin: values['app-login'] });
|
||||
actionRef, triggerPhrase: values['trigger-phrase'], appLogin: values['app-login'], maxOutputTokens: values['max-output-tokens'] });
|
||||
if (values.print) { process.stdout.write(yaml); return; }
|
||||
const directory = realpathSync(values.directory || process.cwd());
|
||||
if (spawnSync('git', ['-C', directory, 'rev-parse', '--show-toplevel'], { encoding: 'utf8' }).stdout.trim() !== directory) throw new Error('--directory must be a Git repository root.');
|
||||
|
||||
Reference in new issue
Block a user