@gajae-code/coding-agent 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/types/cli/fast-help.d.ts +1 -0
  3. package/dist/types/cli/setup-cli.d.ts +2 -0
  4. package/dist/types/commands/harness.d.ts +6 -0
  5. package/dist/types/commands/setup.d.ts +6 -0
  6. package/dist/types/config/model-profile-activation.d.ts +11 -2
  7. package/dist/types/config/model-profiles.d.ts +7 -0
  8. package/dist/types/config/model-registry.d.ts +6 -0
  9. package/dist/types/config/model-resolver.d.ts +2 -0
  10. package/dist/types/config/models-config-schema.d.ts +35 -0
  11. package/dist/types/config/settings-schema.d.ts +4 -3
  12. package/dist/types/coordinator/contract.d.ts +1 -1
  13. package/dist/types/coordinator-mcp/server.d.ts +8 -2
  14. package/dist/types/gjc-runtime/team-runtime.d.ts +0 -1
  15. package/dist/types/gjc-runtime/tmux-common.d.ts +3 -0
  16. package/dist/types/harness-control-plane/finalize.d.ts +5 -0
  17. package/dist/types/harness-control-plane/owner.d.ts +1 -1
  18. package/dist/types/harness-control-plane/phase-rollup.d.ts +23 -0
  19. package/dist/types/harness-control-plane/receipt-ingest.d.ts +19 -0
  20. package/dist/types/harness-control-plane/receipt-spool.d.ts +19 -0
  21. package/dist/types/harness-control-plane/receipts.d.ts +46 -0
  22. package/dist/types/harness-control-plane/rpc-adapter.d.ts +3 -0
  23. package/dist/types/harness-control-plane/state-machine.d.ts +6 -1
  24. package/dist/types/harness-control-plane/types.d.ts +13 -1
  25. package/dist/types/hindsight/mental-models.d.ts +5 -5
  26. package/dist/types/main.d.ts +2 -2
  27. package/dist/types/modes/components/model-selector.d.ts +1 -12
  28. package/dist/types/modes/rpc/rpc-client.d.ts +2 -2
  29. package/dist/types/modes/rpc/rpc-types.d.ts +4 -1
  30. package/dist/types/modes/utils/abort-message.d.ts +4 -0
  31. package/dist/types/sdk.d.ts +5 -0
  32. package/dist/types/session/agent-session.d.ts +2 -0
  33. package/dist/types/session/blob-store.d.ts +20 -1
  34. package/dist/types/session/session-manager.d.ts +32 -6
  35. package/dist/types/session/streaming-output.d.ts +3 -2
  36. package/dist/types/session/tool-choice-queue.d.ts +6 -0
  37. package/dist/types/setup/hermes-setup.d.ts +7 -0
  38. package/dist/types/task/fork-context-advisory.d.ts +13 -0
  39. package/dist/types/task/receipt.d.ts +2 -0
  40. package/dist/types/task/roi-reconciliation.d.ts +27 -0
  41. package/dist/types/task/types.d.ts +17 -0
  42. package/dist/types/thinking-metadata.d.ts +16 -0
  43. package/dist/types/thinking.d.ts +3 -12
  44. package/dist/types/tools/index.d.ts +2 -0
  45. package/dist/types/tools/resolve.d.ts +0 -10
  46. package/dist/types/utils/tool-choice.d.ts +14 -1
  47. package/package.json +8 -7
  48. package/scripts/build-binary.ts +4 -0
  49. package/src/cli/fast-help.ts +80 -0
  50. package/src/cli/setup-cli.ts +12 -3
  51. package/src/cli.ts +112 -17
  52. package/src/commands/coordinator.ts +44 -1
  53. package/src/commands/harness.ts +128 -11
  54. package/src/commands/launch.ts +2 -2
  55. package/src/commands/mcp-serve.ts +3 -2
  56. package/src/commands/session.ts +3 -1
  57. package/src/commands/setup.ts +4 -0
  58. package/src/config/model-profile-activation.ts +15 -3
  59. package/src/config/model-profiles.ts +255 -56
  60. package/src/config/model-resolver.ts +9 -6
  61. package/src/config/models-config-schema.ts +2 -0
  62. package/src/config/settings-schema.ts +6 -3
  63. package/src/coordinator/contract.ts +1 -0
  64. package/src/coordinator-mcp/server.ts +427 -193
  65. package/src/cursor.ts +46 -4
  66. package/src/defaults/gjc/skills/team/SKILL.md +3 -2
  67. package/src/defaults/gjc/skills/ultragoal/SKILL.md +8 -2
  68. package/src/export/html/index.ts +13 -9
  69. package/src/gjc-runtime/launch-worktree.ts +12 -1
  70. package/src/gjc-runtime/session-state-sidecar.ts +38 -0
  71. package/src/gjc-runtime/team-runtime.ts +33 -7
  72. package/src/gjc-runtime/tmux-common.ts +15 -0
  73. package/src/gjc-runtime/tmux-sessions.ts +19 -11
  74. package/src/gjc-runtime/ultragoal-runtime.ts +505 -41
  75. package/src/gjc-runtime/workflow-manifest.generated.json +27 -1
  76. package/src/gjc-runtime/workflow-manifest.ts +16 -1
  77. package/src/harness-control-plane/finalize.ts +39 -5
  78. package/src/harness-control-plane/owner.ts +87 -28
  79. package/src/harness-control-plane/phase-rollup.ts +96 -0
  80. package/src/harness-control-plane/receipt-ingest.ts +127 -0
  81. package/src/harness-control-plane/receipt-spool.ts +128 -0
  82. package/src/harness-control-plane/receipts.ts +229 -1
  83. package/src/harness-control-plane/rpc-adapter.ts +8 -0
  84. package/src/harness-control-plane/state-machine.ts +27 -6
  85. package/src/harness-control-plane/storage.ts +23 -0
  86. package/src/harness-control-plane/types.ts +33 -1
  87. package/src/hindsight/mental-models.ts +17 -16
  88. package/src/internal-urls/docs-index.generated.ts +8 -7
  89. package/src/main.ts +7 -3
  90. package/src/modes/components/assistant-message.ts +26 -14
  91. package/src/modes/components/diff.ts +97 -0
  92. package/src/modes/components/model-selector.ts +353 -181
  93. package/src/modes/components/status-line.ts +6 -6
  94. package/src/modes/components/tool-execution.ts +30 -13
  95. package/src/modes/controllers/event-controller.ts +5 -4
  96. package/src/modes/controllers/selector-controller.ts +33 -42
  97. package/src/modes/interactive-mode.ts +4 -5
  98. package/src/modes/print-mode.ts +1 -1
  99. package/src/modes/rpc/rpc-client.ts +3 -2
  100. package/src/modes/rpc/rpc-mode.ts +44 -14
  101. package/src/modes/rpc/rpc-types.ts +5 -2
  102. package/src/modes/shared/agent-wire/command-dispatch.ts +10 -5
  103. package/src/modes/shared/agent-wire/command-validation.ts +11 -0
  104. package/src/modes/theme/theme.ts +2 -2
  105. package/src/modes/utils/abort-message.ts +41 -0
  106. package/src/modes/utils/context-usage.ts +15 -8
  107. package/src/modes/utils/ui-helpers.ts +5 -6
  108. package/src/sdk.ts +38 -6
  109. package/src/secrets/obfuscator.ts +102 -27
  110. package/src/session/agent-session.ts +121 -25
  111. package/src/session/blob-store.ts +89 -3
  112. package/src/session/session-manager.ts +328 -57
  113. package/src/session/streaming-output.ts +185 -122
  114. package/src/session/tool-choice-queue.ts +23 -0
  115. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -2
  116. package/src/setup/hermes-setup.ts +63 -8
  117. package/src/task/executor.ts +69 -6
  118. package/src/task/fork-context-advisory.ts +99 -0
  119. package/src/task/index.ts +31 -2
  120. package/src/task/receipt.ts +7 -0
  121. package/src/task/render.ts +21 -1
  122. package/src/task/roi-reconciliation.ts +90 -0
  123. package/src/task/types.ts +15 -0
  124. package/src/thinking-metadata.ts +51 -0
  125. package/src/thinking.ts +26 -46
  126. package/src/tools/bash.ts +1 -1
  127. package/src/tools/index.ts +4 -2
  128. package/src/tools/resolve.ts +93 -18
  129. package/src/tools/subagent-render.ts +10 -1
  130. package/src/utils/edit-mode.ts +1 -1
  131. package/src/utils/title-generator.ts +16 -2
  132. package/src/utils/tool-choice.ts +45 -16
