thincoder 0.10.0 → 0.11.1
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/README.md +1 -1
- package/package.json +1 -1
- package/src/advisor.mjs +360 -72
- package/src/agent/helpers.mjs +7 -3
- package/src/agent/setup.mjs +2 -2
- package/src/agent-tools/advisor.mjs +36 -0
- package/src/agent-tools/plan.mjs +53 -2
- package/src/agent-tools/subagent.mjs +7 -1
- package/src/agent-tools/timer.mjs +1 -1
- package/src/agent-tools/verify.mjs +1 -0
- package/src/agent-tools.mjs +1 -0
- package/src/agent.mjs +73 -21
- package/src/auto-think.mjs +23 -5
- package/src/cli/make-agent.mjs +7 -0
- package/src/config.mjs +47 -20
- package/src/prompts/advisor-round1.md +23 -0
- package/src/prompts/advisor-round2.md +26 -0
- package/src/prompts/advisor-round3.md +24 -0
- package/src/prompts/coder.md +6 -2
- package/src/prompts/discipline.md +23 -6
- package/src/prompts/explore.md +2 -0
- package/src/prompts/plan.md +2 -0
- package/src/prompts/system.md +13 -6
- package/src/provider/anthropic.mjs +190 -0
- package/src/provider/core.mjs +42 -130
- package/src/provider/google.mjs +199 -0
- package/src/provider/sse.mjs +112 -0
- package/src/proxy.mjs +236 -0
- package/src/tools/bash.md +8 -0
- package/src/tools/codemode.mjs +5 -16
- package/src/tools/edit.md +8 -0
- package/src/tools/fetch.md +2 -1
- package/src/tools/git.mjs +125 -156
- package/src/tools/index.mjs +9 -9
- package/src/tools/linter.mjs +46 -32
- package/src/tools/read.md +7 -0
- package/src/tools/shared.mjs +16 -0
- package/src/tools/system.mjs +14 -10
- package/src/tools/web.mjs +115 -89
- package/src/tools/websearch.md +5 -3
- package/src/tui/agent-turn.mjs +86 -75
- package/src/tui/cmd-advisor.mjs +138 -49
- package/src/tui/cmd-clear.mjs +11 -17
- package/src/tui/cmd-config.mjs +226 -142
- package/src/tui/cmd-extract.mjs +1 -1
- package/src/tui/cmd-fold.mjs +2 -3
- package/src/tui/cmd-goal.mjs +58 -27
- package/src/tui/cmd-help.mjs +3 -1
- package/src/tui/cmd-mcp.mjs +178 -142
- package/src/tui/cmd-model.mjs +15 -4
- package/src/tui/cmd-new.mjs +7 -13
- package/src/tui/cmd-restore.mjs +12 -16
- package/src/tui/cmd-session.mjs +28 -32
- package/src/tui/cmd-think.mjs +75 -50
- package/src/tui/cmd-undo.mjs +19 -23
- package/src/tui/cmd-upgrade.mjs +22 -26
- package/src/tui/index.mjs +61 -215
- package/src/tui/key-handler.mjs +56 -20
- package/src/tui/layout.mjs +13 -3
- package/src/tui/pickers.mjs +151 -182
- package/src/tui/render-conversation.mjs +92 -0
- package/src/tui/render-frame.mjs +56 -114
- package/src/tui/render-loop.mjs +181 -0
- package/src/tui/slash-commands.mjs +26 -16
|
@@ -29,7 +29,7 @@ export const timerTool = {
|
|
|
29
29
|
readonly: true,
|
|
30
30
|
sideEffectExempt: true,
|
|
31
31
|
execute(args, ctx) {
|
|
32
|
-
const seconds = args.seconds ??
|
|
32
|
+
const seconds = args.seconds ?? 180
|
|
33
33
|
const expiresAt = Date.now() + seconds * 1000
|
|
34
34
|
const message = args.message || `⏰ Time's up (${seconds}s). Have you tried running the code, adding a console.log, or checking the output? Thinking more without data is guessing.`
|
|
35
35
|
|
package/src/agent-tools.mjs
CHANGED
|
@@ -11,3 +11,4 @@ export { goalTool } from "./agent-tools/goal.mjs"
|
|
|
11
11
|
export { verifyTool } from "./agent-tools/verify.mjs"
|
|
12
12
|
export { recentChangesTool } from "./agent-tools/recent-changes.mjs"
|
|
13
13
|
export { timerTool } from "./agent-tools/timer.mjs"
|
|
14
|
+
export { advisorTool } from "./agent-tools/advisor.mjs"
|
package/src/agent.mjs
CHANGED
|
@@ -31,7 +31,7 @@ export const EXPLORE_OVERLAY = _EXPLORE
|
|
|
31
31
|
export const CODER_OVERLAY = _CODER
|
|
32
32
|
export const PLAN_OVERLAY = _PLAN
|
|
33
33
|
|
|
34
|
-
//
|
|
34
|
+
// exported for consumption by agent-tools.mjs
|
|
35
35
|
export {
|
|
36
36
|
ContinueError,
|
|
37
37
|
repairHistory, listWorkDir, loadProjectInstructions,
|
|
@@ -61,8 +61,8 @@ export function createAgent({
|
|
|
61
61
|
provider, tools, config, cwd, memory, _role: role,
|
|
62
62
|
overlay, tasks, history,
|
|
63
63
|
planMode, autoApprove, goal,
|
|
64
|
-
_mutatedThisRun: false, _verifiedThisRun: false, _verifyPassed: undefined,
|
|
65
|
-
_touchedFiles: [], _verifyRetries: 0,
|
|
64
|
+
_mutatedThisRun: false, _verifiedThisRun: false, _verifyPassed: undefined, _calledAdvisorThisRun: false,
|
|
65
|
+
_touchedFiles: [], _verifyRetries: 0, _advisorRound: 0,
|
|
66
66
|
_pendingReminders: [],
|
|
67
67
|
_pendingTimers: [],
|
|
68
68
|
_sessionStart: sessionStart,
|
|
@@ -81,11 +81,16 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
81
81
|
agent._mutatedThisRun = false
|
|
82
82
|
agent._verifiedThisRun = false
|
|
83
83
|
agent._verifyPassed = undefined
|
|
84
|
+
agent._calledAdvisorThisRun = false
|
|
84
85
|
agent._touchedFiles = []
|
|
85
86
|
agent._verifyRetries = 0
|
|
87
|
+
agent._advisorRound = 0
|
|
86
88
|
let guardPushbacks = 0
|
|
87
89
|
let honestReminderInjected = false
|
|
88
90
|
const recentCallSigs = []
|
|
91
|
+
// repeat: "once" stream rules fire at most once per runAgent call (user turn):
|
|
92
|
+
// this set survives across chat() calls (rule abort-retry, tool loop) within the turn.
|
|
93
|
+
const streamRuleFired = new Set()
|
|
89
94
|
|
|
90
95
|
for (let turn = 0; turn < maxTurns; turn++) {
|
|
91
96
|
|
|
@@ -94,6 +99,7 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
94
99
|
try {
|
|
95
100
|
if (await compressIfNeeded(agent, threshold, callbacks)) {
|
|
96
101
|
agent._compressFailures = 0
|
|
102
|
+
agent._planReminderAtLen = 0 // After compression history shrinks, reset cadence so reminders resume
|
|
97
103
|
recentCallSigs.length = 0 // After compression history is rebuilt, reset stall detection counter
|
|
98
104
|
callbacks.onCompress?.()
|
|
99
105
|
if (agent.autoApprove && !agent.history.some((m) => m.content === AUTO_REMINDER)) {
|
|
@@ -111,6 +117,24 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
|
|
120
|
+
// Plan-mode reminder cadence: re-inject constraint reminders while plan mode is active
|
|
121
|
+
// (sparse every 2 turns, full every 5 turns or when the user sends a new message),
|
|
122
|
+
// so the read-only restriction never fades from context.
|
|
123
|
+
if (agent.planMode) {
|
|
124
|
+
const lastMsg = agent.history.at(-1)
|
|
125
|
+
const realUserMsg = lastMsg?.role === "user"
|
|
126
|
+
&& typeof lastMsg.content === "string"
|
|
127
|
+
&& !lastMsg.content.startsWith("[System reminder:")
|
|
128
|
+
&& !lastMsg.content.startsWith("[User interrupt:")
|
|
129
|
+
const newUserSince = realUserMsg && agent.history.length > (agent._planReminderAtLen ?? 0)
|
|
130
|
+
const { planReminderForTurn } = await import("./agent-tools/plan.mjs")
|
|
131
|
+
const reminder = planReminderForTurn(agent, newUserSince)
|
|
132
|
+
if (reminder) {
|
|
133
|
+
agent._planReminderAtLen = agent.history.length + 1
|
|
134
|
+
agent.history.push({ role: "user", content: reminder, transient: true })
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
114
138
|
const messages = [{ role: "system", content: systemPrompt }, ...agent.history]
|
|
115
139
|
let response
|
|
116
140
|
|
|
@@ -129,15 +153,18 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
129
153
|
onWait: callbacks.onWait,
|
|
130
154
|
signal,
|
|
131
155
|
streamRules: agent.config.agent?.streamRules ?? [],
|
|
156
|
+
firedPatterns: streamRuleFired,
|
|
132
157
|
})
|
|
133
158
|
} catch (e) {
|
|
134
159
|
// User interrupt (Ctrl+I): controller.abort({ interrupt: true, message: "…" }).
|
|
135
160
|
// Inject the message into history and let the outer loop recreate the controller.
|
|
136
161
|
if (e.name === "AbortError" && signal?.reason?.interrupt) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
162
|
+
const msg = `[User interrupt: ${signal.reason.message}]`
|
|
163
|
+
// Dedup: if the interrupt was already handled during tool execution (L302-310),
|
|
164
|
+
// don't push a duplicate — the outer loop will still recreate the controller.
|
|
165
|
+
if (agent.history.at(-1)?.content !== msg) {
|
|
166
|
+
agent.history.push({ role: "user", content: msg })
|
|
167
|
+
}
|
|
141
168
|
}
|
|
142
169
|
throw e
|
|
143
170
|
}
|
|
@@ -219,6 +246,7 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
219
246
|
role: "user",
|
|
220
247
|
content: `[System reminder: you still have pending tasks: ${pending}. Update their status with the task tool before finishing — if they're done, mark them done; if they're not applicable, remove them.]`,
|
|
221
248
|
})
|
|
249
|
+
callbacks.onTurnEnd?.(agent, turn)
|
|
222
250
|
continue
|
|
223
251
|
}
|
|
224
252
|
// --- verify guard: push model to verify mutated files before completion ---
|
|
@@ -230,15 +258,15 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
230
258
|
role: "user",
|
|
231
259
|
content: "[System reminder: you modified files in this run but have not verified the changes. Before finishing: call the verify tool to run syntax checks and tests. If verify reports failures, fix them and run verify again. If verification is genuinely impossible here, say so explicitly in your reply.]",
|
|
232
260
|
})
|
|
261
|
+
callbacks.onTurnEnd?.(agent, turn)
|
|
233
262
|
continue
|
|
234
|
-
}
|
|
235
|
-
if (agent._verifiedThisRun && agent._verifyPassed === false && agent._verifyRetries < MAX_VERIFY_RETRIES) {
|
|
236
263
|
agent._verifyRetries++
|
|
237
264
|
agent.history.push({ role: "assistant", content: response.content })
|
|
238
265
|
agent.history.push({
|
|
239
266
|
role: "user",
|
|
240
267
|
content: `[System reminder: verify reported test failures (retry ${agent._verifyRetries}/${MAX_VERIFY_RETRIES}). Review the failures, fix the issues, then run verify again. If you cannot fix after ${MAX_VERIFY_RETRIES} attempts, explain honestly what's blocking you.]`,
|
|
241
268
|
})
|
|
269
|
+
callbacks.onTurnEnd?.(agent, turn)
|
|
242
270
|
continue
|
|
243
271
|
}
|
|
244
272
|
if (agent._verifyPassed === false && agent._verifyRetries >= MAX_VERIFY_RETRIES) {
|
|
@@ -252,6 +280,22 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
252
280
|
role: "user",
|
|
253
281
|
content: `[System reminder: ${MAX_VERIFY_RETRIES} verify attempts exhausted and tests are still failing. In your response to the user, you MUST state explicitly: (1) what tests are still failing, (2) what you tried, (3) what you believe the root cause is. Do not present this as complete — the user needs to know the work is unfinished.]`,
|
|
254
282
|
})
|
|
283
|
+
callbacks.onTurnEnd?.(agent, turn)
|
|
284
|
+
continue
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// --- advisor guard: push model to review changes before completion ---
|
|
288
|
+
// When advisor is enabled and guard is not explicitly disabled, mutated files
|
|
289
|
+
// must be reviewed before the turn ends. No hard round cap — convergence protocol
|
|
290
|
+
// (round 3+ strict verification) naturally limits divergence.
|
|
291
|
+
if (depth === 0 && agent.config?.advisor?.enabled && agent.config?.advisor?.guard !== false) {
|
|
292
|
+
if (agent._mutatedThisRun && !agent._calledAdvisorThisRun && (agent._touchedFiles ?? []).length > 0) {
|
|
293
|
+
agent.history.push({ role: "assistant", content: response.content })
|
|
294
|
+
agent.history.push({
|
|
295
|
+
role: "user",
|
|
296
|
+
content: `[System reminder: you changed code in this run but haven't reviewed with advisor (round ${agent._advisorRound + 1}). Call the \`advisor\` tool to get an independent code review. After the review, produce a response table for every issue found (see discipline rules for format). If the changes are trivial (typo, one-liner, formatting only), you may skip and explain why in your reply.]`,
|
|
297
|
+
})
|
|
298
|
+
callbacks.onTurnEnd?.(agent, turn)
|
|
255
299
|
continue
|
|
256
300
|
}
|
|
257
301
|
}
|
|
@@ -276,6 +320,17 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
276
320
|
|
|
277
321
|
const results = await executeToolCalls(agent, toolByName, response.toolCalls, callbacks, depth, signal)
|
|
278
322
|
|
|
323
|
+
// Ctrl+I interrupt during tool execution: skip committing partial results —
|
|
324
|
+
// the tool failure messages would mislead the model. Inject the interrupt and retry.
|
|
325
|
+
if (signal?.reason?.interrupt) {
|
|
326
|
+
agent.history.push({
|
|
327
|
+
role: "user",
|
|
328
|
+
content: `[User interrupt: ${signal.reason.message}]`,
|
|
329
|
+
})
|
|
330
|
+
callbacks.onTurnEnd?.(agent, turn)
|
|
331
|
+
continue
|
|
332
|
+
}
|
|
333
|
+
|
|
279
334
|
// Model is executing tools → doing real work, reset guard pushback counter
|
|
280
335
|
guardPushbacks = 0
|
|
281
336
|
|
|
@@ -308,8 +363,16 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
308
363
|
}
|
|
309
364
|
agent.history.push({ role: "tool", tool_call_id: toolCall.id, content: result })
|
|
310
365
|
if (tool && ok) {
|
|
311
|
-
if (!tool.readonly && !tool.sideEffectExempt)
|
|
366
|
+
if (!tool.readonly && !tool.sideEffectExempt) {
|
|
367
|
+
agent._mutatedThisRun = true
|
|
368
|
+
// Any mutation after advisor invalidates the review — need re-review
|
|
369
|
+
if (agent._calledAdvisorThisRun) agent._calledAdvisorThisRun = false
|
|
370
|
+
}
|
|
312
371
|
if (toolCall.name === "verify") agent._verifiedThisRun = true
|
|
372
|
+
if (toolCall.name === "advisor") {
|
|
373
|
+
agent._calledAdvisorThisRun = true
|
|
374
|
+
agent._advisorRound++ // advance convergence round
|
|
375
|
+
}
|
|
313
376
|
if (FILE_MUTATORS.has(toolCall.name)) {
|
|
314
377
|
const args = JSON.parse(toolCall.arguments)
|
|
315
378
|
const paths = tool.touchedPaths ? tool.touchedPaths(args) : [args.path]
|
|
@@ -386,17 +449,6 @@ export async function runAgent(agent, input, callbacks = {}, { depth = 0, signal
|
|
|
386
449
|
}
|
|
387
450
|
|
|
388
451
|
callbacks.onTurnEnd?.(agent, turn)
|
|
389
|
-
|
|
390
|
-
// Advisor: automated code review after each tool-execution turn.
|
|
391
|
-
// Runs asynchronously — failure is silent, main loop continues regardless.
|
|
392
|
-
if (agent.config?.advisor?.enabled) {
|
|
393
|
-
const { runAdvisor } = await import("./advisor.mjs")
|
|
394
|
-
const note = await runAdvisor(agent)
|
|
395
|
-
if (note) {
|
|
396
|
-
agent.history.push({ role: "user", content: note })
|
|
397
|
-
callbacks.onAdvisor?.(note)
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
452
|
}
|
|
401
453
|
|
|
402
454
|
throw new ContinueError(maxTurns)
|
package/src/auto-think.mjs
CHANGED
|
@@ -31,6 +31,26 @@ const EFFORT_MAP = {
|
|
|
31
31
|
high: ["max", "max", "xhigh", "max"],
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Build classifier input from history: the latest real user message (reminders and
|
|
36
|
+
* interrupt injections excluded), plus the previous user message as context when the
|
|
37
|
+
* latest is too short to classify on its own (e.g. "继续" / "还有几个问题").
|
|
38
|
+
* Exported for tests.
|
|
39
|
+
*/
|
|
40
|
+
export function buildClassifierInput(history) {
|
|
41
|
+
const isRealUser = (m) =>
|
|
42
|
+
m.role === "user" && typeof m.content === "string"
|
|
43
|
+
&& !m.content.startsWith("[System reminder:") && !m.content.startsWith("[User interrupt:")
|
|
44
|
+
const users = history.filter(isRealUser)
|
|
45
|
+
const last = users.at(-1)
|
|
46
|
+
if (!last) return null
|
|
47
|
+
let prompt = last.content
|
|
48
|
+
if (prompt.length < 200 && users.length > 1) {
|
|
49
|
+
prompt = `Previous request (context):\n${users.at(-2).content.slice(0, 1200)}\n\nLatest message:\n${prompt}`
|
|
50
|
+
}
|
|
51
|
+
return prompt.slice(0, 2000)
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
/**
|
|
35
55
|
* Classify the difficulty of the user's prompt and adjust reasoning effort.
|
|
36
56
|
* Only runs on the first turn (turn === 0) of a user message.
|
|
@@ -47,10 +67,8 @@ export async function classifyAndApply(agent, turn) {
|
|
|
47
67
|
const validEfforts = spec.reasoningEffortEnum
|
|
48
68
|
if (!validEfforts) return null // Model doesn't support reasoning effort
|
|
49
69
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (!lastUser) return null
|
|
53
|
-
const prompt = typeof lastUser.content === "string" ? lastUser.content : ""
|
|
70
|
+
const prompt = buildClassifierInput(agent.history)
|
|
71
|
+
if (prompt == null) return null
|
|
54
72
|
|
|
55
73
|
// Classification call: use same provider, minimal tokens, no tools, no streaming
|
|
56
74
|
let level
|
|
@@ -59,7 +77,7 @@ export async function classifyAndApply(agent, turn) {
|
|
|
59
77
|
const response = await chat(classifierProvider, {
|
|
60
78
|
messages: [
|
|
61
79
|
{ role: "system", content: CLASSIFY_PROMPT },
|
|
62
|
-
{ role: "user", content: prompt
|
|
80
|
+
{ role: "user", content: prompt },
|
|
63
81
|
],
|
|
64
82
|
tools: [],
|
|
65
83
|
signal: AbortSignal.timeout(5_000),
|
package/src/cli/make-agent.mjs
CHANGED
|
@@ -12,6 +12,13 @@ export async function assembleAgent() {
|
|
|
12
12
|
const config = loadConfig()
|
|
13
13
|
const provider = config.provider
|
|
14
14
|
const providers = config.providersList
|
|
15
|
+
|
|
16
|
+
// Inject proxy URI into providers (double opt-in: provider.proxy + config.proxy.model)
|
|
17
|
+
const { injectProxy } = await import("../proxy.mjs")
|
|
18
|
+
injectProxy(providers, config)
|
|
19
|
+
// config.provider 是 loadConfig 里的独立拷贝,同步注入结果
|
|
20
|
+
provider.proxyUri = providers.find((p) => p.name === config.activeProvider)?.proxyUri
|
|
21
|
+
|
|
15
22
|
const memory = createMemory({ dbPath: config.memory.dbPath })
|
|
16
23
|
// Vector retrieval: enabled if embedding is configured (lazy vector generation, computed on first search)
|
|
17
24
|
if (config.embedding?.apiKey) {
|
package/src/config.mjs
CHANGED
|
@@ -14,11 +14,16 @@ export const configPath = join(configDir, "config.json")
|
|
|
14
14
|
|
|
15
15
|
/** Built-in provider presets: shared by /provider add <preset> and first-run wizard */
|
|
16
16
|
export const PROVIDER_PRESETS = {
|
|
17
|
-
deepseek: { baseURL: "https://api.deepseek.com
|
|
17
|
+
deepseek: { baseURL: "https://api.deepseek.com", model: "deepseek-v4-pro", thinking: { type: "enabled" }, reasoningEffort: "max", maxTokens: 393216, desc: "DeepSeek" },
|
|
18
18
|
kimi: { baseURL: "https://api.moonshot.cn/v1", model: "kimi-k3", thinking: null, reasoningEffort: "max", maxTokens: 131072, desc: "Kimi / Moonshot" },
|
|
19
|
-
glm: { baseURL: "https://open.bigmodel.cn/api/paas/v4", model: "glm-5.2", thinking: { type: "enabled" }, reasoningEffort: "max", maxTokens:
|
|
19
|
+
glm: { baseURL: "https://open.bigmodel.cn/api/paas/v4", model: "glm-5.2", thinking: { type: "enabled" }, reasoningEffort: "max", maxTokens: 128000, desc: "Zhipu GLM" },
|
|
20
20
|
qwen: { baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1", model: "qwen3.7-max", maxTokens: 131072, desc: "Qwen / Alibaba" },
|
|
21
|
-
minimax: { baseURL: "https://api.minimaxi.com/v1", model: "MiniMax-M3", thinking: { type: "adaptive" }, maxTokens:
|
|
21
|
+
minimax: { baseURL: "https://api.minimaxi.com/v1", model: "MiniMax-M3", thinking: { type: "adaptive" }, maxTokens: 128000, chatPath: "/text/chatcompletion_v2", desc: "MiniMax" },
|
|
22
|
+
openai: { baseURL: "https://api.openai.com/v1", model: "gpt-4o", desc: "OpenAI" },
|
|
23
|
+
claude: { baseURL: "https://api.anthropic.com/v1", model: "claude-sonnet-4", format: "anthropic", maxTokens: 8192, desc: "Claude (Anthropic)" },
|
|
24
|
+
gemini: { baseURL: "https://generativelanguage.googleapis.com/v1beta", model: "gemini-2.5-flash", format: "google", maxTokens: 8192, desc: "Gemini (Google)" },
|
|
25
|
+
grok: { baseURL: "https://api.x.ai/v1", model: "grok-4.5", maxTokens: 65536, desc: "Grok (xAI)" },
|
|
26
|
+
mistral: { baseURL: "https://api.mistral.ai/v1", model: "mistral-large", maxTokens: 32768, desc: "Mistral" },
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
// Default provider matches deepseek preset (strip the desc display field)
|
|
@@ -34,7 +39,7 @@ const DEFAULTS = {
|
|
|
34
39
|
compactThreshold: 100000,
|
|
35
40
|
verifyGuard: false, // push model back to verify when files were mutated but verify not run (opt-in)
|
|
36
41
|
streamRules: [], // time-traveling stream rules: [{ pattern: "regex", message: "reminder", action: "abort"|"warn", repeat: "always"|"once" }]
|
|
37
|
-
advisor: { enabled: false }, //
|
|
42
|
+
advisor: { enabled: false }, // code review; { enabled: true, provider: "deepseek", model: "deepseek-chat", thinking: { type: "enabled" }, reasoningEffort: "max", guard: true }
|
|
38
43
|
autoThink: false, // auto-classify task difficulty and set reasoning effort per-turn
|
|
39
44
|
},
|
|
40
45
|
memory: {
|
|
@@ -75,13 +80,13 @@ const MODEL_SPECS = [
|
|
|
75
80
|
["deepseek-reasoner", { context: 256_000, maxOutput: 384_000, thinking: true, prefixMode: true, cacheMode: "prompt", thinkApi: "type", reasoningEcho: "required", reasoningEffortEnum: ["high", "max"], tempRange: [0, 2] }],
|
|
76
81
|
["deepseek-chat", { context: 256_000, maxOutput: 384_000, thinking: false, prefixMode: true, cacheMode: "prompt", thinkApi: "type", reasoningEcho: "required", reasoningEffortEnum: ["high", "max"], tempRange: [0, 2] }],
|
|
77
82
|
// Kimi series
|
|
78
|
-
["kimi-k3", { context: 1_000_000, maxOutput:
|
|
83
|
+
["kimi-k3", { context: 1_000_000, maxOutput: 131_072, thinking: true, partialMode: true, multimodal: true, cacheMode: "auto", thinkApi: "effort", reasoningEcho: "required", reasoningEffortEnum: ["low", "high", "max"] }],
|
|
79
84
|
["kimi-k2", { context: 256_000, maxOutput: 128_000, thinking: false, partialMode: true, multimodal: true, cacheMode: "none" }],
|
|
80
85
|
["moonshot", { context: 128_000, maxOutput: 32_000, thinking: false, cacheMode: "none" }],
|
|
81
86
|
// GLM series
|
|
82
|
-
["glm-5.2", { context: 1_000_000, maxOutput: 128_000, thinking: true, cacheMode: "auto", thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["max", "xhigh", "high", "medium", "low", "minimal", "none"], tempRange: [0, 1] }],
|
|
83
|
-
["glm-5", { context: 1_000_000, maxOutput: 128_000, thinking: true, cacheMode: "auto", thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["max", "xhigh", "high", "medium", "low", "minimal", "none"], tempRange: [0, 1] }],
|
|
84
|
-
["glm-4", { context: 128_000, maxOutput: 32_000, thinking: true, cacheMode: "auto", thinkApi: "type", reasoningEcho: "optional", tempRange: [0, 1] }],
|
|
87
|
+
["glm-5.2", { context: 1_000_000, maxOutput: 128_000, thinking: true, cacheMode: "auto", thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["max", "xhigh", "high", "medium", "low", "minimal", "none"], tempRange: [0, 1], noUsageStream: true }],
|
|
88
|
+
["glm-5", { context: 1_000_000, maxOutput: 128_000, thinking: true, cacheMode: "auto", thinkApi: "type", reasoningEcho: "optional", reasoningEffortEnum: ["max", "xhigh", "high", "medium", "low", "minimal", "none"], tempRange: [0, 1], noUsageStream: true }],
|
|
89
|
+
["glm-4", { context: 128_000, maxOutput: 32_000, thinking: true, cacheMode: "auto", thinkApi: "type", reasoningEcho: "optional", tempRange: [0, 1], noUsageStream: true }],
|
|
85
90
|
// GPT series
|
|
86
91
|
["gpt-4.1", { context: 1_000_000, maxOutput: 128_000, thinking: false, cacheMode: "prompt" }],
|
|
87
92
|
["gpt-4o", { context: 128_000, maxOutput: 16_000, thinking: false, multimodal: true, cacheMode: "prompt" }],
|
|
@@ -93,18 +98,29 @@ const MODEL_SPECS = [
|
|
|
93
98
|
["qwen-plus", { context: 1_000_000, maxOutput: 32_000, thinking: false, partialMode: true, multimodal: true, cacheMode: "none", thinkApi: "effort", tempRange: [0, 2] }],
|
|
94
99
|
["qwen", { context: 1_000_000, maxOutput: 128_000, thinking: false, partialMode: true, multimodal: true, cacheMode: "none", thinkApi: "effort", tempRange: [0, 2] }],
|
|
95
100
|
// MiniMax series
|
|
96
|
-
["MiniMax-M3", { context: 1_000_000, maxOutput: 128_000, thinking: true, multimodal: true, cacheMode: "auto", thinkApi: "type",
|
|
97
|
-
["minimax-m3", { context: 1_000_000, maxOutput: 128_000, thinking: true, multimodal: true, cacheMode: "auto", thinkApi: "type",
|
|
98
|
-
["minimax-m1", { context: 256_000, maxOutput: 128_000, thinking: false, cacheMode: "auto" }],
|
|
101
|
+
["MiniMax-M3", { context: 1_000_000, maxOutput: 128_000, thinking: true, multimodal: true, cacheMode: "auto", thinkApi: "type", thinkEnabledValue: "adaptive", tempRange: [0, 2], noUsageStream: true }],
|
|
102
|
+
["minimax-m3", { context: 1_000_000, maxOutput: 128_000, thinking: true, multimodal: true, cacheMode: "auto", thinkApi: "type", thinkEnabledValue: "adaptive", tempRange: [0, 2], noUsageStream: true }],
|
|
103
|
+
["minimax-m1", { context: 256_000, maxOutput: 128_000, thinking: false, cacheMode: "auto", noUsageStream: true }],
|
|
104
|
+
// Grok series (xAI — OpenAI-compatible)
|
|
105
|
+
["grok-4.5", { context: 500_000, maxOutput: 64_000, thinking: false, multimodal: true, tempRange: [0, 2] }],
|
|
106
|
+
["grok-4", { context: 500_000, maxOutput: 64_000, thinking: false, multimodal: true, tempRange: [0, 2] }],
|
|
107
|
+
["grok-4-mini", { context: 128_000, maxOutput: 16_000, thinking: false, tempRange: [0, 2] }],
|
|
108
|
+
// Mistral series (OpenAI-compatible)
|
|
109
|
+
["mistral-large", { context: 128_000, maxOutput: 32_000, thinking: false, multimodal: true, tempRange: [0, 2] }],
|
|
110
|
+
["codestral", { context: 256_000, maxOutput: 32_000, thinking: false, tempRange: [0, 2] }],
|
|
111
|
+
// Claude series (Anthropic)
|
|
112
|
+
["claude-opus-4", { context: 200_000, maxOutput: 32_000, thinking: false, multimodal: true, cacheMode: "none", format: "anthropic" }],
|
|
113
|
+
["claude-sonnet-4", { context: 200_000, maxOutput: 32_000, thinking: false, multimodal: true, cacheMode: "none", format: "anthropic" }],
|
|
114
|
+
["claude-3.5-haiku", { context: 200_000, maxOutput: 8_192, thinking: false, cacheMode: "none", format: "anthropic" }],
|
|
115
|
+
// Gemini series (Google)
|
|
116
|
+
["gemini-2.5-pro", { context: 2_000_000, maxOutput: 64_000, thinking: false, multimodal: true, cacheMode: "none", format: "google", noUsageStream: true }],
|
|
117
|
+
["gemini-2.5-flash", { context: 1_000_000, maxOutput: 64_000, thinking: false, multimodal: true, cacheMode: "none", format: "google", noUsageStream: true }],
|
|
99
118
|
]
|
|
100
119
|
const DEFAULT_SPEC = { context: 128_000, maxOutput: 32_000, cacheMode: "none" }
|
|
101
|
-
// Window utilization
|
|
102
|
-
// injected context (directory tree, git context, outline, project instructions,
|
|
103
|
-
// search results) can consume 30-50K tokens each turn
|
|
104
|
-
// For 1M-window models: 600K is still too high → cap at 300K.
|
|
120
|
+
// Window utilization threshold: compacts at 60% context, reserving 40% headroom
|
|
121
|
+
// for injected context (directory tree, git context, outline, project instructions,
|
|
122
|
+
// memory/doc search results) which can consume 30-50K tokens each turn.
|
|
105
123
|
const COMPACT_RATIO = 0.6
|
|
106
|
-
const COMPACT_CAP_TOKENS = 300_000
|
|
107
|
-
const COMPACT_FLOOR = 40_000
|
|
108
124
|
|
|
109
125
|
/** Look up spec by model name prefix (case-insensitive), conservative default for unknown models */
|
|
110
126
|
export function specForModel(model) {
|
|
@@ -119,9 +135,7 @@ export function specForModel(model) {
|
|
|
119
135
|
export function resolveCompactThreshold(explicit, model) {
|
|
120
136
|
if (explicit != null) return { value: explicit, auto: false }
|
|
121
137
|
const spec = specForModel(model)
|
|
122
|
-
const
|
|
123
|
-
// Cap for large-window models (1M) and floor for small-window models (<64K, should not compact too aggressively)
|
|
124
|
-
const value = Math.max(Math.min(ratioBased, COMPACT_CAP_TOKENS), COMPACT_FLOOR)
|
|
138
|
+
const value = Math.floor(spec.context * COMPACT_RATIO)
|
|
125
139
|
return { value, auto: true }
|
|
126
140
|
}
|
|
127
141
|
|
|
@@ -140,6 +154,15 @@ export function findProvider(providers, name) {
|
|
|
140
154
|
return providers[0] ?? { name: "default", baseURL: "", model: "" }
|
|
141
155
|
}
|
|
142
156
|
|
|
157
|
+
/** Normalize proxy config to { uri, web, model } or undefined (uri/url both accepted; invalid types dropped) */
|
|
158
|
+
export function normalizeProxy(proxy) {
|
|
159
|
+
if (typeof proxy === "string") return proxy ? { uri: proxy, web: true, model: false } : undefined
|
|
160
|
+
if (!proxy || typeof proxy !== "object" || Array.isArray(proxy)) return undefined
|
|
161
|
+
const uri = proxy.uri || proxy.url || ""
|
|
162
|
+
if (typeof uri !== "string" || !uri) return undefined
|
|
163
|
+
return { uri, web: proxy.web !== false, model: proxy.model === true }
|
|
164
|
+
}
|
|
165
|
+
|
|
143
166
|
/**
|
|
144
167
|
* Load configuration.
|
|
145
168
|
* Env var priority: THINCODER_ACTIVE_PROVIDER > config file activeProvider
|
|
@@ -170,6 +193,10 @@ export function loadConfig() {
|
|
|
170
193
|
if (p.baseURL) p.baseURL = p.baseURL.replace(/\/+$/, "")
|
|
171
194
|
}
|
|
172
195
|
|
|
196
|
+
// Normalize proxy: string → { uri, web:true, model:false }; object 补默认值;非法类型丢弃。
|
|
197
|
+
// 保证 agent.config.proxy 永远是规范形态或 undefined
|
|
198
|
+
merged.proxy = normalizeProxy(merged.proxy)
|
|
199
|
+
|
|
173
200
|
// Env var overrides activeProvider
|
|
174
201
|
if (process.env.THINCODER_ACTIVE_PROVIDER) {
|
|
175
202
|
merged.activeProvider = process.env.THINCODER_ACTIVE_PROVIDER
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
You are a code review advisor.
|
|
2
|
+
Perform a full-scope review of the code changes.
|
|
3
|
+
You have read-only tools to explore the codebase.
|
|
4
|
+
|
|
5
|
+
Review workflow:
|
|
6
|
+
1. Read AGENTS.md and any design documents to understand project conventions, version requirements, and architecture decisions.
|
|
7
|
+
2. Run git diff HEAD to discover uncommitted changes.
|
|
8
|
+
3. Read changed files for full context.
|
|
9
|
+
4. Use grep or lsp to trace callers, imports, and dependencies.
|
|
10
|
+
5. Produce your review table.
|
|
11
|
+
|
|
12
|
+
Rules:
|
|
13
|
+
- Reply in the same language as the task summary.
|
|
14
|
+
- Respect the project's stated platform requirements — do not flag features as errors if they are valid under the project's target environment.
|
|
15
|
+
- Output a Markdown table. This table becomes the sole basis for convergence in later rounds — be thorough.
|
|
16
|
+
| # | File | Severity | Issue | Suggestion |
|
|
17
|
+
|---|------|----------|-------|------------|
|
|
18
|
+
| 1 | src/x.mjs | 🔴 | ... | ... |
|
|
19
|
+
- Order by severity: 🔴 Critical · 🟡 Advisory · 🔵 Style.
|
|
20
|
+
- For each issue state: which file, what the problem is, why it is a problem, how to fix it.
|
|
21
|
+
- If the code is clean, say exactly: "No issues found — code quality looks good."
|
|
22
|
+
- Cover everything now. Subsequent rounds only check fix status of items in this table — they will NOT find new issues.
|
|
23
|
+
- Stop calling tools once you are ready to produce the review table.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
You are a code review advisor.
|
|
2
|
+
Verify the prior issue table (provided in the review context).
|
|
3
|
+
You may note obvious new issues introduced by the fixes.
|
|
4
|
+
You have read-only tools to explore the codebase.
|
|
5
|
+
|
|
6
|
+
Review workflow:
|
|
7
|
+
1. Read AGENTS.md and any design documents to understand project conventions, version requirements, and architecture decisions.
|
|
8
|
+
2. Run git diff HEAD to see what changed since the last review.
|
|
9
|
+
3. Read changed files for full context.
|
|
10
|
+
4. Use grep or lsp to trace callers, imports, and dependencies.
|
|
11
|
+
5. Produce your review table.
|
|
12
|
+
|
|
13
|
+
Rules:
|
|
14
|
+
- Respect the project's stated platform requirements — do not flag features as errors if they are valid under the project's target environment.
|
|
15
|
+
- Primarily check fix status of items in the prior issue table.
|
|
16
|
+
- For items marked "fixed": verify they were actually fixed.
|
|
17
|
+
- For items marked "not an issue": evaluate whether the reasoning is sound.
|
|
18
|
+
- You may flag obvious new problems — but only if clearly visible in the diff and would cause crashes, data loss, or logic errors.
|
|
19
|
+
- Do NOT nitpick style or naming.
|
|
20
|
+
- Output a Markdown table listing all remaining problems (old or new):
|
|
21
|
+
| # | Orig# | File | Severity | Status | Notes |
|
|
22
|
+
|---|-------|------|----------|--------|-------|
|
|
23
|
+
| 1 | 3 | src/x.mjs | 🔴 | Unfixed | ... |
|
|
24
|
+
| N | (new) | src/y.mjs | 🔴 | New: null check missing after fix | ... |
|
|
25
|
+
- If all issues are resolved, say exactly: "All issues resolved — review passed."
|
|
26
|
+
- Stop calling tools once you are ready to produce the review table.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
You are a code review advisor.
|
|
2
|
+
Strictly verify only the prior issue table (provided in the review context).
|
|
3
|
+
Do NOT look for new issues.
|
|
4
|
+
You have read-only tools to explore the codebase.
|
|
5
|
+
|
|
6
|
+
Review workflow:
|
|
7
|
+
1. Read AGENTS.md and any design documents to understand project conventions, version requirements, and architecture decisions.
|
|
8
|
+
2. Run git diff HEAD to see what changed since the last review.
|
|
9
|
+
3. Read changed files for full context.
|
|
10
|
+
4. Verify fix status of each item in the prior issue table.
|
|
11
|
+
5. Produce your review table.
|
|
12
|
+
|
|
13
|
+
Rules:
|
|
14
|
+
- Respect the project's stated platform requirements — do not flag features as errors if they are valid under the project's target environment.
|
|
15
|
+
- Only check fix status of items in the prior issue table.
|
|
16
|
+
- For items marked "fixed": verify they were actually fixed.
|
|
17
|
+
- For items marked "not an issue": evaluate whether the reasoning is sound.
|
|
18
|
+
- Output a Markdown table. Only list items that still have problems:
|
|
19
|
+
| # | Orig# | File | Severity | Status | Notes |
|
|
20
|
+
|---|-------|------|----------|--------|-------|
|
|
21
|
+
| 1 | 3 | src/x.mjs | 🔴 | Unfixed | ... |
|
|
22
|
+
| 2 | 5 | src/y.mjs | 🟡 | Reasoning invalid | ... |
|
|
23
|
+
- If all issues are resolved, say exactly: "All issues resolved — review passed."
|
|
24
|
+
- Stop calling tools once you are ready to produce the review table.
|
package/src/prompts/coder.md
CHANGED
|
@@ -3,6 +3,7 @@ You are a coding subagent. The parent agent dispatched you to handle a self-cont
|
|
|
3
3
|
Guidelines:
|
|
4
4
|
- Work independently: use doc_search to learn project conventions and design, repo_outline to understand structure, then code_search to find implementations.
|
|
5
5
|
Don't write code until you know what the project intends.
|
|
6
|
+
- MINIMAL changes: solve the task, nothing more. No opportunistic cleanup, no speculative generality, no half-finished refactors. Keep the diff small enough to review at a glance — the parent agent evaluates your work by reading the diff, and every unrelated change dilutes it.
|
|
6
7
|
- Write code in small, verified steps — don't write multiple files at once without checking each along the way:
|
|
7
8
|
1. After every write/edit of a file: run a syntax/lint check to catch parse errors immediately
|
|
8
9
|
2. After a logical group of changes: run the relevant tests to confirm behavior
|
|
@@ -16,8 +17,11 @@ Guidelines:
|
|
|
16
17
|
3. Read every file you changed — catch leftover debug code, stale comments, or incomplete edits
|
|
17
18
|
4. Check that comments and docstrings match what the code actually does
|
|
18
19
|
5. Verify imports/dependencies are correct — no stale or missing references
|
|
19
|
-
- Your last message IS the report the parent sees —
|
|
20
|
-
|
|
20
|
+
- Your last message IS the report the parent sees — it is the ONLY thing the parent receives. Make it complete and self-contained. A report that fails this checklist is sent back for expansion, costing an extra turn:
|
|
21
|
+
1. What you changed and why
|
|
22
|
+
2. The path of every file you touched
|
|
23
|
+
3. How you verified the change (tests run, commands executed, with results)
|
|
24
|
+
4. Anything left undone or worth follow-up
|
|
21
25
|
|
|
22
26
|
IMPORTANT — Tool permissions: when you see "permission denied by user" for a tool, it means the parent has not granted that tool.
|
|
23
27
|
This is expected: your job is to write a detailed report of what SHOULD be done, not to force tool execution.
|
|
@@ -3,9 +3,12 @@ Coding discipline (rigor over speed—tokens spent on verification are well spen
|
|
|
3
3
|
**Workflow — match the process to the task:**
|
|
4
4
|
- Complex tasks (3+ distinct steps, architectural changes, new features): follow the full process — 1) Requirements, 2) Design, 3) Development, 4) Testing.
|
|
5
5
|
In the Requirements step, identify affected users and scenarios: who calls this code? what workflows touch it? how does the change alter their experience?
|
|
6
|
-
Write a design doc for step 2.
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Write a design doc for step 2.
|
|
7
|
+
Two tracking tools, two different purposes — use BOTH for complex work:
|
|
8
|
+
* `checklist` — project-level deliverable tracking (persists to `.thincoder/checklist.md` across sessions). One entry per requirement point. This is what the user sees as "done."
|
|
9
|
+
* `task` — session-level step breakdown (in-memory, replaced each call). Exactly one item in_progress at a time. This is your working plan for THIS conversation.
|
|
10
|
+
Mark checklist items done when the deliverable is complete; mark task items done when the step is finished.
|
|
11
|
+
- Medium tasks (2-3 steps, localized refactoring, non-trivial bug fixes): plan briefly before coding — a few lines of approach is enough, no full design doc needed. Consider who is affected and whether the change alters user-facing behavior. Use the `task` tool to track steps; checklist is optional for medium tasks.
|
|
9
12
|
- Small tasks (typo, one-line fix, trivial refactor): skip the ritual. Read the affected code, think about whether the change affects the user experience, make the change, syntax-check, verify. Done.
|
|
10
13
|
- Never guess which tier a task belongs to — if unsure, treat it as complex. Under-planning costs far more than over-planning.
|
|
11
14
|
|
|
@@ -41,7 +44,7 @@ Coding discipline (rigor over speed—tokens spent on verification are well spen
|
|
|
41
44
|
After making the change, update every dependent — no exceptions, no "I'll fix it later."
|
|
42
45
|
A change that compiles but breaks callers is not a working change — it's a regression.
|
|
43
46
|
This is not a suggestion. Modifying exports without tracing dependents is the single most common cause of incomplete work.
|
|
44
|
-
- Before destructive operations (git reset, git clean, large-scale edits, applying a big patch):
|
|
47
|
+
- Before destructive operations (git reset, git clean, large-scale edits, applying a big patch): use `git action="checkpoint" checkpointAction="create"` first. Uncommitted work is the most valuable thing in the repo — protect it before risking it.
|
|
45
48
|
- Deliver complete changes: no placeholder stubs, no "// rest unchanged", no TODO gaps left for the user to fill in.
|
|
46
49
|
- Before finalizing any implementation, pause and think through edge cases: what could go wrong? what happens on failure? what boundary conditions exist?
|
|
47
50
|
Reason about the failure modes — then handle or document the fallback.
|
|
@@ -56,7 +59,7 @@ Coding discipline (rigor over speed—tokens spent on verification are well spen
|
|
|
56
59
|
Would someone USING this code find it intuitive, predictable, and consistent with the rest of the project?
|
|
57
60
|
|
|
58
61
|
Testing discipline (right check at the right time):
|
|
59
|
-
- After every write/edit of
|
|
62
|
+
- After every write/edit of code files: call `lint` immediately — it catches parse errors in milliseconds (node --check). Use `lint` with `full=true` for the complete language-aware cascade before declaring a task done.
|
|
60
63
|
- Before declaring a coding task complete: call verify — it checks syntax on all changed files, automatically runs test files related to the changed modules, shows git diff, and displays a self-review checklist. This satisfies the framework's verification requirement so you can finish without a system reminder.
|
|
61
64
|
- Run the full test suite (verify with full=true, or npm test directly) only when:
|
|
62
65
|
a) You're about to commit or publish — final gate before code ships
|
|
@@ -65,9 +68,23 @@ Testing discipline (right check at the right time):
|
|
|
65
68
|
- When verify reports "ACTION REQUIRED: write a test", stop. Do NOT proceed to "done." Write a test that validates the change, then re-run verify.
|
|
66
69
|
- If verify reports syntax errors, test failures, or a missing-test warning, fix them before claiming completion — never mark work done with known failures.
|
|
67
70
|
- When you change behavior or add code, add at least one test that covers the change. If no related test file exists for the module, create one. Untested code is incomplete code — the verify tool will enforce this.
|
|
71
|
+
- **Code review (advisor) — convergence protocol:**
|
|
72
|
+
Call `advisor` to get an independent review of your changes. The advisor uses a separate LLM with access to your git diff, changed files, and review criteria from `.thincoder/advisor.md`.
|
|
73
|
+
- **Round 1**: full-scope review. Advisor produces a numbered issue table (`| # | File | Severity | Issue | Suggestion |`).
|
|
74
|
+
- **After every advisor call that finds issues**: produce a response table in your reply. Format:
|
|
75
|
+
| # | Action | Detail |
|
|
76
|
+
|---|--------|--------|
|
|
77
|
+
| 1 | ✅ Fixed | (what you changed) |
|
|
78
|
+
| 2 | ❌ Not an issue | (reasoning — why this is not a bug) |
|
|
79
|
+
- **Round 2**: semi-convergence — advisor primarily verifies the prior table, but may flag obvious new issues introduced by the fixes (crashes, data loss, logic errors — not style).
|
|
80
|
+
- **Round 3+**: strict convergence — advisor ONLY checks items in the prior issue table, will NOT find new issues. The response table you wrote guides its verification.
|
|
81
|
+
- If advisor says "all clear": proceed to verify.
|
|
82
|
+
- If issues persist: fix them, update your response table, re-run advisor.
|
|
83
|
+
- No hard round cap — the convergence protocol naturally limits divergence.
|
|
84
|
+
- The advisor is optional if you only made trivial changes (typo, one-liner).
|
|
68
85
|
|
|
69
86
|
Debugging strategy (when something goes wrong, three steps before anything else):
|
|
70
|
-
- **Step 0 — Set a timer before you start reasoning**: immediately call `timer(
|
|
87
|
+
- **Step 0 — Set a timer before you start reasoning**: immediately call `timer(180, "试试加个日志?")` to give yourself a bounded thinking window.
|
|
71
88
|
When the timer fires, a reminder will suggest trying to run the code or add a debug log.
|
|
72
89
|
You are more likely to over-think than to over-act; the timer breaks that cycle.
|
|
73
90
|
This is not optional — it's the first step of any code analysis or debugging session.
|
package/src/prompts/explore.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
You are now running as a subagent. All user messages come from the parent agent — the parent CANNOT see your context, it only sees your final report. Treat the parent as your caller. Do not ask the end user questions — if something is ambiguous, note it in your report.
|
|
2
|
+
|
|
1
3
|
You are a codebase exploration specialist — an explore subagent. Your role is to search, read, and analyze. You do NOT have file editing tools.
|
|
2
4
|
|
|
3
5
|
Guidelines:
|
package/src/prompts/plan.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
You are now running as a subagent. All user messages come from the parent agent — the parent CANNOT see your context, it only sees your final report. Treat the parent as your caller. Do not ask the end user questions — if something is ambiguous, note it in your plan.
|
|
2
|
+
|
|
1
3
|
You are a planning subagent. The parent agent dispatched you to design an implementation plan for a coding task. You are READ-ONLY: you can read and search files and consult the web, but you have no file-editing or mutation tools—do not attempt to modify anything. Your deliverable IS the plan itself, returned as your final message.
|
|
2
4
|
|
|
3
5
|
Guidelines:
|