mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
* fix(source-control): read the Kimi answer from stream-json Kimi Code's text mode prefixes thinking and hook output with a bullet, so the commit message arrived mixed with narration. The recipe now asks for --output-format stream-json and the answer is taken from the last assistant record, which is the commit message (#33556). A record that requests a tool is narration rather than an answer, so it clears the candidate: a stream that ends on a tool call yields no answer, which finalizeFromAgentOutput already treats as a failed run. Only a body whose every non-empty line is a record counts as stream output, so a plain answer that happens to contain a JSON line is left alone. * fix(source-control): decode Kimi output only for the selected protocol * fix(source-control): satisfy generation hook checks * Preserve Kimi generation failures and normalize options linearly * Fix Kimi argument failure messages * Bound Kimi option failure recognition * Fix Kimi generation test fixture types --------- Co-authored-by: beduldul <alkaysan07@gmail.com>
81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
import { expect, it } from 'vitest'
|
|
import { planCommitMessageGeneration } from './commit-message-plan'
|
|
import { KIMI_VALUE_OPTIONS } from './commit-message-generation-options'
|
|
|
|
function plan(prefix = '', agentArgs = '', prompt = 'P') {
|
|
const result = planCommitMessageGeneration(
|
|
{ agentId: 'kimi', model: 'default', agentCommandOverride: `kimi ${prefix}`, agentArgs },
|
|
prompt
|
|
)
|
|
if (!result.ok) {
|
|
throw new Error(result.error)
|
|
}
|
|
return result.plan
|
|
}
|
|
const base = '--prompt P'
|
|
const stream = '--output-format stream-json'
|
|
const text = '--output-format text'
|
|
const equalsText = '--output-format=text'
|
|
it.each([
|
|
['', `${equalsText} ${stream}`, `${base} ${equalsText}`, false],
|
|
[text, '--output-format=stream-json', `${base} --output-format=stream-json`, true],
|
|
[`${equalsText} ${stream}`, '', `${equalsText} ${base}`, false],
|
|
['', `${text} -- ${stream}`, `${base} ${text} -- ${stream}`, false],
|
|
[`-- ${stream}`, '', `-- ${stream} ${base} ${stream}`, false],
|
|
[`--model "--" ${text}`, stream, `--model -- ${base} ${stream}`, true],
|
|
[
|
|
'-mprefix --keep before',
|
|
'-mrecipe --model ignored --keep after',
|
|
`--keep before ${base} ${stream} -mrecipe --keep after`,
|
|
true
|
|
]
|
|
])('preserves prefix %s / recipe %s', (prefix, recipe, argv, selected) => {
|
|
const result = plan(prefix, recipe)
|
|
expect(result.args).toEqual(argv.split(' '))
|
|
expect(result.outputFormat).toBe(selected ? 'kimi-stream-json' : undefined)
|
|
})
|
|
it.each(KIMI_VALUE_OPTIONS.filter((option) => option !== '--output-format'))(
|
|
'preserves required operands of %s including a literal terminator',
|
|
(option) => {
|
|
for (const value of ['--', '--output-format=text']) {
|
|
expect(plan('', `${option} "${value}"`).args.join(' ')).toBe(
|
|
`${base} ${stream} ${option} ${value}`
|
|
)
|
|
}
|
|
}
|
|
)
|
|
it.each(['--', '--output-format=text', 'stream-json'])(
|
|
'preserves flag-looking prompt %s',
|
|
(prompt) => {
|
|
expect(plan('', '--output-format=text', prompt).args).toEqual([
|
|
'--prompt',
|
|
prompt,
|
|
'--output-format=text'
|
|
])
|
|
}
|
|
)
|
|
|
|
it('keeps repeated-format planning linear', () => {
|
|
const slice = Array.prototype.slice
|
|
const counts: number[] = []
|
|
for (const n of [20, 200]) {
|
|
const recipe = Array(n).fill('--output-format=text').join(' ')
|
|
let copied = 0
|
|
Array.prototype.slice = function (start, end) {
|
|
const result = slice.call(this, start, end)
|
|
copied += result.length
|
|
return result
|
|
}
|
|
let result
|
|
try {
|
|
result = plan('', recipe)
|
|
} finally {
|
|
Array.prototype.slice = slice
|
|
}
|
|
expect(result.args).toEqual(['--prompt', 'P', '--output-format=text'])
|
|
expect(copied).toBeLessThan(5 * n + 100)
|
|
counts.push(copied)
|
|
}
|
|
expect(counts[1]).toBeLessThanOrEqual(10 * counts[0])
|
|
})
|