@@ -18,7 +18,9 @@ function writeText(lines: string[]): void {
18
18
  function writeJsonFailure(error: unknown): void {
19
19
  const message = error instanceof Error ? error.message : String(error);
20
20
  const [reason = "session_error"] = message.split(":");
21
- writeJson({ ok: false, reason });
21
+ const hintIndex = message.indexOf(" — ");
22
+ const detail = hintIndex >= 0 ? message.slice(hintIndex + " — ".length).trim() : "";
23
+ writeJson(detail ? { ok: false, reason, detail } : { ok: false, reason });
22
24
  }
23
25
 
24
26
  interface SessionJsonDto {
@@ -28,6 +28,8 @@ export default class Setup extends Command {
28
28
  repo: Flags.string({ description: "Hermes MCP repo namespace" }),
29
29
  profile: Flags.string({ description: "Hermes MCP profile namespace" }),
30
30
  "session-command": Flags.string({ description: "Explicit GJC session command for Hermes to launch" }),
31
+ "no-worktree": Flags.boolean({ description: "Disable default GJC --worktree isolation for Hermes sessions" }),
32
+ "worktree-name": Flags.string({ description: "Named GJC --worktree branch for Hermes sessions" }),
31
33
  "state-root": Flags.string({ description: "Hermes MCP coordination state root" }),
32
34
  mutation: Flags.string({
33
35
  description: "Hermes MCP mutation classes: sessions,questions,reports,all",
@@ -68,6 +70,8 @@ export default class Setup extends Command {
68
70
  repo: flags.repo,
69
71
  profile: flags.profile,
70
72
  sessionCommand: flags["session-command"],
73
+ noWorktree: flags["no-worktree"],
74
+ worktreeName: flags["worktree-name"],
71
75
  stateRoot: flags["state-root"],
72
76
  mutation: flags.mutation,
73
77
  artifactByteCap: flags["artifact-byte-cap"],
@@ -1,6 +1,7 @@
1
1
  import type { ThinkingLevel } from "@gajae-code/agent-core";
2
2
  import type { Api, Model } from "@gajae-code/ai";
3
3
  import type { AgentSession } from "../session/agent-session";
4
+ import { formatClampedModelSelector } from "../thinking";
4
5
  import {
5
6
  aggregateModelProfileRequiredProviders,
6
7
  formatAvailableProfileNames,
@@ -10,8 +11,14 @@ import { type GjcModelAssignmentTargetId, isAuthenticated, type ModelRegistry }
10
11
  import { resolveModelRoleValue } from "./model-resolver";
11
12
  import type { Settings } from "./settings";
12
13
 
14
+ type ModelProfileActivationSession = Pick<AgentSession, "model" | "thinkingLevel" | "sessionId"> & {
15
+ setModelTemporary?: AgentSession["setModelTemporary"];
16
+ setActiveModelProfile?: (name: string | undefined) => void;
17
+ getActiveModelProfile?: () => string | undefined;
18
+ };
19
+
13
20
  export interface PrepareModelProfileActivationOptions {
14
- session: Pick<AgentSession, "model" | "thinkingLevel" | "sessionId">;
21
+ session: ModelProfileActivationSession;
15
22
  modelRegistry: Pick<
16
23
  ModelRegistry,
17
24
  | "getModelProfile"
@@ -29,7 +36,7 @@ export interface PrepareModelProfileActivationOptions {
29
36
 
30
37
  export interface PreparedModelProfileActivation {
31
38
  profileName: string;
32
- session: Pick<AgentSession, "model" | "thinkingLevel" | "sessionId" | "setModelTemporary">;
39
+ session: ModelProfileActivationSession & { setModelTemporary: AgentSession["setModelTemporary"] };
33
40
  settings: Pick<Settings, "get" | "override" | "set" | "flush">;
34
41
  previousModel: Model<Api> | undefined;
35
42
  previousThinkingLevel: ThinkingLevel | undefined;
@@ -37,6 +44,7 @@ export interface PreparedModelProfileActivation {
37
44
  defaultModel: Model<Api> | undefined;
38
45
  defaultThinkingLevel: ThinkingLevel | undefined;
39
46
  agentModelOverrides: Record<string, string>;
47
+ previousActiveModelProfile: string | undefined;
40
48
  }
41
49
 
42
50
  export function formatModelProfileCredentialError(profileName: string, providers: readonly string[]): string {
@@ -89,7 +97,7 @@ export async function prepareModelProfileActivation(
89
97
  if (!resolved.model) {
90
98
  throw new Error(`Model profile "${options.profileName}" ${role} selector did not resolve: ${selector}`);
91
99
  }
92
- agentModelOverrides[role] = selector;
100
+ agentModelOverrides[role] = formatClampedModelSelector(selector, resolved.model);
93
101
  }
94
102
 
95
103
  return {
@@ -102,6 +110,7 @@ export async function prepareModelProfileActivation(
102
110
  defaultModel: resolvedDefault?.model,
103
111
  defaultThinkingLevel: resolvedDefault?.thinkingLevel,
104
112
  agentModelOverrides,
113
+ previousActiveModelProfile: options.session.getActiveModelProfile?.(),
105
114
  };
106
115
  }
107
116
 
@@ -113,6 +122,7 @@ export async function applyPreparedModelProfileActivation(
113
122
  const previousThinkingLevel = prepared.previousThinkingLevel;
114
123
  const previousAgentModelOverrides = prepared.previousAgentModelOverrides;
115
124
  const previousPersistedDefault = prepared.settings.get("modelProfile.default");
125
+ const previousActiveModelProfile = prepared.previousActiveModelProfile;
116
126
  let modelChanged = false;
117
127
  let overridesChanged = false;
118
128
  let defaultChanged = false;
@@ -134,6 +144,7 @@ export async function applyPreparedModelProfileActivation(
134
144
  defaultChanged = true;
135
145
  await prepared.settings.flush();
136
146
  }
147
+ prepared.session.setActiveModelProfile?.(prepared.profileName);
137
148
  } catch (error) {
138
149
  if (defaultChanged) {
139
150
  prepared.settings.set("modelProfile.default", previousPersistedDefault);
@@ -141,6 +152,7 @@ export async function applyPreparedModelProfileActivation(
141
152
  if (overridesChanged) {
142
153
  prepared.settings.override("task.agentModelOverrides", previousAgentModelOverrides);
143
154
  }
155
+ prepared.session.setActiveModelProfile?.(previousActiveModelProfile);
144
156
  if (modelChanged && previousModel) {
145
157
  await prepared.session.setModelTemporary(previousModel, previousThinkingLevel);
146
158
  }
@@ -54,71 +54,270 @@ const profile = (
54
54
  });
55
55
 
56
56
  export const BUILTIN_MODEL_PROFILES: readonly ModelProfileDefinition[] = [
57
- profile("opencode-go-eco", ["opencode-go"], {
58
- default: "opencode-go/deepseek-v4-flash",
59
- executor: "opencode-go/qwen3.5-plus",
60
- architect: "opencode-go/glm-5",
61
- planner: "opencode-go/minimax-m2.5",
62
- critic: "opencode-go/kimi-k2.5",
63
- }),
64
- profile("opencode-go-standard", ["opencode-go"], {
65
- default: "opencode-go/kimi-k2.6",
66
- executor: "opencode-go/qwen3.6-plus",
67
- architect: "opencode-go/glm-5.1",
68
- planner: "opencode-go/minimax-m2.7",
69
- critic: "opencode-go/deepseek-v4-pro",
70
- }),
71
- profile("opencode-go-pro", ["opencode-go"], {
72
- default: "opencode-go/qwen3.7-max",
73
- executor: "opencode-go/kimi-k2.6",
74
- architect: "opencode-go/deepseek-v4-pro:high",
75
- planner: "opencode-go/glm-5.1:high",
76
- critic: "opencode-go/minimax-m2.7:high",
77
- }),
78
57
  profile("codex-eco", ["openai-codex"], {
79
- default: "openai-codex/gpt-5.4-mini",
80
- executor: "openai-codex/gpt-5.4-nano",
81
- architect: "openai-codex/gpt-5.4-mini",
82
- planner: "openai-codex/gpt-5.4-mini",
83
- critic: "openai-codex/gpt-5.4-mini",
84
- }),
85
- profile("codex-standard", ["openai-codex"], {
86
- default: "openai-codex/gpt-5.4:medium",
87
- executor: "openai-codex/gpt-5.4:low",
88
- architect: "openai-codex/gpt-5.4:xhigh",
89
- planner: "openai-codex/gpt-5.4:medium",
90
- critic: "openai-codex/gpt-5.4:high",
58
+ default: "openai-codex/gpt-5.5:low",
59
+ executor: "openai-codex/gpt-5.5:minimal",
60
+ planner: "openai-codex/gpt-5.5:low",
61
+ critic: "openai-codex/gpt-5.5:medium",
62
+ architect: "openai-codex/gpt-5.5:high",
63
+ }),
64
+ profile("codex-medium", ["openai-codex"], {
65
+ default: "openai-codex/gpt-5.5:medium",
66
+ executor: "openai-codex/gpt-5.5:low",
67
+ planner: "openai-codex/gpt-5.5:medium",
68
+ critic: "openai-codex/gpt-5.5:high",
69
+ architect: "openai-codex/gpt-5.5:xhigh",
91
70
  }),
92
71
  profile("codex-pro", ["openai-codex"], {
93
- default: "openai-codex/gpt-5.5",
94
- executor: "openai-codex/gpt-5.2-codex",
95
- architect: "openai-codex/gpt-5.1-codex-max:high",
72
+ default: "openai-codex/gpt-5.5:xhigh",
73
+ executor: "openai-codex/gpt-5.5:medium",
96
74
  planner: "openai-codex/gpt-5.5:high",
97
- critic: "openai-codex/gpt-5.3-codex-spark:high",
75
+ critic: "openai-codex/gpt-5.5:xhigh",
76
+ architect: "openai-codex/gpt-5.5:xhigh",
98
77
  }),
99
- profile("opencode-go-codex-eco", ["opencode-go", "openai-codex"], {
100
- default: "opencode-go/deepseek-v4-flash",
101
- executor: "opencode-go/qwen3.5-plus",
102
- architect: "openai-codex/gpt-5.4-mini",
103
- planner: "openai-codex/gpt-5.4-mini",
104
- critic: "openai-codex/gpt-5.4-mini",
105
- }),
106
- profile("opencode-go-codex-standard", ["opencode-go", "openai-codex"], {
78
+ profile("opencodego", ["opencode-go"], {
107
79
  default: "opencode-go/kimi-k2.6",
108
- executor: "opencode-go/qwen3.6-plus",
109
- architect: "openai-codex/gpt-5.4",
110
- planner: "openai-codex/gpt-5.4",
111
- critic: "openai-codex/gpt-5.4",
112
- }),
113
- profile("opencode-go-codex-pro", ["opencode-go", "openai-codex"], {
114
- default: "opencode-go/qwen3.7-max",
115
- executor: "opencode-go/kimi-k2.6",
116
- architect: "openai-codex/gpt-5.1-codex-max:high",
117
- planner: "openai-codex/gpt-5.5:high",
118
- critic: "openai-codex/gpt-5.3-codex-spark:high",
80
+ executor: "opencode-go/deepseek-v4-flash",
81
+ planner: "opencode-go/qwen3.7-max",
82
+ critic: "opencode-go/mimo-v2.5-pro",
83
+ architect: "opencode-go/deepseek-v4-pro",
84
+ }),
85
+ profile("claude-opus", ["anthropic"], {
86
+ default: "anthropic/claude-opus-4-8:xhigh",
87
+ executor: "anthropic/claude-sonnet-4-6",
88
+ planner: "anthropic/claude-opus-4-8:low",
89
+ critic: "anthropic/claude-opus-4-8:high",
90
+ architect: "anthropic/claude-opus-4-8:xhigh",
91
+ }),
92
+ profile("glm-eco", ["zai"], {
93
+ default: "zai/glm-5.1:low",
94
+ executor: "zai/glm-5.1:minimal",
95
+ planner: "zai/glm-5.1:low",
96
+ critic: "zai/glm-5.1:medium",
97
+ architect: "zai/glm-5.1:high",
98
+ }),
99
+ profile("glm-medium", ["zai"], {
100
+ default: "zai/glm-5.1:medium",
101
+ executor: "zai/glm-5.1:low",
102
+ planner: "zai/glm-5.1:medium",
103
+ critic: "zai/glm-5.1:high",
104
+ architect: "zai/glm-5.1:xhigh",
105
+ }),
106
+ profile("glm-pro", ["zai"], {
107
+ default: "zai/glm-5.1:xhigh",
108
+ executor: "zai/glm-5.1:medium",
109
+ planner: "zai/glm-5.1:high",
110
+ critic: "zai/glm-5.1:xhigh",
111
+ architect: "zai/glm-5.1:xhigh",
112
+ }),
113
+ profile("kimi-coding-plan-eco", ["kimi-code"], {
114
+ default: "kimi-code/kimi-k2.7-code:low",
115
+ executor: "kimi-code/kimi-k2.7-code:minimal",
116
+ planner: "kimi-code/kimi-k2.7-code:low",
117
+ critic: "kimi-code/kimi-k2.7-code:medium",
118
+ architect: "kimi-code/kimi-k2.7-code:high",
119
+ }),
120
+ profile("kimi-coding-plan-medium", ["kimi-code"], {
121
+ default: "kimi-code/kimi-k2.7-code:medium",
122
+ executor: "kimi-code/kimi-k2.7-code:low",
123
+ planner: "kimi-code/kimi-k2.7-code:medium",
124
+ critic: "kimi-code/kimi-k2.7-code:high",
125
+ architect: "kimi-code/kimi-k2.7-code:xhigh",
126
+ }),
127
+ profile("kimi-coding-plan-pro", ["kimi-code"], {
128
+ default: "kimi-code/kimi-k2.7-code:xhigh",
129
+ executor: "kimi-code/kimi-k2.7-code:medium",
130
+ planner: "kimi-code/kimi-k2.7-code:high",
131
+ critic: "kimi-code/kimi-k2.7-code:xhigh",
132
+ architect: "kimi-code/kimi-k2.7-code:xhigh",
133
+ }),
134
+ profile("mimo-eco", ["xiaomi"], {
135
+ default: "xiaomi/mimo-v2.5-pro:low",
136
+ executor: "xiaomi/mimo-v2.5-pro:minimal",
137
+ planner: "xiaomi/mimo-v2.5-pro:low",
138
+ critic: "xiaomi/mimo-v2.5-pro:medium",
139
+ architect: "xiaomi/mimo-v2.5-pro:high",
140
+ }),
141
+ profile("mimo-medium", ["xiaomi"], {
142
+ default: "xiaomi/mimo-v2.5-pro:medium",
143
+ executor: "xiaomi/mimo-v2.5-pro:low",
144
+ planner: "xiaomi/mimo-v2.5-pro:medium",
145
+ critic: "xiaomi/mimo-v2.5-pro:high",
146
+ architect: "xiaomi/mimo-v2.5-pro:xhigh",
147
+ }),
148
+ profile("mimo-pro", ["xiaomi"], {
149
+ default: "xiaomi/mimo-v2.5-pro:xhigh",
150
+ executor: "xiaomi/mimo-v2.5-pro:medium",
151
+ planner: "xiaomi/mimo-v2.5-pro:high",
152
+ critic: "xiaomi/mimo-v2.5-pro:xhigh",
153
+ architect: "xiaomi/mimo-v2.5-pro:xhigh",
154
+ }),
155
+ profile("grok-eco", ["xai"], {
156
+ default: "xai/grok-4.3:low",
157
+ executor: "xai/grok-4.3:minimal",
158
+ planner: "xai/grok-4.3:low",
159
+ critic: "xai/grok-4.3:medium",
160
+ architect: "xai/grok-4.3:high",
161
+ }),
162
+ profile("grok-medium", ["xai"], {
163
+ default: "xai/grok-4.3:medium",
164
+ executor: "xai/grok-4.3:low",
165
+ planner: "xai/grok-4.3:medium",
166
+ critic: "xai/grok-4.3:high",
167
+ architect: "xai/grok-4.3:xhigh",
168
+ }),
169
+ profile("grok-pro", ["xai"], {
170
+ default: "xai/grok-4.3:xhigh",
171
+ executor: "xai/grok-4.3:medium",
172
+ planner: "xai/grok-4.3:high",
173
+ critic: "xai/grok-4.3:xhigh",
174
+ architect: "xai/grok-4.3:xhigh",
175
+ }),
176
+ profile("cursor-eco", ["cursor"], {
177
+ default: "cursor/composer-1.5:low",
178
+ executor: "cursor/composer-1.5:minimal",
179
+ planner: "cursor/composer-1.5:low",
180
+ critic: "cursor/composer-1.5:medium",
181
+ architect: "cursor/composer-1.5:high",
182
+ }),
183
+ profile("cursor-medium", ["cursor"], {
184
+ default: "cursor/composer-1.5:medium",
185
+ executor: "cursor/composer-1.5:low",
186
+ planner: "cursor/composer-1.5:medium",
187
+ critic: "cursor/composer-1.5:high",
188
+ architect: "cursor/composer-1.5:xhigh",
119
189
  }),
190
+ profile("cursor-pro", ["cursor"], {
191
+ default: "cursor/composer-1.5:xhigh",
192
+ executor: "cursor/composer-1.5:medium",
193
+ planner: "cursor/composer-1.5:high",
194
+ critic: "cursor/composer-1.5:xhigh",
195
+ architect: "cursor/composer-1.5:xhigh",
196
+ }),
197
+ profile("minimax-eco", ["minimax-code"], {
198
+ default: "minimax-code/minimax-v3:low",
199
+ executor: "minimax-code/minimax-v3:minimal",
200
+ planner: "minimax-code/minimax-v3:low",
201
+ critic: "minimax-code/minimax-v3:medium",
202
+ architect: "minimax-code/minimax-v3:high",
203
+ }),
204
+ profile("minimax-medium", ["minimax-code"], {
205
+ default: "minimax-code/minimax-v3:medium",
206
+ executor: "minimax-code/minimax-v3:low",
207
+ planner: "minimax-code/minimax-v3:medium",
208
+ critic: "minimax-code/minimax-v3:high",
209
+ architect: "minimax-code/minimax-v3:xhigh",
210
+ }),
211
+ profile("minimax-pro", ["minimax-code"], {
212
+ default: "minimax-code/minimax-v3:xhigh",
213
+ executor: "minimax-code/minimax-v3:medium",
214
+ planner: "minimax-code/minimax-v3:high",
215
+ critic: "minimax-code/minimax-v3:xhigh",
216
+ architect: "minimax-code/minimax-v3:xhigh",
217
+ }),
218
+ profile("opus-codex", ["anthropic", "openai-codex"], {
219
+ default: "anthropic/claude-opus-4-8:xhigh",
220
+ executor: "openai-codex/gpt-5.5:low",
221
+ planner: "openai-codex/gpt-5.5:medium",
222
+ critic: "openai-codex/gpt-5.5:high",
223
+ architect: "openai-codex/gpt-5.5:xhigh",
224
+ }),
225
+ profile("codex-opencodego", ["openai-codex", "opencode-go"], {
226
+ default: "openai-codex/gpt-5.5:medium",
227
+ executor: "opencode-go/deepseek-v4-pro",
228
+ planner: "opencode-go/kimi-k2.6",
229
+ critic: "opencode-go/mimo-v2.5-pro",
230
+ architect: "openai-codex/gpt-5.5:xhigh",
231
+ }),
232
+ ];
233
+
234
+ export interface ModelProfilePresentation {
235
+ displayName: string;
236
+ providerGroup: string;
237
+ }
238
+
239
+ const PROFILE_PRESENTATION: Record<string, ModelProfilePresentation> = {
240
+ "codex-eco": { displayName: "Codex Eco", providerGroup: "CODEX" },
241
+ "codex-medium": { displayName: "Codex Medium", providerGroup: "CODEX" },
242
+ "codex-pro": { displayName: "Codex Pro", providerGroup: "CODEX" },
243
+ opencodego: { displayName: "OpenCodeGo", providerGroup: "OPENCODEGO" },
244
+ "claude-opus": { displayName: "Claude Opus", providerGroup: "CLAUDE" },
245
+ "glm-eco": { displayName: "GLM Eco", providerGroup: "GLM" },
246
+ "glm-medium": { displayName: "GLM Medium", providerGroup: "GLM" },
247
+ "glm-pro": { displayName: "GLM Pro", providerGroup: "GLM" },
248
+ "kimi-coding-plan-eco": { displayName: "Kimi Coding Plan Eco", providerGroup: "KIMI CODING PLAN" },
249
+ "kimi-coding-plan-medium": { displayName: "Kimi Coding Plan Medium", providerGroup: "KIMI CODING PLAN" },
250
+ "kimi-coding-plan-pro": { displayName: "Kimi Coding Plan Pro", providerGroup: "KIMI CODING PLAN" },
251
+ "mimo-eco": { displayName: "Mimo Eco", providerGroup: "MIMO" },
252
+ "mimo-medium": { displayName: "Mimo Medium", providerGroup: "MIMO" },
253
+ "mimo-pro": { displayName: "Mimo Pro", providerGroup: "MIMO" },
254
+ "grok-eco": { displayName: "Grok Eco", providerGroup: "GROK" },
255
+ "grok-medium": { displayName: "Grok Medium", providerGroup: "GROK" },
256
+ "grok-pro": { displayName: "Grok Pro", providerGroup: "GROK" },
257
+ "cursor-eco": { displayName: "Cursor Eco", providerGroup: "CURSOR" },
258
+ "cursor-medium": { displayName: "Cursor Medium", providerGroup: "CURSOR" },
259
+ "cursor-pro": { displayName: "Cursor Pro", providerGroup: "CURSOR" },
260
+ "minimax-eco": { displayName: "MiniMax Eco", providerGroup: "MINIMAX" },
261
+ "minimax-medium": { displayName: "MiniMax Medium", providerGroup: "MINIMAX" },
262
+ "minimax-pro": { displayName: "MiniMax Pro", providerGroup: "MINIMAX" },
263
+ "opus-codex": { displayName: "Opus + Codex", providerGroup: "COMBOS" },
264
+ "codex-opencodego": { displayName: "Codex + OpenCodeGo", providerGroup: "COMBOS" },
265
+ };
266
+
267
+ const PROFILE_GROUP_ORDER = [
268
+ "CODEX",
269
+ "OPENCODEGO",
270
+ "CLAUDE",
271
+ "GLM",
272
+ "KIMI CODING PLAN",
273
+ "MIMO",
274
+ "GROK",
275
+ "CURSOR",
276
+ "MINIMAX",
277
+ "COMBOS",
120
278
  ];
121
279
 
280
+ const PROFILE_RECOMMENDATIONS: Record<string, string> = {
281
+ "openai-codex": "codex-medium",
282
+ anthropic: "claude-opus",
283
+ "opencode-go": "opencodego",
284
+ zai: "glm-medium",
285
+ "kimi-code": "kimi-coding-plan-medium",
286
+ xiaomi: "mimo-medium",
287
+ xai: "grok-medium",
288
+ cursor: "cursor-medium",
289
+ "minimax-code": "minimax-medium",
290
+ };
291
+
292
+ export function getModelProfilePresentation(name: string): ModelProfilePresentation {
293
+ return PROFILE_PRESENTATION[name] ?? { displayName: name, providerGroup: "COMBOS" };
294
+ }
295
+
296
+ export function groupModelProfilesForPresetLanding(
297
+ profiles: ReadonlyMap<string, ModelProfileDefinition>,
298
+ ): Map<string, ModelProfileDefinition[]> {
299
+ const groups = new Map<string, ModelProfileDefinition[]>();
300
+ for (const group of PROFILE_GROUP_ORDER) groups.set(group, []);
301
+ for (const profile of profiles.values()) {
302
+ const group = getModelProfilePresentation(profile.name).providerGroup;
303
+ if (!groups.has(group)) groups.set(group, []);
304
+ groups.get(group)?.push(profile);
305
+ }
306
+ for (const [group, entries] of groups) {
307
+ if (entries.length === 0) groups.delete(group);
308
+ else entries.sort((a, b) => a.name.localeCompare(b.name));
309
+ }
310
+ return groups;
311
+ }
312
+
313
+ export function recommendModelProfileForProvider(
314
+ providerId: string,
315
+ profiles: ReadonlyMap<string, ModelProfileDefinition>,
316
+ ): ModelProfileDefinition | undefined {
317
+ const recommended = PROFILE_RECOMMENDATIONS[providerId];
318
+ return recommended ? profiles.get(recommended) : undefined;
319
+ }
320
+
122
321
  export function mergeModelProfiles(userProfiles?: ModelsConfig["profiles"]): Map<string, ModelProfileDefinition> {
123
322
  const profiles = new Map<string, ModelProfileDefinition>();
124
323
  for (const definition of BUILTIN_MODEL_PROFILES) {
@@ -776,30 +776,33 @@ export async function resolveModelOverrideWithAuthFallback(
776
776
  thinkingLevel?: ThinkingLevel;
777
777
  explicitThinkingLevel: boolean;
778
778
  authFallbackUsed: boolean;
779
+ requestedModel?: Model<Api>;
780
+ fallbackReason?: "auth_unavailable";
779
781
  }> {
780
782
  const primary = resolveModelOverride(modelPatterns, modelRegistry, settings);
783
+ const unchanged = { ...primary, requestedModel: primary.model, authFallbackUsed: false };
781
784
  if (!primary.model || !parentActiveModelPattern) {
782
- return { ...primary, authFallbackUsed: false };
785
+ return unchanged;
783
786
  }
784
787
 
785
788
  const primaryKey = await modelRegistry.getApiKey(primary.model, sessionId);
786
789
  if (primaryKey === kNoAuth || isAuthenticated(primaryKey)) {
787
- return { ...primary, authFallbackUsed: false };
790
+ return unchanged;
788
791
  }
789
792
 
790
793
  const fallback = resolveModelOverride([parentActiveModelPattern], modelRegistry, settings);
791
794
  if (!fallback.model) {
792
- return { ...primary, authFallbackUsed: false };
795
+ return unchanged;
793
796
  }
794
797
  if (modelsAreEqual(fallback.model, primary.model)) {
795
- return { ...primary, authFallbackUsed: false };
798
+ return unchanged;
796
799
  }
797
800
  const fallbackKey = await modelRegistry.getApiKey(fallback.model, sessionId);
798
801
  if (!isAuthenticated(fallbackKey)) {
799
- return { ...primary, authFallbackUsed: false };
802
+ return unchanged;
800
803
  }
801
804
 
802
- return { ...fallback, authFallbackUsed: true };
805
+ return { ...fallback, requestedModel: primary.model, authFallbackUsed: true, fallbackReason: "auth_unavailable" };
803
806
  }
804
807
 
805
808
  /**
@@ -36,6 +36,8 @@ export const OpenAICompatSchema = z.object({
36
36
  allowsSyntheticReasoningContentForToolCalls: z.boolean().optional(),
37
37
  requiresAssistantContentForToolCalls: z.boolean().optional(),
38
38
  supportsToolChoice: z.boolean().optional(),
39
+ supportsForcedToolChoice: z.boolean().optional(),
40
+ toolChoiceSupport: z.enum(["none", "auto", "required", "named"]).optional(),
39
41
  disableReasoningOnForcedToolChoice: z.boolean().optional(),
40
42
  disableReasoningOnToolChoice: z.boolean().optional(),
41
43
  thinkingFormat: z.enum(["openai", "openrouter", "zai", "qwen", "qwen-chat-template"]).optional(),
@@ -1,7 +1,10 @@
1
- import { THINKING_EFFORTS } from "@gajae-code/ai/model-thinking";
1
+ import type { Effort } from "@gajae-code/ai/model-thinking";
2
2
  import { TASK_SIMPLE_MODES } from "../task/simple-mode";
3
- import { getThinkingLevelMetadata } from "../thinking";
3
+ import { getThinkingLevelMetadata } from "../thinking-metadata";
4
4
  import { EDIT_MODES } from "../utils/edit-mode";
5
+
6
+ const THINKING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh", "max"] as readonly Effort[];
7
+
5
8
  import {
6
9
  DEFAULT_DISABLED_EXTENSIONS,
7
10
  DEFAULT_SKILL_DISCOVERY_SETTINGS,
@@ -665,7 +668,7 @@ export const SETTINGS_SCHEMA = {
665
668
  defaultThinkingLevel: {
666
669
  type: "enum",
667
670
  values: THINKING_EFFORTS,
668
- default: "high",
671
+ default: THINKING_EFFORTS[3],
669
672
  ui: {
670
673
  tab: "model",
671
674
  label: "Thinking Level",
@@ -9,6 +9,7 @@ export const COORDINATOR_MCP_TOOL_NAMES = [
9
9
  "gjc_coordinator_list_artifacts",
10
10
  "gjc_coordinator_read_artifact",
11
11
  "gjc_coordinator_read_coordination_status",
12
+ "gjc_coordinator_register_session",
12
13
  "gjc_coordinator_start_session",
13
14
  "gjc_coordinator_send_prompt",
14
15
  "gjc_coordinator_submit_question_answer",