Files
orca/src/shared/commit-message-generation-options.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

76 lines
1.9 KiB
TypeScript

import { findOptionOccurrence } from './command-option-occurrence'
import {
tokenizeCustomCommandTemplate,
type CommandTemplateBackslash
} from './commit-message-prompt'
export function planAdditionalAgentArgs(
agentArgs: string | null | undefined,
backslash: CommandTemplateBackslash = 'escape'
): { ok: true; args: string[] } | { ok: false; error: string } {
const trimmed = agentArgs?.trim()
if (!trimmed) {
return { ok: true, args: [] }
}
const tokenized = tokenizeCustomCommandTemplate(trimmed, backslash)
if (!tokenized.ok) {
return { ok: false, error: `CLI arguments are invalid: ${tokenized.error}` }
}
return { ok: true, args: tokenized.tokens }
}
export const KIMI_VALUE_OPTIONS = [
'--prompt',
'-p',
'--model',
'-m',
'--output-format',
'--skills-dir',
'--agent',
'--agent-file',
'--add-dir'
]
export function findRecipeOption(
tokens: readonly string[],
aliases: readonly string[],
valueOptions: readonly string[],
startIndex = 0,
stopAtTerminator = true
) {
return findOptionOccurrence(
tokens,
aliases,
stopAtTerminator,
valueOptions,
startIndex,
valueOptions.length ? 'required' : true
)
}
export function compactRecipeOptions(
tokens: string[],
aliases: readonly string[],
valueOptions: readonly string[] = [],
keepFirst = false
): string[] {
const result: string[] = []
let cursor = 0
let kept = false
let found = findRecipeOption(tokens, aliases, valueOptions, cursor)
while (found) {
const end = found.index + found.consumed
const keepUntil = keepFirst && !kept ? end : found.index
for (; cursor < keepUntil; cursor++) {
result.push(tokens[cursor])
}
cursor = end
kept = true
found = findRecipeOption(tokens, aliases, valueOptions, cursor)
}
for (; cursor < tokens.length; cursor++) {
result.push(tokens[cursor])
}
return result
}