Files
orca/src/shared/omp-model-list-probe.ts
T
Neilandunknown 4dec64d533 feat(source-control-ai): support OMP generation (#20624)
* feat(source-control-ai): support OMP text generation

Read prompts on stdin, retain OMP configured model by default, and reuse JSON model discovery.

Co-authored-by: unknown <1784931579@qq.com>

* test(source-control-ai): cover OMP large input and model overrides

* fix(omp): keep configured model default out of discovered catalog

* fix(omp): hide config default from model discovery catalog

* fix(omp): separate terminal discovery from generation defaults

* test(omp): keep model probe import compatible with CLI typecheck

* test: align Source Control AI registry contracts with OMP

---------

Co-authored-by: unknown <1784931579@qq.com>
2026-09-19 01:54:50 -07:00

67 lines
2.4 KiB
TypeScript

import type { CommitMessageModel } from './commit-message-agent-spec'
import { labelFromModelId } from './model-id-label'
// Why: `omp models --json` is the one machine-readable listing OMP offers; the
// default table output groups rows per provider and would need a brittle parser.
export const OMP_MODEL_LIST_ARGS = ['models', '--json']
/** The outermost JSON value on stdout, or null when none parses. */
function parseJsonObject(stdout: string): unknown {
const trimmed = stdout.trim()
try {
return JSON.parse(trimmed)
} catch {
// Why: an update notice or extension warning can precede the JSON on stdout;
// the listing itself is the outermost object.
const start = trimmed.indexOf('{')
const end = trimmed.lastIndexOf('}')
if (start === -1 || end <= start) {
return null
}
try {
return JSON.parse(trimmed.slice(start, end + 1))
} catch {
return null
}
}
}
/** Parses `omp models --json`. Ids are OMP's `provider/model` selector — the form
* `--model` and `/model` resolve exactly, unlike a bare model id that several
* providers can share. */
export function parseOmpModelList(stdout: string): CommitMessageModel[] {
const parsed = parseJsonObject(stdout)
if (!parsed || typeof parsed !== 'object' || !('models' in parsed)) {
return []
}
const rows: unknown = parsed.models
if (!Array.isArray(rows)) {
return []
}
const byId = new Map<string, CommitMessageModel>()
for (const row of rows) {
const value: unknown = row
if (!value || typeof value !== 'object' || Array.isArray(value)) {
continue
}
const provider =
'provider' in value && typeof value.provider === 'string' ? value.provider.trim() : ''
const bareId = 'id' in value && typeof value.id === 'string' ? value.id.trim() : ''
const selector =
'selector' in value && typeof value.selector === 'string' ? value.selector.trim() : ''
const id = selector || (provider && bareId ? `${provider}/${bareId}` : '')
if (!id || byId.has(id)) {
continue
}
const name = 'name' in value && typeof value.name === 'string' ? value.name.trim() : ''
byId.set(id, {
id,
label: name || labelFromModelId(id),
// Why: the same model name ships under several providers; the provider is
// what tells two "DeepSeek V4 Pro" rows apart in the picker.
...(provider ? { description: provider } : {})
})
}
return [...byId.values()]
}