Files
orca/src/shared/command-option-occurrence.ts
T
Brennan Bensonandbeduldul 47018d4844 fix(source-control): decode Kimi generated text by selected format (#34237)
* 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>
2026-10-27 16:33:33 -07:00

50 lines
1.6 KiB
TypeScript

function matchesOption(token: string, aliases: readonly string[]): boolean {
return aliases.some(
(alias) =>
token === alias ||
(alias !== '--' && token.startsWith(`${alias}=`)) ||
(alias.startsWith('-') &&
!alias.startsWith('--') &&
token.startsWith(alias) &&
token.length > alias.length)
)
}
export function findOptionOccurrence(
tokens: readonly string[],
aliases: readonly string[],
stopAtTerminator: boolean,
valueOptions: readonly string[] = [],
startIndex = 0,
/** False keeps the next token; 'required' consumes even a dash-leading operand. */
takesValue: boolean | 'required' = true
): { index: number; consumed: number; value?: string } | null {
for (let index = startIndex; index < tokens.length; index += 1) {
const token = tokens[index]
if (stopAtTerminator && token === '--') {
break
}
if (!matchesOption(token, aliases)) {
// Required option values can look like flags, including `--`.
if (valueOptions.includes(token)) {
index += 1
}
continue
}
const nextToken = tokens[index + 1]
const consumesNext =
takesValue &&
aliases.includes(token) &&
nextToken !== undefined &&
(takesValue === 'required' || !nextToken.startsWith('-'))
const alias = aliases.find((name) => matchesOption(token, [name]))
const value = consumesNext
? nextToken
: alias && token !== alias
? token.slice(alias.length + (token[alias.length] === '=' ? 1 : 0))
: undefined
return { index, consumed: consumesNext ? 2 : 1, value }
}
return null
}