thincoder 0.7.7 → 0.7.8
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 +4 -0
- package/package.json +1 -1
- package/src/tools/bash.md +1 -0
- package/src/tools.mjs +6 -0
- package/src/tui.mjs +23 -3
package/README.md
CHANGED
|
@@ -193,6 +193,10 @@ Code conventions: pure `.mjs`, no semicolons, no npm dependencies allowed (inclu
|
|
|
193
193
|
|
|
194
194
|
## Changelog
|
|
195
195
|
|
|
196
|
+
### 0.7.8 (2026-07)
|
|
197
|
+
- **Provider config flow streamlined**: adding a provider now immediately prompts for API key (no more "go back to /provider → Set Key"). Switching to a keyless provider via `/model` also prompts for key inline. Empty input gives clear "skipped" feedback
|
|
198
|
+
- **bash tool: file writing forbidden**: models must use write/edit/insert_after/apply_patch instead of `echo`/`sed`/`printf > file`. Fixes GBK encoding corruption on Chinese Windows (cmd.exe writes redirected files in ANSI code page, not UTF-8). `PYTHONIOENCODING=utf-8` set for Python subprocesses on Windows
|
|
199
|
+
|
|
196
200
|
### 0.7.7 (2026-07)
|
|
197
201
|
- **Code review fixes (4 critical bugs)**:
|
|
198
202
|
- `gitSync` anchor never set after full `codeSync` fallback → fast path was dead in production; now `codeSync`/`docSync` write the anchor on success
|
package/package.json
CHANGED
package/src/tools/bash.md
CHANGED
|
@@ -25,3 +25,4 @@ Notes:
|
|
|
25
25
|
- Do NOT run destructive commands (rm -rf, force-push, drop table) without explicit user confirmation
|
|
26
26
|
- After commands that change files (git checkout, npm install, etc.), repo_outline and code_search may be stale — re-run them to get current results.
|
|
27
27
|
- Prefer read/glob/grep/ls for file operations inside the project — bash has no directory confinement.
|
|
28
|
+
- NEVER use bash to write or modify files (echo/sed/printf > file, cat << EOF, etc.). Use write/edit/insert_after/apply_patch instead — they handle encoding, escaping, and directory confinement correctly.
|
package/src/tools.mjs
CHANGED
|
@@ -600,6 +600,11 @@ const bashTool = {
|
|
|
600
600
|
try { child.kill("SIGKILL") } catch {} // 组杀失败时兜底杀本体
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
|
+
// Windows 中文系统默认代码页是 GBK (CP936),cmd.exe 重定向写文件时用 ANSI 代码页,
|
|
604
|
+
// chcp 65001 也改不了重定向的编码。bash 工具写含 CJK 的文件会产生 GBK——
|
|
605
|
+
// 提示词层已禁止用 bash 写文件(用 write/edit 工具替代),这里设 PYTHONIOENCODING
|
|
606
|
+
// 覆盖 Python 脚本的 stdout 编码(Python 是唯一可能正确响应环境变量的子进程)
|
|
607
|
+
const winCmd = process.platform === "win32"
|
|
603
608
|
const child = spawn(args.command, {
|
|
604
609
|
cwd: ctx.cwd,
|
|
605
610
|
shell: true,
|
|
@@ -614,6 +619,7 @@ const bashTool = {
|
|
|
614
619
|
GIT_PAGER: "cat",
|
|
615
620
|
PAGER: "cat",
|
|
616
621
|
TERM: "dumb",
|
|
622
|
+
...(winCmd ? { PYTHONIOENCODING: "utf-8" } : {}),
|
|
617
623
|
},
|
|
618
624
|
})
|
|
619
625
|
// stdout / stderr 各自独立解码(同进程通常同编码,但分开收集更干净,
|
package/src/tui.mjs
CHANGED
|
@@ -1661,7 +1661,15 @@ export async function startTUI(agent, opts = {}) {
|
|
|
1661
1661
|
await persistRaw((raw) => { raw.providers = agent.providers })
|
|
1662
1662
|
pushLabel(`❯ Provider`, ansi.bold + C.tool)
|
|
1663
1663
|
pushLine(`Added ${name} (${baseURL} / ${model})`, C.tool)
|
|
1664
|
-
|
|
1664
|
+
// 直接接 key 输入,不让用户再绕一圈
|
|
1665
|
+
askQuestion(`Enter API key for ${name} (留空跳过,之后 /provider → Set Key):`).then(async (key) => {
|
|
1666
|
+
if (key) {
|
|
1667
|
+
await setProviderKey(name, key)
|
|
1668
|
+
pushLine(`Key saved for ${name}`, C.tool)
|
|
1669
|
+
} else {
|
|
1670
|
+
pushLine(`跳过 key。之后 /provider → Set API Key 配置`, C.dim)
|
|
1671
|
+
}
|
|
1672
|
+
})
|
|
1665
1673
|
})
|
|
1666
1674
|
return
|
|
1667
1675
|
}
|
|
@@ -1680,7 +1688,10 @@ export async function startTUI(agent, opts = {}) {
|
|
|
1680
1688
|
entries: keyEntries,
|
|
1681
1689
|
onSelect: (se) => {
|
|
1682
1690
|
askQuestion(`Enter API key for ${se.name}:`).then(async (key) => {
|
|
1683
|
-
if (!key)
|
|
1691
|
+
if (!key) {
|
|
1692
|
+
pushLine(`跳过 key 输入`, C.dim)
|
|
1693
|
+
return
|
|
1694
|
+
}
|
|
1684
1695
|
await setProviderKey(se.name, key)
|
|
1685
1696
|
})
|
|
1686
1697
|
},
|
|
@@ -2142,7 +2153,16 @@ export async function startTUI(agent, opts = {}) {
|
|
|
2142
2153
|
agent.config.activeProvider = item.provider
|
|
2143
2154
|
pushLabel(`❯ Model`, ansi.bold + C.tool)
|
|
2144
2155
|
pushLine(`Switched to ${item.provider} / ${item.model}${thresholdNote} (persisted)`, C.tool)
|
|
2145
|
-
if (!agent.provider.apiKey)
|
|
2156
|
+
if (!agent.provider.apiKey) {
|
|
2157
|
+
pushLine(`Provider has no key`, C.warn)
|
|
2158
|
+
askQuestion(`Enter API key for ${item.provider} (留空跳过):`).then(async (key) => {
|
|
2159
|
+
if (key) {
|
|
2160
|
+
await setProviderKey(item.provider, key)
|
|
2161
|
+
} else {
|
|
2162
|
+
pushLine(`跳过。之后 /provider → Set API Key 配置`, C.dim)
|
|
2163
|
+
}
|
|
2164
|
+
})
|
|
2165
|
+
}
|
|
2146
2166
|
}
|
|
2147
2167
|
|
|
2148
2168
|
/** /distill:从current会话提取候选,逐条 y/n 确认后入库 */
|