Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions GraphcodeKit/Sources/Domain/BackendCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,23 @@ extension CLISessionBackendKind {
///
/// Deliberately per-backend rather than one shared alias list: Claude Code takes short
/// aliases that keep resolving to the current model in a class, whereas Copilot's
/// `--model` takes explicit versioned ids from a fixed set (read off `copilot --help`
/// at 0.0.410). Pointing the same string at both would silently fail on one of them.
/// `--model` takes explicit versioned ids from a fixed set (read off `copilot help
/// config` at 1.0.84). Pointing the same string at both would silently fail on one of
/// them.
///
/// `.standard` returns nil everywhere — passing no flag lets the backend's own default
/// apply, which is different from asserting what we think it is.
/// apply, which is different from asserting what we think it is. Copilot's `.capable`
/// is nil too: its list turns over fast enough that the pinned id (`claude-opus-4.6`)
/// had already gone by 1.0.84, and a capable loop that fails to launch is worse than
/// one on Copilot's own default.
public func modelArguments(for tier: ModelTier) -> [String] {
switch self {
case .claudeCode:
return tier.modelAlias.map { ["--model", $0] } ?? []
case .copilotCLI:
switch tier {
case .fast: return ["--model", "claude-haiku-4.5"]
case .standard: return []
case .capable: return ["--model", "claude-opus-4.6"]
case .fast: return ["--model", "gpt-5.6-luna"]
case .standard, .capable: return []
}
case .codex:
// `-m` is real, but the valid model ids are not visible from `codex --help` and a
Expand Down
2 changes: 1 addition & 1 deletion GraphcodeKit/Sources/Sessions/SummaryModelWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public enum SummaryModelWriter {
/// **The model argument comes from the backend, not from the tier.** `ModelTier`'s alias
/// is Claude Code's spelling — `haiku` — and this passed it to all three, which is the
/// exact mistake `BackendCommand.modelArguments(for:)` was written to prevent: Copilot's
/// `--model` takes explicit versioned ids (`claude-haiku-4.5`) and Codex's valid ids
/// `--model` takes explicit versioned ids (`gpt-5.6-luna`) and Codex's valid ids
/// aren't visible from its `--help` at all, so it is given none and its own default
/// applies. A wrong id fails at launch, which for this path means every rewrite quietly
/// failing and the agent's own sentence standing — the feature would look switched off.
Expand Down
12 changes: 6 additions & 6 deletions graphcode/Tests/CopilotBackendTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ struct CopilotBackendTests {
// at runtime, which is why the mapping is per-backend.
#expect(
CLISessionBackendKind.copilotCLI.modelArguments(for: .fast)
== ["--model", "claude-haiku-4.5"])
#expect(
CLISessionBackendKind.copilotCLI.modelArguments(for: .capable)
== ["--model", "claude-opus-4.6"])
== ["--model", "gpt-5.6-luna"])
// Capable is deliberately unpinned on Copilot: its id list turns over faster than a
// release cycle, and a launch that fails on a stale id is worse than the default.
#expect(CLISessionBackendKind.copilotCLI.modelArguments(for: .capable).isEmpty)
// Claude Code's aliases stay aliases — they keep resolving to the current model.
#expect(CLISessionBackendKind.claudeCode.modelArguments(for: .fast) == ["--model", "haiku"])
}
Expand All @@ -76,10 +76,10 @@ struct CopilotBackendTests {

@Test
func aPinnedTierReachesTheCopilotArgv() {
let arguments = ZmxSessionLauncher.arguments(forNode: node(tier: .capable)) ?? []
let arguments = ZmxSessionLauncher.arguments(forNode: node(tier: .fast)) ?? []

#expect(arguments.contains("--model"))
#expect(arguments.contains("claude-opus-4.6"))
#expect(arguments.contains("gpt-5.6-luna"))
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion graphcode/Tests/SummaryStoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ struct SummaryStoreTests {
// Copilot's `--model` takes an explicit versioned id, not Claude Code's short alias.
#expect(
SummaryModelWriter.invocation(forBackend: .copilotCLI, prompt: "p")
== ["copilot", "-p", "p", "--model", "claude-haiku-4.5"])
== ["copilot", "-p", "p", "--model", "gpt-5.6-luna"])
// Codex's valid ids aren't visible from its `--help`, so it is given none and its own
// default applies — an honest omission rather than a guessed id. Its non-interactive
// mode is a subcommand.
Expand Down
Loading