[codex] Harden LLM command decoding - #65
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
data:event wrappers, serialized JSON payload wrappers, runner JSON log envelopes, and final/partial metadata.asr_result,transcription_result, andrecognitionResultso runner envelopes do not hide the actual transcript.result,data, andpayload, while preserving literal JSON-like dictation when no transcript signal is present.level,logger, orseveritywithout transcript signals, so startup/progress messages are not inserted as dictated text.data,message,payload, and stable/final wrappers now count only when their nested object, array, or serialized JSON contains a real transcript signal, so plain log strings are skipped while log-shaped transcript payloads are preserved.normalized_text,recognizedText,recognizedPhrases, candidate/beam lists, typed element arrays, monologue wrappers, stable/final wrappers, and nested result wrappers.{ "type": "text", "value": "..." }and punctuation elements, while leaving untypedvaluemetadata alone.channel.alternativestranscript wrappers andspeech_finalmetadata so final channel hypotheses are selected over interim channel hypotheses.sentence_end,utterance_end,end_of_speech, andis_eos, plus endpoint string status values such asSentenceEnd,UtteranceEnd, andEndOfSpeech.FinalTranscript,PartialTranscript,FinalResult, andPartialResultfromtype/status/message_typestyle metadata.resultsarrays whose final entries contain alternatives, while treating cumulative final updates as replacements so partial/full repeats do not duplicate text.done, so stream completion markers do not cause the earlier dictated text to be dropped.conf,confidence_value,confidence_percent, andconfidence_pct, plus envelopes such as{ "confidence": { "value": "0.93" } }and normalized confidence wrappers, so high-confidence alternatives/candidates can still win when providers vary score fields.<|...|>markers, so model scaffolding does not leak into dictated text.data:payloads, content arrays/objects, typed OpenAI content delta blocks, parsed payloads, singular/plural tool call deltas, Anthropic camelCase stream aliases, Anthropic content-block index aliases and single-block streams without explicit indexes, tool/function arguments, typed final text/content-part done blocks, final-text value envelopes, wrapped replacement payloads, and case-insensitive field names."{...}"still resolve to the intended command while earlier quoted examples do not override later final output.edit_instruction,rewrite_instruction,goal, andobjective, intent preset objects that usetypeorkindvalues such as{ "intent": { "type": "summary" } }, target aliases such astarget,scope,object, andedit_target, target objects such as{ "kind": "selection" }and{ "entity": "lastInsertion" }, target boolean flags such as{ "selection": true }and{ "lastInsertion": true }, nested target or scope fields inside action objects such as{ "action": { "type": "rewrite", "target": { "kind": "selection" } } }, action parameter containers such as{ "action": { "name": "rewrite", "parameters": { "target": { "kind": "selection" } } } }, action boolean flags such as{ "rewrite": true }and{ "replaceLast": true }, top-level replacement text aliases such asto_text,correctedText, andcurrent,command_type/operationTypeaction aliases, action+target pairs such asreplace+last_insertionorrewrite+selection, andpercent/percentage/pct/certaintyconfidence aliases from model-generated command JSON, includingcertainty/justificationwhen they appear as metadata inside action, target, intent, replacement, or final-text objects.Why
Real ASR and LLM providers do not always return the ideal shape. They stream partial fragments, emit final segment/result lists, wrap transcripts in provider-specific result/channel/SSE envelopes, serialize inner ASR JSON into wrapper strings, interleave transcript lines with structured runner logs, attach log-like metadata such as severity to real transcript payloads, vary finality metadata names and status values, split no-space-language text into tokenizer pieces, include tokenizer control markers, wrap confidence scores, send terminal events separately from transcript text, name competing ASR hypotheses as candidates or beams, put transcript text in typed
valueelements undermonologues/elements, split committed and tentative text intostable/unstableorfinal/partialwrappers, name confidence asconf,confidence_value, or percentage fields, put event types in SSEevent:lines instead ofdata:JSON payloads, rename or omit stream block indexes in single-block adapters, double-encode JSON payloads as JSON strings, or return final text and edit-command replacement text through tool arguments, singular tool-call deltas, Anthropic camelCase stream fields, typed OpenAI content delta blocks, content-part done events, nested value envelopes, adapter-specific payload fields, action fields named as command/operation types, edit actions or targets expressed as boolean flags, edit targets named separately as scope/object/target fields, nested target objects, or boolean target flags, intent fields named as goals/objectives/instructions, replacement text fields emitted directly at the top level, and confidence fields named as percentages instead of canonicalconfidence. The voice path should recover the model's intended transcript or edit command when the signal is present, while keeping semantic cleanup and command decisions with the LLM.Validation
swift test --quiet --filter LocalASRStableWrapperTests— 4 passedswift test --quiet --filter LocalASRElementOutputTests— 3 passedswift test --quiet --filter LocalASRConfidenceTests— 4 passedswift test --quiet --filter LocalASRCandidateOutputTests— 3 passedswift test --quiet --filter LocalASR— 83 passedswift test --quiet --filter LLMStructuredOutputTests— 7 passedswift test --quiet --filter SpokenEditCommandQuotedJSONTests— 2 passedswift test --quiet --filter SpokenEditCommandLLMRobustnessTests— 19 passedswift test --quiet --filter SpokenEditCommandIntentValueTests— 9 passedswift test --quiet --filter SpokenEditCommandReplacementValueTests— 6 passedswift test --quiet --filter SpokenEditCommandActionValueTests— 8 passedswift test --quiet --filter SpokenEditCommandConfidenceValueTests— 3 passedswift test --quiet --filter SpokenEditCommandMetadataValueTests— 5 passedswift test --quiet --filter FormattedOutputCleanerMetadataTests— 2 passedswift test --quiet --filter FormattedOutputCleaner— 24 passedswift test --quiet --filter SpokenEditCommand— 72 passedswift test --quiet --filter LocalASRJSONLinesOutputTests— 11 passedswift test --quiet— 503 passed, 3 skippedswift build --quietxcodebuild -downloadComponent MetalToolchain./scripts/build-app.sh --app-only --sign=-codesign --verify --deep --strict --verbose=2 dist/OpenType.appbash scripts/ci-basic-checks.shgit diff --checkgit diff --cached --check