@gajae-code/coding-agent 0.4.5 → 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.
- package/CHANGELOG.md +43 -0
- package/dist/types/commands/harness.d.ts +3 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -2
- package/dist/types/config/model-profiles.d.ts +7 -0
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +30 -0
- package/dist/types/config/settings-schema.d.ts +4 -3
- package/dist/types/gjc-runtime/team-runtime.d.ts +0 -1
- package/dist/types/gjc-runtime/tmux-common.d.ts +3 -0
- package/dist/types/harness-control-plane/owner.d.ts +1 -1
- package/dist/types/harness-control-plane/receipt-spool.d.ts +19 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +6 -1
- package/dist/types/harness-control-plane/types.d.ts +4 -0
- package/dist/types/hindsight/mental-models.d.ts +5 -5
- package/dist/types/modes/components/model-selector.d.ts +1 -12
- package/dist/types/modes/rpc/rpc-client.d.ts +2 -2
- package/dist/types/modes/rpc/rpc-types.d.ts +4 -1
- package/dist/types/sdk.d.ts +5 -0
- package/dist/types/session/agent-session.d.ts +2 -0
- package/dist/types/session/blob-store.d.ts +20 -1
- package/dist/types/session/session-manager.d.ts +24 -6
- package/dist/types/session/streaming-output.d.ts +3 -2
- package/dist/types/session/tool-choice-queue.d.ts +6 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +7 -0
- package/dist/types/thinking-metadata.d.ts +16 -0
- package/dist/types/thinking.d.ts +3 -12
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resolve.d.ts +0 -10
- package/dist/types/utils/tool-choice.d.ts +14 -1
- package/package.json +7 -7
- package/src/cli.ts +8 -4
- package/src/commands/harness.ts +36 -2
- package/src/commands/launch.ts +2 -2
- package/src/commands/session.ts +3 -1
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +255 -56
- package/src/config/model-resolver.ts +9 -6
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +6 -3
- package/src/coordinator-mcp/server.ts +54 -23
- package/src/cursor.ts +16 -2
- package/src/defaults/gjc/skills/team/SKILL.md +3 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +8 -2
- package/src/export/html/index.ts +13 -9
- package/src/gjc-runtime/team-runtime.ts +33 -7
- package/src/gjc-runtime/tmux-common.ts +15 -0
- package/src/gjc-runtime/tmux-sessions.ts +19 -11
- package/src/gjc-runtime/ultragoal-runtime.ts +505 -41
- package/src/gjc-runtime/workflow-manifest.generated.json +27 -1
- package/src/gjc-runtime/workflow-manifest.ts +16 -1
- package/src/harness-control-plane/owner.ts +78 -27
- package/src/harness-control-plane/receipt-spool.ts +128 -0
- package/src/harness-control-plane/state-machine.ts +27 -6
- package/src/harness-control-plane/storage.ts +23 -0
- package/src/harness-control-plane/types.ts +4 -0
- package/src/hindsight/mental-models.ts +17 -16
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/modes/components/assistant-message.ts +26 -14
- package/src/modes/components/diff.ts +97 -0
- package/src/modes/components/model-selector.ts +353 -181
- package/src/modes/components/tool-execution.ts +30 -13
- package/src/modes/controllers/selector-controller.ts +33 -42
- package/src/modes/rpc/rpc-client.ts +3 -2
- package/src/modes/rpc/rpc-mode.ts +44 -14
- package/src/modes/rpc/rpc-types.ts +5 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +10 -5
- package/src/modes/shared/agent-wire/command-validation.ts +11 -0
- package/src/sdk.ts +29 -2
- package/src/secrets/obfuscator.ts +102 -27
- package/src/session/agent-session.ts +105 -20
- package/src/session/blob-store.ts +89 -3
- package/src/session/session-manager.ts +309 -58
- package/src/session/streaming-output.ts +185 -122
- package/src/session/tool-choice-queue.ts +23 -0
- package/src/task/executor.ts +69 -6
- package/src/task/receipt.ts +5 -0
- package/src/task/render.ts +21 -1
- package/src/task/types.ts +8 -0
- package/src/thinking-metadata.ts +51 -0
- package/src/thinking.ts +26 -46
- package/src/tools/bash.ts +1 -1
- package/src/tools/index.ts +2 -0
- package/src/tools/resolve.ts +93 -18
- package/src/utils/edit-mode.ts +1 -1
- package/src/utils/tool-choice.ts +45 -16
|
@@ -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.
|
|
80
|
-
executor: "openai-codex/gpt-5.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}),
|
|
85
|
-
profile("codex-
|
|
86
|
-
default: "openai-codex/gpt-5.
|
|
87
|
-
executor: "openai-codex/gpt-5.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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.
|
|
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.
|
|
75
|
+
critic: "openai-codex/gpt-5.5:xhigh",
|
|
76
|
+
architect: "openai-codex/gpt-5.5:xhigh",
|
|
98
77
|
}),
|
|
99
|
-
profile("
|
|
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/
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}),
|
|
113
|
-
profile("
|
|
114
|
-
default: "
|
|
115
|
-
executor: "
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
|
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
|
|
790
|
+
return unchanged;
|
|
788
791
|
}
|
|
789
792
|
|
|
790
793
|
const fallback = resolveModelOverride([parentActiveModelPattern], modelRegistry, settings);
|
|
791
794
|
if (!fallback.model) {
|
|
792
|
-
return
|
|
795
|
+
return unchanged;
|
|
793
796
|
}
|
|
794
797
|
if (modelsAreEqual(fallback.model, primary.model)) {
|
|
795
|
-
return
|
|
798
|
+
return unchanged;
|
|
796
799
|
}
|
|
797
800
|
const fallbackKey = await modelRegistry.getApiKey(fallback.model, sessionId);
|
|
798
801
|
if (!isAuthenticated(fallbackKey)) {
|
|
799
|
-
return
|
|
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
|
/**
|
|
@@ -37,6 +37,7 @@ export const OpenAICompatSchema = z.object({
|
|
|
37
37
|
requiresAssistantContentForToolCalls: z.boolean().optional(),
|
|
38
38
|
supportsToolChoice: z.boolean().optional(),
|
|
39
39
|
supportsForcedToolChoice: z.boolean().optional(),
|
|
40
|
+
toolChoiceSupport: z.enum(["none", "auto", "required", "named"]).optional(),
|
|
40
41
|
disableReasoningOnForcedToolChoice: z.boolean().optional(),
|
|
41
42
|
disableReasoningOnToolChoice: z.boolean().optional(),
|
|
42
43
|
thinkingFormat: z.enum(["openai", "openrouter", "zai", "qwen", "qwen-chat-template"]).optional(),
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
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:
|
|
671
|
+
default: THINKING_EFFORTS[3],
|
|
669
672
|
ui: {
|
|
670
673
|
tab: "model",
|
|
671
674
|
label: "Thinking Level",
|
|
@@ -742,6 +742,7 @@ async function startTmuxSession(
|
|
|
742
742
|
config: CoordinatorMcpConfig,
|
|
743
743
|
input: SessionStartInput,
|
|
744
744
|
namespaceDir: string,
|
|
745
|
+
runner: CommandRunner = runCommand,
|
|
745
746
|
): Promise<Record<string, unknown>> {
|
|
746
747
|
if (!config.sessionCommand) throw new Error("coordinator_session_command_required");
|
|
747
748
|
const sessionName = `gjc-coordinator-${randomUUID().slice(0, 8)}`;
|
|
@@ -752,7 +753,7 @@ async function startTmuxSession(
|
|
|
752
753
|
`${GJC_COORDINATOR_SESSION_ID_ENV}=${shellQuote(sessionName)}`,
|
|
753
754
|
config.sessionCommand,
|
|
754
755
|
].join(" ");
|
|
755
|
-
const started = await
|
|
756
|
+
const started = await runner([
|
|
756
757
|
"tmux",
|
|
757
758
|
"new-session",
|
|
758
759
|
"-d",
|
|
@@ -767,9 +768,6 @@ async function startTmuxSession(
|
|
|
767
768
|
]);
|
|
768
769
|
if (started.exitCode !== 0) throw new Error(`coordinator_tmux_start_failed:${started.stderr || started.stdout}`);
|
|
769
770
|
const [tmuxTarget, paneId] = started.stdout.trim().split(/\s+/, 2);
|
|
770
|
-
const initialPromptTmuxKeysSent = input.prompt
|
|
771
|
-
? await sendTmuxPromptKeys(tmuxTarget || sessionName, input.prompt)
|
|
772
|
-
: false;
|
|
773
771
|
return {
|
|
774
772
|
sessionId: sessionName,
|
|
775
773
|
tmuxSession: sessionName,
|
|
@@ -779,7 +777,6 @@ async function startTmuxSession(
|
|
|
779
777
|
createdAt: new Date().toISOString(),
|
|
780
778
|
sessionCommand: config.sessionCommand,
|
|
781
779
|
runtimeStateFile,
|
|
782
|
-
initialPromptTmuxKeysSent,
|
|
783
780
|
};
|
|
784
781
|
}
|
|
785
782
|
|
|
@@ -964,27 +961,26 @@ export function createCoordinatorMcpServer(options: CoordinatorMcpServerOptions
|
|
|
964
961
|
}
|
|
965
962
|
|
|
966
963
|
async function activateTurn(session: Record<string, unknown>, turn: TurnRecord): Promise<TurnRecord> {
|
|
967
|
-
const tmuxKeysSent = await sendTmuxPrompt(session, turn.prompt.text, commandRunner);
|
|
968
964
|
const timestamp = new Date().toISOString();
|
|
969
965
|
const target = typeof session.tmux_target === "string" ? session.tmux_target : session.tmuxTarget;
|
|
970
966
|
const live = hasTmuxIdentity(session) ? await hasTmuxSession(session, commandRunner) : null;
|
|
971
|
-
const
|
|
967
|
+
const pendingTurn: TurnRecord = {
|
|
972
968
|
...turn,
|
|
973
969
|
status: "active",
|
|
974
970
|
delivery: {
|
|
975
971
|
delivered: false,
|
|
976
|
-
queued:
|
|
972
|
+
queued: true,
|
|
977
973
|
target: typeof target === "string" ? target : null,
|
|
978
|
-
tmux_keys_sent:
|
|
974
|
+
tmux_keys_sent: false,
|
|
979
975
|
prompt_acknowledged: false,
|
|
980
|
-
state:
|
|
976
|
+
state: "queued",
|
|
981
977
|
attempts: [
|
|
982
978
|
{
|
|
983
979
|
delivered: false,
|
|
984
|
-
tmux_keys_sent:
|
|
980
|
+
tmux_keys_sent: false,
|
|
985
981
|
channel: "tmux_keys",
|
|
986
982
|
created_at: timestamp,
|
|
987
|
-
reason:
|
|
983
|
+
reason: "awaiting_tmux_delivery",
|
|
988
984
|
},
|
|
989
985
|
],
|
|
990
986
|
},
|
|
@@ -992,13 +988,50 @@ export function createCoordinatorMcpServer(options: CoordinatorMcpServerOptions
|
|
|
992
988
|
started_at: turn.started_at ?? timestamp,
|
|
993
989
|
updated_at: timestamp,
|
|
994
990
|
};
|
|
995
|
-
await
|
|
996
|
-
await
|
|
997
|
-
|
|
991
|
+
await writeTurnRecord(namespaceDir, pendingTurn);
|
|
992
|
+
await writeActiveTurn(namespaceDir, pendingTurn);
|
|
993
|
+
await writeSessionState(namespaceDir, pendingTurn.session_id, "running", {
|
|
994
|
+
currentTurnId: pendingTurn.turn_id,
|
|
998
995
|
live,
|
|
999
|
-
reason:
|
|
996
|
+
reason: null,
|
|
1000
997
|
});
|
|
998
|
+
|
|
999
|
+
const tmuxKeysSent = await sendTmuxPrompt(session, turn.prompt.text, commandRunner);
|
|
1000
|
+
const deliveredAt = new Date().toISOString();
|
|
1001
|
+
const activeTurn: TurnRecord = {
|
|
1002
|
+
...pendingTurn,
|
|
1003
|
+
delivery: {
|
|
1004
|
+
delivered: false,
|
|
1005
|
+
queued: !tmuxKeysSent,
|
|
1006
|
+
target: typeof target === "string" ? target : null,
|
|
1007
|
+
tmux_keys_sent: tmuxKeysSent,
|
|
1008
|
+
prompt_acknowledged: false,
|
|
1009
|
+
state: tmuxKeysSent ? "tmux_keys_sent" : "unavailable",
|
|
1010
|
+
attempts: [
|
|
1011
|
+
{
|
|
1012
|
+
delivered: false,
|
|
1013
|
+
tmux_keys_sent: tmuxKeysSent,
|
|
1014
|
+
channel: "tmux_keys",
|
|
1015
|
+
created_at: deliveredAt,
|
|
1016
|
+
reason: tmuxKeysSent ? "awaiting_runtime_ack" : "tmux_delivery_unavailable",
|
|
1017
|
+
},
|
|
1018
|
+
],
|
|
1019
|
+
},
|
|
1020
|
+
updated_at: deliveredAt,
|
|
1021
|
+
};
|
|
1001
1022
|
await writeTurnRecord(namespaceDir, activeTurn);
|
|
1023
|
+
await writeActiveTurn(namespaceDir, activeTurn);
|
|
1024
|
+
const sessionState = await readSessionState(namespaceDir, activeTurn.session_id);
|
|
1025
|
+
const runtimeStateAlreadySettled =
|
|
1026
|
+
sessionState?.current_turn_id === activeTurn.turn_id &&
|
|
1027
|
+
(sessionState.state === "completed" || sessionState.state === "errored");
|
|
1028
|
+
if (!runtimeStateAlreadySettled) {
|
|
1029
|
+
await writeSessionState(namespaceDir, activeTurn.session_id, tmuxKeysSent ? "running" : "stale", {
|
|
1030
|
+
currentTurnId: activeTurn.turn_id,
|
|
1031
|
+
live,
|
|
1032
|
+
reason: tmuxKeysSent ? null : "tmux_delivery_unavailable",
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1002
1035
|
return activeTurn;
|
|
1003
1036
|
}
|
|
1004
1037
|
|
|
@@ -1149,18 +1182,16 @@ export function createCoordinatorMcpServer(options: CoordinatorMcpServerOptions
|
|
|
1149
1182
|
};
|
|
1150
1183
|
const started = services.startSession
|
|
1151
1184
|
? await services.startSession(input)
|
|
1152
|
-
: await startTmuxSession(config, input, namespaceDir);
|
|
1185
|
+
: await startTmuxSession(config, input, namespaceDir, commandRunner);
|
|
1153
1186
|
const startedRecord = asRecord(started);
|
|
1154
1187
|
if (!startedRecord) throw new Error("coordinator_session_command_required");
|
|
1155
1188
|
const session = normalizeSession(startedRecord);
|
|
1156
1189
|
await writeJsonFile(sessionFile(session.session_id), session);
|
|
1157
1190
|
const live = hasTmuxIdentity(session) ? await hasTmuxSession(session, commandRunner) : null;
|
|
1158
|
-
let sessionState = await writeSessionState(
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
{ live, reason: null },
|
|
1163
|
-
);
|
|
1191
|
+
let sessionState = await writeSessionState(namespaceDir, String(session.session_id), "ready_for_input", {
|
|
1192
|
+
live,
|
|
1193
|
+
reason: null,
|
|
1194
|
+
});
|
|
1164
1195
|
if (typeof args.prompt === "string" && args.prompt.length > 0) {
|
|
1165
1196
|
const turn = await activateTurn(
|
|
1166
1197
|
session,
|
package/src/cursor.ts
CHANGED
|
@@ -160,6 +160,20 @@ function formatMcpToolErrorMessage(toolName: string, availableTools: string[]):
|
|
|
160
160
|
return `MCP tool "${toolName}" not found. Available tools: ${list}`;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Cursor's wire protocol carries shell timeouts in milliseconds — the
|
|
165
|
+
* model-facing parameter is `block_until_ms`, and `ShellArgs.hard_timeout` is
|
|
166
|
+
* likewise documented in ms — while the bash tool's `timeout` is seconds.
|
|
167
|
+
* Passing the raw value through made a requested 30 s wait (30000 ms) arrive
|
|
168
|
+
* as 30000 s and clamp to the 3600 s ceiling, i.e. an accidental 1-hour
|
|
169
|
+
* timeout on a blocking command. Convert, rounding sub-second values up to 1 s
|
|
170
|
+
* so a tiny requested wait does not collapse to "no timeout".
|
|
171
|
+
*/
|
|
172
|
+
function shellTimeoutSeconds(timeout: number | undefined): number | undefined {
|
|
173
|
+
if (!timeout || timeout <= 0) return undefined;
|
|
174
|
+
return Math.max(1, Math.ceil(timeout / 1000));
|
|
175
|
+
}
|
|
176
|
+
|
|
163
177
|
export class CursorExecHandlers implements ICursorExecHandlers {
|
|
164
178
|
constructor(private options: CursorExecBridgeOptions) {
|
|
165
179
|
// Bind every native handler so methods stay instance-safe when invoked
|
|
@@ -240,7 +254,7 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
240
254
|
|
|
241
255
|
async shell(args: Parameters<NonNullable<ICursorExecHandlers["shell"]>>[0]) {
|
|
242
256
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
243
|
-
const timeoutSeconds = args.timeout
|
|
257
|
+
const timeoutSeconds = shellTimeoutSeconds(args.timeout);
|
|
244
258
|
const toolResultMessage = await executeTool(this.#optionsForCall(), "bash", toolCallId, {
|
|
245
259
|
command: args.command,
|
|
246
260
|
cwd: args.workingDirectory || undefined,
|
|
@@ -262,7 +276,7 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
262
276
|
return createToolResultMessage(toolCallId, toolName, result, true);
|
|
263
277
|
}
|
|
264
278
|
|
|
265
|
-
const timeoutSeconds = args.timeout
|
|
279
|
+
const timeoutSeconds = shellTimeoutSeconds(args.timeout);
|
|
266
280
|
const toolArgs: Record<string, unknown> = {
|
|
267
281
|
command: args.command,
|
|
268
282
|
cwd: args.workingDirectory || undefined,
|
|
@@ -306,8 +306,9 @@ Worker protocol:
|
|
|
306
306
|
|
|
307
307
|
Useful runtime env vars:
|
|
308
308
|
|
|
309
|
-
- `GJC_TEAM_TMUX_COMMAND`
|
|
310
|
-
- tmux binary/command override (default `tmux`)
|
|
309
|
+
- `GJC_TMUX_COMMAND` / `GJC_TEAM_TMUX_COMMAND`
|
|
310
|
+
- tmux binary/command override (default `tmux`). `GJC_TMUX_COMMAND` applies to every GJC tmux flow; `GJC_TEAM_TMUX_COMMAND` is honored as an alias by the team path. Both resolve through the same resolver, so the team leader and `gjc session ...` always target the same multiplexer.
|
|
311
|
+
- Multiplexer support boundary: GJC-managed sessions and the team leader are detected via tmux user options (`@gjc-profile`, written with `set-option` and read back with `show-options` / `list-sessions -F`). A provider must round-trip those user options to be supported. Real tmux works. Alternative multiplexers such as psmux on Windows do not reliably persist tmux user options yet, so `gjc session status` reports `gjc_tmux_session_untagged` (the session exists in the multiplexer but is not GJC-tagged) and team startup rejects the leader as `unmanaged_tmux_session`. The Windows-native psmux path is therefore not fully supported; use real tmux for GJC-managed session and team flows.
|
|
311
312
|
- `GJC_TEAM_WORKER_COMMAND`
|
|
312
313
|
- worker command override (default resolves to active GJC entrypoint or `gjc`)
|
|
313
314
|
- `GJC_TEAM_STATE_ROOT`
|
|
@@ -120,9 +120,15 @@ Examples:
|
|
|
120
120
|
|
|
121
121
|
```sh
|
|
122
122
|
gjc ultragoal steer --kind add_subgoal --title "Investigate blocker" --objective "Validate the blocker and report evidence." --evidence "log/test output" --rationale "The blocker changes the safe execution order." --json
|
|
123
|
-
gjc ultragoal steer --
|
|
123
|
+
gjc ultragoal steer --kind split_subgoal --goal-id G002 --replacements-json '[{"title":"Fix parser","objective":"Resolve parser blocker."},{"title":"Verify parser","objective":"Run focused parser verification."}]' --evidence "Implementation split found two separable risks" --rationale "Splitting keeps each sub-goal independently verifiable." --json
|
|
124
|
+
gjc ultragoal steer --kind reorder_pending --order-json '["G003","G002"]' --evidence "Dependency order changed after investigation" --rationale "G003 must land before G002 can proceed safely." --json
|
|
125
|
+
gjc ultragoal steer --kind revise_pending_wording --goal-id G002 --title "Clarify blocker story" --evidence "The current title hides the actual blocker" --rationale "Clear wording keeps the ledger auditable." --json
|
|
126
|
+
gjc ultragoal steer --kind annotate_ledger --evidence "User changed release ordering at runtime" --rationale "The aggregate objective is unchanged, but the execution history needs an audit note." --json
|
|
127
|
+
gjc ultragoal steer --kind mark_blocked_superseded --goal-id G004 --evidence "The blocked work is no longer required because replacement evidence covers it" --rationale "No replacement sub-goal is needed; superseding only the blocked sub-goal unblocks final completion without changing the aggregate objective." --json
|
|
124
128
|
```
|
|
125
129
|
|
|
130
|
+
`--directive-json` and UserPromptSubmit structured steering are planned/deferred routing surfaces, not part of the native typed `--kind` CLI path described above.
|
|
131
|
+
|
|
126
132
|
Steering invariants:
|
|
127
133
|
|
|
128
134
|
- Do not edit the aggregate goal objective, original brief constraints, quality gates, or completion status. The aggregate objective is a stable pointer to `.gjc/ultragoal/goals.json` and `.gjc/ultragoal/ledger.jsonl`, not an enumeration of initial goal ids.
|
|
@@ -131,7 +137,7 @@ Steering invariants:
|
|
|
131
137
|
- Superseded goals remain in `goals.json` with steering metadata and are skipped for scheduling.
|
|
132
138
|
- Blocked goals without replacements are skipped for scheduling but still block final completion until later explicit steering replaces or supersedes them.
|
|
133
139
|
|
|
134
|
-
UserPromptSubmit
|
|
140
|
+
UserPromptSubmit structured steering directives are a planned/deferred routing surface. Normal prose does not mutate state.
|
|
135
141
|
|
|
136
142
|
## Role-agent delegation guidance
|
|
137
143
|
|
package/src/export/html/index.ts
CHANGED
|
@@ -150,15 +150,19 @@ export async function exportFromFile(inputPath: string, options?: ExportOptions
|
|
|
150
150
|
throw err;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
try {
|
|
154
|
+
const sessionData: SessionData = {
|
|
155
|
+
header: sm.getHeader(),
|
|
156
|
+
entries: sm.getEntries(),
|
|
157
|
+
leafId: sm.getLeafId(),
|
|
158
|
+
};
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
const html = await generateHtml(sessionData, opts.themeName);
|
|
161
|
+
const outputPath = opts.outputPath || `${APP_NAME}-session-${path.basename(inputPath, ".jsonl")}.html`;
|
|
161
162
|
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
await Bun.write(outputPath, html);
|
|
164
|
+
return outputPath;
|
|
165
|
+
} finally {
|
|
166
|
+
await sm.close();
|
|
167
|
+
}
|
|
164
168
|
}
|