thatgfsj-code 1.0.3 → 3.0.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 +192 -0
- package/DEVELOPMENT.md +286 -0
- package/dist/app/index.d.ts +40 -3
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +87 -12
- package/dist/app/index.js.map +1 -1
- package/dist/cache/fingerprint.d.ts +49 -0
- package/dist/cache/fingerprint.d.ts.map +1 -0
- package/dist/cache/fingerprint.js +100 -0
- package/dist/cache/fingerprint.js.map +1 -0
- package/dist/cache/index.d.ts +15 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +15 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/smartModel.d.ts +40 -0
- package/dist/cache/smartModel.d.ts.map +1 -0
- package/dist/cache/smartModel.js +43 -0
- package/dist/cache/smartModel.js.map +1 -0
- package/dist/cache/stats.d.ts +93 -0
- package/dist/cache/stats.d.ts.map +1 -0
- package/dist/cache/stats.js +155 -0
- package/dist/cache/stats.js.map +1 -0
- package/dist/cache/volatile.d.ts +32 -0
- package/dist/cache/volatile.d.ts.map +1 -0
- package/dist/cache/volatile.js +44 -0
- package/dist/cache/volatile.js.map +1 -0
- package/dist/cmd/index.d.ts +21 -0
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +155 -31
- package/dist/cmd/index.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +8 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/types.d.ts +14 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/llm/anthropic.d.ts +55 -5
- package/dist/llm/anthropic.d.ts.map +1 -1
- package/dist/llm/anthropic.js +172 -26
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/index.d.ts +26 -8
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +83 -15
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/openai.d.ts +28 -8
- package/dist/llm/openai.d.ts.map +1 -1
- package/dist/llm/openai.js +58 -8
- package/dist/llm/openai.js.map +1 -1
- package/dist/llm/provider.d.ts +40 -8
- package/dist/llm/provider.d.ts.map +1 -1
- package/dist/llm/provider.js +8 -1
- package/dist/llm/provider.js.map +1 -1
- package/dist/prompts/index.d.ts +32 -0
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +33 -11
- package/dist/prompts/index.js.map +1 -1
- package/dist/session/index.d.ts +43 -3
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +114 -17
- package/dist/session/index.js.map +1 -1
- package/dist/skills/brainstorming.js +33 -33
- package/dist/skills/code-review.js +35 -35
- package/dist/skills/executing-plans.js +18 -18
- package/dist/skills/frontend-design.js +25 -25
- package/dist/skills/git-workflow.js +26 -26
- package/dist/skills/improve-architecture.js +28 -28
- package/dist/skills/neuroweave.js +37 -37
- package/dist/skills/playwright.js +62 -62
- package/dist/skills/prototype.js +20 -20
- package/dist/skills/subagent.js +19 -19
- package/dist/skills/supabase.js +34 -34
- package/dist/skills/systematic-debugging.js +34 -34
- package/dist/skills/tdd.js +29 -29
- package/dist/skills/triage.js +25 -25
- package/dist/skills/verification.js +22 -22
- package/dist/skills/writing-plans.js +32 -32
- package/dist/tools/nwt.js +16 -16
- package/dist/tui/app.d.ts.map +1 -1
- package/dist/tui/app.js +9 -2
- package/dist/tui/app.js.map +1 -1
- package/dist/tui/components/ChatList.d.ts.map +1 -1
- package/dist/tui/components/ChatList.js +4 -3
- package/dist/tui/components/ChatList.js.map +1 -1
- package/dist/tui/components/Header.d.ts +8 -0
- package/dist/tui/components/Header.d.ts.map +1 -1
- package/dist/tui/components/Header.js +17 -3
- package/dist/tui/components/Header.js.map +1 -1
- package/dist/tui/components/InitWizard.d.ts +12 -1
- package/dist/tui/components/InitWizard.d.ts.map +1 -1
- package/dist/tui/components/InitWizard.js +58 -3
- package/dist/tui/components/InitWizard.js.map +1 -1
- package/dist/tui/components/ToolCall.d.ts +1 -1
- package/dist/tui/components/ToolCall.d.ts.map +1 -1
- package/dist/tui/components/ToolCall.js +4 -4
- package/dist/tui/components/ToolCall.js.map +1 -1
- package/dist/tui/hooks/useChat.d.ts +22 -0
- package/dist/tui/hooks/useChat.d.ts.map +1 -1
- package/dist/tui/hooks/useChat.js +127 -50
- package/dist/tui/hooks/useChat.js.map +1 -1
- package/dist/tui/hooks/useCommands.d.ts.map +1 -1
- package/dist/tui/hooks/useCommands.js +78 -0
- package/dist/tui/hooks/useCommands.js.map +1 -1
- package/dist/types.d.ts +79 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/stableStringify.d.ts +21 -0
- package/dist/utils/stableStringify.d.ts.map +1 -0
- package/dist/utils/stableStringify.js +53 -0
- package/dist/utils/stableStringify.js.map +1 -0
- package/dist/utils/thinking.d.ts +59 -0
- package/dist/utils/thinking.d.ts.map +1 -0
- package/dist/utils/thinking.js +104 -0
- package/dist/utils/thinking.js.map +1 -0
- package/install.bat +63 -0
- package/install.ps1 +238 -0
- package/install.sh +113 -0
- package/package.json +7 -4
- package/src/app/index.ts +180 -108
- package/src/cache/fingerprint.ts +101 -0
- package/src/cache/index.ts +15 -0
- package/src/cache/smartModel.ts +52 -0
- package/src/cache/stats.ts +199 -0
- package/src/cache/volatile.ts +47 -0
- package/src/cmd/index.tsx +288 -160
- package/src/config/index.ts +156 -148
- package/src/config/providers.ts +234 -234
- package/src/config/types.ts +67 -53
- package/src/hooks/index.ts +111 -111
- package/src/llm/anthropic.ts +388 -243
- package/src/llm/gemini.ts +169 -169
- package/src/llm/index.ts +265 -200
- package/src/llm/openai.ts +243 -196
- package/src/llm/provider.ts +66 -34
- package/src/prompts/index.ts +260 -220
- package/src/session/compactor.ts +103 -103
- package/src/session/index.ts +181 -87
- package/src/session/message.ts +42 -42
- package/src/skills/brainstorming.ts +43 -43
- package/src/skills/code-review.ts +45 -45
- package/src/skills/executing-plans.ts +27 -27
- package/src/skills/frontend-design.ts +35 -35
- package/src/skills/git-workflow.ts +36 -36
- package/src/skills/improve-architecture.ts +38 -38
- package/src/skills/index.ts +136 -136
- package/src/skills/neuroweave.ts +47 -47
- package/src/skills/playwright.ts +72 -72
- package/src/skills/prototype.ts +30 -30
- package/src/skills/subagent.ts +28 -28
- package/src/skills/supabase.ts +44 -44
- package/src/skills/systematic-debugging.ts +44 -44
- package/src/skills/tdd.ts +39 -39
- package/src/skills/triage.ts +35 -35
- package/src/skills/verification.ts +31 -31
- package/src/skills/writing-plans.ts +42 -42
- package/src/tools/nwt.ts +598 -598
- package/src/tools/types.ts +122 -122
- package/src/tui/app.tsx +199 -186
- package/src/tui/components/ChatList.tsx +41 -32
- package/src/tui/components/ChatMessage.tsx +54 -54
- package/src/tui/components/Header.tsx +56 -28
- package/src/tui/components/InitWizard.tsx +217 -132
- package/src/tui/components/Markdown.tsx +35 -35
- package/src/tui/components/ModelSelector.tsx +87 -87
- package/src/tui/components/StatusBar.tsx +30 -30
- package/src/tui/components/Thinking.tsx +17 -17
- package/src/tui/components/ToolCall.tsx +102 -71
- package/src/tui/components/UserInput.tsx +131 -131
- package/src/tui/hooks/useChat.ts +287 -194
- package/src/tui/hooks/useCommands.ts +234 -154
- package/src/tui/index.ts +6 -6
- package/src/tui/welcome.ts +177 -177
- package/src/types.ts +104 -42
- package/src/utils/diff.ts +71 -71
- package/src/utils/project.ts +99 -99
- package/src/utils/stableStringify.ts +47 -0
- package/src/utils/thinking.ts +119 -0
- package/tests/cache/fingerprint.test.ts +75 -0
- package/tests/cache/stableStringify.test.ts +43 -0
- package/tests/cache/stats.test.ts +146 -0
- package/tests/cache/volatile.test.ts +75 -0
- package/tests/smoke-pollution.mjs +78 -0
- package/tests/smoke-thinking.mjs +110 -0
- package/tests/smoke-tool-stream.mjs +69 -0
- package/tests/smoke-tool.mjs +117 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thinking block extraction + compression
|
|
3
|
+
*
|
|
4
|
+
* Models that aren't truly reasoning-capable (Qwen, DeepSeek-V3 chat,
|
|
5
|
+
* Kimi, etc.) still emit `<think>...</think>` blocks as plain text
|
|
6
|
+
* inside their response. These blocks can be hundreds of lines of
|
|
7
|
+
* internal monologue that the user doesn't want to see scroll by.
|
|
8
|
+
*
|
|
9
|
+
* opencode handles this by separating reasoning into its own stream
|
|
10
|
+
* part at the protocol level. We don't have that luxury — the model
|
|
11
|
+
* is emitting everything as a single `content` field. So we use the
|
|
12
|
+
* same regex-strip approach opencode uses internally (see
|
|
13
|
+
* packages/opencode/src/session/prompt.ts line 244).
|
|
14
|
+
*
|
|
15
|
+
* Three block delimiters are supported:
|
|
16
|
+
* 1. <think>...</think> — DeepSeek / Qwen / Kimi
|
|
17
|
+
* 2. <reasoning>...</reasoning> — OpenRouter-style
|
|
18
|
+
* 3. [THINK]...[/THINK] — some custom fine-tunes
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* const { thinking, conclusion } = splitThinking(fullContent);
|
|
22
|
+
* if (thinking && compress) {
|
|
23
|
+
* render(`💭 ${summarize(thinking)}\n${conclusion}`);
|
|
24
|
+
* } else {
|
|
25
|
+
* render(fullContent);
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
export interface ThinkingSplit {
|
|
29
|
+
/** Raw `<think>...` content, or empty if none. */
|
|
30
|
+
thinking: string;
|
|
31
|
+
/** Content with thinking blocks stripped + trimmed. */
|
|
32
|
+
conclusion: string;
|
|
33
|
+
/** How many lines the thinking block spanned. */
|
|
34
|
+
thinkingLines: number;
|
|
35
|
+
/** First non-empty line of the thinking block (heuristic summary). */
|
|
36
|
+
thinkingHint: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* All known thinking-block delimiters, in priority order. The regex
|
|
40
|
+
* flags `gi` (global, case-insensitive) so `[THINK]` and `<think>`
|
|
41
|
+
* are both caught, and so multiple blocks collapse cleanly.
|
|
42
|
+
*/
|
|
43
|
+
declare const THINKING_PATTERNS: RegExp[];
|
|
44
|
+
export declare function splitThinking(content: string): ThinkingSplit;
|
|
45
|
+
/**
|
|
46
|
+
* Build a short, single-line summary of a thinking block, suitable
|
|
47
|
+
* for collapsed display. Returns something like:
|
|
48
|
+
* "💭 thought for 24 lines: The user is asking about Win+E..."
|
|
49
|
+
* Falls back to "(no hint)" if the block is empty.
|
|
50
|
+
*/
|
|
51
|
+
export declare function summarizeThinking(split: ThinkingSplit): string;
|
|
52
|
+
/**
|
|
53
|
+
* Render full content with thinking blocks compressed (collapsed to
|
|
54
|
+
* a single-line indicator). If `showThinking` is true, returns the
|
|
55
|
+
* content unchanged (debug mode).
|
|
56
|
+
*/
|
|
57
|
+
export declare function compressThinking(content: string, showThinking?: boolean): string;
|
|
58
|
+
export { THINKING_PATTERNS };
|
|
59
|
+
//# sourceMappingURL=thinking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking.d.ts","sourceRoot":"","sources":["../../src/utils/thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,QAAA,MAAM,iBAAiB,EAAE,MAAM,EAI9B,CAAC;AAEF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAqB5D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAM9D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,MAAM,CAMvF;AAoBD,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thinking block extraction + compression
|
|
3
|
+
*
|
|
4
|
+
* Models that aren't truly reasoning-capable (Qwen, DeepSeek-V3 chat,
|
|
5
|
+
* Kimi, etc.) still emit `<think>...</think>` blocks as plain text
|
|
6
|
+
* inside their response. These blocks can be hundreds of lines of
|
|
7
|
+
* internal monologue that the user doesn't want to see scroll by.
|
|
8
|
+
*
|
|
9
|
+
* opencode handles this by separating reasoning into its own stream
|
|
10
|
+
* part at the protocol level. We don't have that luxury — the model
|
|
11
|
+
* is emitting everything as a single `content` field. So we use the
|
|
12
|
+
* same regex-strip approach opencode uses internally (see
|
|
13
|
+
* packages/opencode/src/session/prompt.ts line 244).
|
|
14
|
+
*
|
|
15
|
+
* Three block delimiters are supported:
|
|
16
|
+
* 1. <think>...</think> — DeepSeek / Qwen / Kimi
|
|
17
|
+
* 2. <reasoning>...</reasoning> — OpenRouter-style
|
|
18
|
+
* 3. [THINK]...[/THINK] — some custom fine-tunes
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* const { thinking, conclusion } = splitThinking(fullContent);
|
|
22
|
+
* if (thinking && compress) {
|
|
23
|
+
* render(`💭 ${summarize(thinking)}\n${conclusion}`);
|
|
24
|
+
* } else {
|
|
25
|
+
* render(fullContent);
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* All known thinking-block delimiters, in priority order. The regex
|
|
30
|
+
* flags `gi` (global, case-insensitive) so `[THINK]` and `<think>`
|
|
31
|
+
* are both caught, and so multiple blocks collapse cleanly.
|
|
32
|
+
*/
|
|
33
|
+
const THINKING_PATTERNS = [
|
|
34
|
+
/<think>[\s\S]*?<\/think>/gi,
|
|
35
|
+
/<reasoning>[\s\S]*?<\/reasoning>/gi,
|
|
36
|
+
/\[THINK\][\s\S]*?\[\/THINK\]/gi,
|
|
37
|
+
];
|
|
38
|
+
export function splitThinking(content) {
|
|
39
|
+
if (!content) {
|
|
40
|
+
return { thinking: '', conclusion: '', thinkingLines: 0, thinkingHint: '' };
|
|
41
|
+
}
|
|
42
|
+
let thinking = '';
|
|
43
|
+
let remaining = content;
|
|
44
|
+
for (const pat of THINKING_PATTERNS) {
|
|
45
|
+
const matches = remaining.match(pat);
|
|
46
|
+
if (matches) {
|
|
47
|
+
thinking += matches.join('\n');
|
|
48
|
+
remaining = remaining.replace(pat, '');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const conclusion = remaining.trim();
|
|
52
|
+
const thinkingLines = thinking ? thinking.split('\n').length : 0;
|
|
53
|
+
const thinkingHint = firstNonEmptyLine(thinking);
|
|
54
|
+
return { thinking, conclusion, thinkingLines, thinkingHint };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build a short, single-line summary of a thinking block, suitable
|
|
58
|
+
* for collapsed display. Returns something like:
|
|
59
|
+
* "💭 thought for 24 lines: The user is asking about Win+E..."
|
|
60
|
+
* Falls back to "(no hint)" if the block is empty.
|
|
61
|
+
*/
|
|
62
|
+
export function summarizeThinking(split) {
|
|
63
|
+
if (!split.thinking)
|
|
64
|
+
return '';
|
|
65
|
+
const hint = split.thinkingHint.length > 60
|
|
66
|
+
? split.thinkingHint.slice(0, 57) + '...'
|
|
67
|
+
: split.thinkingHint;
|
|
68
|
+
return `💭 thought for ${split.thinkingLines} line${split.thinkingLines === 1 ? '' : 's'}${hint ? `: ${hint}` : ''}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Render full content with thinking blocks compressed (collapsed to
|
|
72
|
+
* a single-line indicator). If `showThinking` is true, returns the
|
|
73
|
+
* content unchanged (debug mode).
|
|
74
|
+
*/
|
|
75
|
+
export function compressThinking(content, showThinking = false) {
|
|
76
|
+
if (showThinking || !content)
|
|
77
|
+
return content;
|
|
78
|
+
const split = splitThinking(content);
|
|
79
|
+
if (!split.thinking)
|
|
80
|
+
return content;
|
|
81
|
+
const summary = summarizeThinking(split);
|
|
82
|
+
return summary ? `${summary}\n${split.conclusion}` : split.conclusion;
|
|
83
|
+
}
|
|
84
|
+
function firstNonEmptyLine(s) {
|
|
85
|
+
if (!s)
|
|
86
|
+
return '';
|
|
87
|
+
for (const line of s.split('\n')) {
|
|
88
|
+
// Strip any leading/trailing thinking-tag fragments that may have
|
|
89
|
+
// been captured by the regex (e.g. "<think>The user said..."
|
|
90
|
+
// or "...</think>"). We strip ALL occurrences to handle the
|
|
91
|
+
// case where the first line wraps across a tag.
|
|
92
|
+
const t = line
|
|
93
|
+
.trim()
|
|
94
|
+
.replace(/<\/?think>/gi, '')
|
|
95
|
+
.replace(/<\/?reasoning>/gi, '')
|
|
96
|
+
.replace(/\[\/?THINK\]/gi, '')
|
|
97
|
+
.trim();
|
|
98
|
+
if (t)
|
|
99
|
+
return t;
|
|
100
|
+
}
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
export { THINKING_PATTERNS };
|
|
104
|
+
//# sourceMappingURL=thinking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking.js","sourceRoot":"","sources":["../../src/utils/thinking.ts"],"names":[],"mappings":"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"}
|
package/install.bat
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
chcp 65001 >nul
|
|
3
|
+
title Thatgfsj Code 安装向导
|
|
4
|
+
echo.
|
|
5
|
+
echo Thatgfsj Code 一键安装
|
|
6
|
+
echo =====================
|
|
7
|
+
echo.
|
|
8
|
+
|
|
9
|
+
echo [*] 检查环境...
|
|
10
|
+
echo.
|
|
11
|
+
|
|
12
|
+
:: Check PowerShell
|
|
13
|
+
powershell -Version >nul 2>&1
|
|
14
|
+
if %errorlevel% neq 0 (
|
|
15
|
+
echo [错误] 需要 PowerShell,请升级: https://aka.ms/powershell
|
|
16
|
+
pause
|
|
17
|
+
exit /b 1
|
|
18
|
+
)
|
|
19
|
+
echo [OK] PowerShell 已就绪
|
|
20
|
+
|
|
21
|
+
:: Check Node.js
|
|
22
|
+
for /f "delims=" %%i in ('powershell -Command "node --version 2^>nul"') do set NODE_VERSION=%%i
|
|
23
|
+
if defined NODE_VERSION (
|
|
24
|
+
echo [OK] Node.js %NODE_VERSION% 已安装
|
|
25
|
+
) else (
|
|
26
|
+
echo.
|
|
27
|
+
echo [!] 未检测到 Node.js,开始自动安装...
|
|
28
|
+
echo.
|
|
29
|
+
|
|
30
|
+
:: Try winget
|
|
31
|
+
where winget >nul 2>&1
|
|
32
|
+
if %errorlevel% equ 0 (
|
|
33
|
+
echo [*] 正在通过 winget 安装 Node.js...
|
|
34
|
+
winget install OpenJS.NodeJS.LTS --source winget --accept-package-agreements --accept-source-agreements
|
|
35
|
+
echo.
|
|
36
|
+
echo [OK] Node.js 安装完成
|
|
37
|
+
echo [!] 请重新打开一个 CMD 然后再次运行此脚本
|
|
38
|
+
pause
|
|
39
|
+
exit /b 0
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
:: Fallback: manual download
|
|
43
|
+
echo [*] 正在下载 Node.js 安装包...
|
|
44
|
+
powershell -Command "Start-Process 'https://nodejs.org/' -Verb Open"
|
|
45
|
+
echo.
|
|
46
|
+
echo [!] 请手动安装 Node.js LTS 版本
|
|
47
|
+
echo [!] 安装完成后,重新运行此脚本
|
|
48
|
+
pause
|
|
49
|
+
exit /b 0
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
:: Download install.ps1
|
|
53
|
+
echo.
|
|
54
|
+
echo [*] 正在下载安装程序...
|
|
55
|
+
powershell -Command "Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/Thatgfsj/thatgfsj-code/main/install.ps1' -OutFile '%TEMP%\thatgfsj_install.ps1'"
|
|
56
|
+
|
|
57
|
+
echo.
|
|
58
|
+
echo [*] 启动安装向导...
|
|
59
|
+
echo.
|
|
60
|
+
powershell -ExecutionPolicy Bypass -File "%TEMP%\thatgfsj_install.ps1"
|
|
61
|
+
|
|
62
|
+
echo.
|
|
63
|
+
pause
|
package/install.ps1
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Thatgfsj Code Installer for Windows
|
|
2
|
+
# Usage:
|
|
3
|
+
# powershell -c "irm https://raw.githubusercontent.com/Thatgfsj/thatgfsj-code/main/install.ps1 | iex"
|
|
4
|
+
# powershell -c "& ([scriptblock]::Create((irm https://raw.githubusercontent.com/Thatgfsj/thatgfsj-code/main/install.ps1)))"
|
|
5
|
+
|
|
6
|
+
param(
|
|
7
|
+
[switch]$NoOpen,
|
|
8
|
+
[switch]$DryRun
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
$ErrorActionPreference = "Stop"
|
|
12
|
+
|
|
13
|
+
# Colors
|
|
14
|
+
function Write-Step { param($msg) Write-Host "[*] $msg" -ForegroundColor Yellow }
|
|
15
|
+
function Write-Success { param($msg) Write-Host "[✓] $msg" -ForegroundColor Green }
|
|
16
|
+
function Write-Error { param($msg) Write-Host "[✗] $msg" -ForegroundColor Red }
|
|
17
|
+
function Write-Info { param($msg) Write-Host " $msg" -ForegroundColor Gray }
|
|
18
|
+
|
|
19
|
+
Write-Host ""
|
|
20
|
+
Write-Host " Thatgfsj Code 安装向导" -ForegroundColor Cyan
|
|
21
|
+
Write-Host " =======================" -ForegroundColor Cyan
|
|
22
|
+
Write-Host ""
|
|
23
|
+
|
|
24
|
+
if ($DryRun) {
|
|
25
|
+
Write-Host "[DRY RUN] 仅显示将要执行的操作" -ForegroundColor Yellow
|
|
26
|
+
Write-Host ""
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# ============== Step 1: Check PowerShell ==============
|
|
30
|
+
Write-Step "检查 PowerShell 版本..."
|
|
31
|
+
|
|
32
|
+
if ($PSVersionTable.PSVersion.Major -lt 5) {
|
|
33
|
+
Write-Error "需要 PowerShell 5.0 或更高版本"
|
|
34
|
+
Write-Host "请升级您的 PowerShell: https://aka.ms/powershell" -ForegroundColor Gray
|
|
35
|
+
exit 1
|
|
36
|
+
}
|
|
37
|
+
Write-Success "PowerShell $($PSVersionTable.PSVersion) 检测正常"
|
|
38
|
+
|
|
39
|
+
# ============== Step 2: Check/Fetch Node.js ==============
|
|
40
|
+
Write-Step "检查 Node.js..."
|
|
41
|
+
|
|
42
|
+
function Test-NodeInstalled {
|
|
43
|
+
try {
|
|
44
|
+
$nodeVersion = node --version 2>$null
|
|
45
|
+
if ($nodeVersion) {
|
|
46
|
+
$version = [int]($nodeVersion -replace 'v(\d+)\..*', '$1')
|
|
47
|
+
return @{ installed = $true; version = $nodeVersion; major = $version }
|
|
48
|
+
}
|
|
49
|
+
} catch {}
|
|
50
|
+
return @{ installed = $false; version = $null; major = 0 }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
$nodeStatus = Test-NodeInstalled
|
|
54
|
+
if ($nodeStatus.installed -and $nodeStatus.major -ge 18) {
|
|
55
|
+
Write-Success "Node.js $($nodeStatus.version) 已安装"
|
|
56
|
+
} else {
|
|
57
|
+
Write-Host " 未检测到 Node.js 18+,开始安装..." -ForegroundColor Gray
|
|
58
|
+
|
|
59
|
+
# Try winget first
|
|
60
|
+
if (Get-Command winget -ErrorAction SilentlyContinue) {
|
|
61
|
+
Write-Info "使用 winget 安装..."
|
|
62
|
+
winget install OpenJS.NodeJS.LTS --source winget --accept-package-agreements --accept-source-agreements
|
|
63
|
+
|
|
64
|
+
# Refresh PATH
|
|
65
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
|
66
|
+
|
|
67
|
+
$nodeStatus = Test-NodeInstalled
|
|
68
|
+
if ($nodeStatus.installed) {
|
|
69
|
+
Write-Success "Node.js 安装完成"
|
|
70
|
+
} else {
|
|
71
|
+
Write-Host " 需要重启 PowerShell 后重新运行安装" -ForegroundColor Yellow
|
|
72
|
+
exit 0
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
# Try choco
|
|
76
|
+
elseif (Get-Command choco -ErrorAction SilentlyContinue) {
|
|
77
|
+
Write-Info "使用 Chocolatey 安装..."
|
|
78
|
+
choco install nodejs-lts -y
|
|
79
|
+
Write-Success "Node.js 安装完成 (可能需要重启)"
|
|
80
|
+
}
|
|
81
|
+
# Manual fallback
|
|
82
|
+
else {
|
|
83
|
+
Write-Host ""
|
|
84
|
+
Write-Error "未检测到包管理器 (winget/choco/scoop)"
|
|
85
|
+
Write-Host ""
|
|
86
|
+
Write-Host "请手动安装 Node.js:" -ForegroundColor Yellow
|
|
87
|
+
Write-Host " 1. 访问 https://nodejs.org" -ForegroundColor Gray
|
|
88
|
+
Write-Host " 2. 下载 LTS 版本 (推荐 v20 或 v22)" -ForegroundColor Gray
|
|
89
|
+
Write-Host " 3. 运行安装程序" -ForegroundColor Gray
|
|
90
|
+
Write-Host " 4. 重新运行此安装脚本" -ForegroundColor Gray
|
|
91
|
+
Write-Host ""
|
|
92
|
+
exit 1
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# ============== Step 3: Clone/Update Repository ==============
|
|
97
|
+
Write-Step "准备安装 Thatgfsj Code..."
|
|
98
|
+
|
|
99
|
+
$installDir = Join-Path $env:USERPROFILE "thatgfsj-code"
|
|
100
|
+
|
|
101
|
+
if (Test-Path $installDir) {
|
|
102
|
+
Write-Info "检测到已有安装,正在更新..."
|
|
103
|
+
if (-not $DryRun) {
|
|
104
|
+
Set-Location $installDir
|
|
105
|
+
git pull origin main 2>$null
|
|
106
|
+
if ($LASTEXITCODE -ne 0) {
|
|
107
|
+
# If pull fails, re-clone
|
|
108
|
+
Remove-Item $installDir -Recurse -Force
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
if (-not $DryRun) {
|
|
113
|
+
Write-Info "正在克隆仓库..."
|
|
114
|
+
git clone https://github.com/Thatgfsj/thatgfsj-code.git $installDir
|
|
115
|
+
Set-Location $installDir
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (-not (Test-Path (Join-Path $installDir "package.json"))) {
|
|
120
|
+
Write-Error "安装目录无效: $installDir"
|
|
121
|
+
exit 1
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Write-Success "代码准备完成: $installDir"
|
|
125
|
+
|
|
126
|
+
# ============== Step 4: Install Dependencies ==============
|
|
127
|
+
Write-Step "安装依赖..."
|
|
128
|
+
|
|
129
|
+
if (-not $DryRun) {
|
|
130
|
+
Set-Location $installDir
|
|
131
|
+
npm install
|
|
132
|
+
if ($LASTEXITCODE -ne 0) {
|
|
133
|
+
Write-Error "npm install 失败"
|
|
134
|
+
exit 1
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
Write-Info "编译 TypeScript..."
|
|
138
|
+
npm run build
|
|
139
|
+
if ($LASTEXITCODE -ne 0) {
|
|
140
|
+
Write-Error "编译失败"
|
|
141
|
+
exit 1
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
Write-Success "依赖安装完成"
|
|
145
|
+
|
|
146
|
+
# ============== Step 5: Link Command ==============
|
|
147
|
+
Write-Step "设置命令..."
|
|
148
|
+
|
|
149
|
+
if (-not $DryRun) {
|
|
150
|
+
npm link
|
|
151
|
+
}
|
|
152
|
+
Write-Success "命令 'gfcode' 已可用"
|
|
153
|
+
|
|
154
|
+
# ============== Step 6: Setup API Key ==============
|
|
155
|
+
Write-Host ""
|
|
156
|
+
Write-Step "配置 API Key (可选)..."
|
|
157
|
+
|
|
158
|
+
$apiKeySet = $false
|
|
159
|
+
$providers = @{
|
|
160
|
+
"1" = @{name="SiliconFlow (推荐)"; var="SILICONFLOW_API_KEY"; url="https://siliconflow.cn"}
|
|
161
|
+
"2" = @{name="MiniMax"; var="MINIMAX_API_KEY"; url="https://platform.minimax.io"}
|
|
162
|
+
"3" = @{name="OpenAI"; var="OPENAI_API_KEY"; url="https://platform.openai.com"}
|
|
163
|
+
"4" = @{name="Anthropic"; var="ANTHROPIC_API_KEY"; url="https://www.anthropic.com"}
|
|
164
|
+
"5" = @{name="Google Gemini"; var="GEMINI_API_KEY"; url="https://aistudio.google.com/app/apikey"}
|
|
165
|
+
"6" = @{name="跳过 (稍后配置)"; var=""; url=""}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
Write-Host ""
|
|
169
|
+
Write-Host " 选择 AI Provider:" -ForegroundColor White
|
|
170
|
+
Write-Host ""
|
|
171
|
+
foreach ($key in $providers.Keys | Sort-Object) {
|
|
172
|
+
$p = $providers[$key]
|
|
173
|
+
Write-Host " $key. $($p.name)" -ForegroundColor Gray
|
|
174
|
+
}
|
|
175
|
+
Write-Host ""
|
|
176
|
+
|
|
177
|
+
if ($NoOpen) {
|
|
178
|
+
Write-Host " 使用 --NoOpen 跳过配置" -ForegroundColor Gray
|
|
179
|
+
} else {
|
|
180
|
+
$choice = Read-Host " 请选择 (1-6, 直接回车跳过)"
|
|
181
|
+
|
|
182
|
+
if ($choice -and $providers.ContainsKey($choice)) {
|
|
183
|
+
$selected = $providers[$choice]
|
|
184
|
+
if ($selected.var) {
|
|
185
|
+
Write-Host ""
|
|
186
|
+
Write-Host " 访问 $($selected.url) 获取 API Key" -ForegroundColor Cyan
|
|
187
|
+
Write-Host " 获取后粘贴到下方" -ForegroundColor Gray
|
|
188
|
+
Write-Host ""
|
|
189
|
+
|
|
190
|
+
$key = Read-Host " 请输入 API Key (输入后回车)"
|
|
191
|
+
|
|
192
|
+
if ($key) {
|
|
193
|
+
# Save to config file
|
|
194
|
+
$configDir = Join-Path $env:USERPROFILE ".thatgfsj"
|
|
195
|
+
if (-not (Test-Path $configDir)) {
|
|
196
|
+
New-Item -ItemType Directory -Path $configDir -Force | Out-Null
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
$configFile = Join-Path $configDir "config.json"
|
|
200
|
+
$config = @{
|
|
201
|
+
model = "Qwen/Qwen2.5-7B-Instruct"
|
|
202
|
+
apiKey = $key
|
|
203
|
+
provider = "siliconflow"
|
|
204
|
+
temperature = 0.7
|
|
205
|
+
maxTokens = 4096
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# Set provider-specific defaults
|
|
209
|
+
switch ($choice) {
|
|
210
|
+
"1" { $config.provider = "siliconflow"; $config.model = "Qwen/Qwen2.5-7B-Instruct" }
|
|
211
|
+
"2" { $config.provider = "minimax"; $config.model = "MiniMax-M2.5" }
|
|
212
|
+
"3" { $config.provider = "openai"; $config.model = "gpt-4o-mini" }
|
|
213
|
+
"4" { $config.provider = "anthropic"; $config.model = "claude-3-haiku-20240307" }
|
|
214
|
+
"5" { $config.provider = "gemini"; $config.model = "gemini-1.5-flash-8b" }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
$config | ConvertTo-Json | Set-Content $configFile -Encoding UTF8
|
|
218
|
+
Write-Success "配置已保存到: $configFile"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# ============== Done ==============
|
|
225
|
+
Write-Host ""
|
|
226
|
+
Write-Host " ======================================" -ForegroundColor Cyan
|
|
227
|
+
Write-Success " 安装完成!"
|
|
228
|
+
Write-Host " ======================================" -ForegroundColor Cyan
|
|
229
|
+
Write-Host ""
|
|
230
|
+
Write-Host " 使用方法:" -ForegroundColor White
|
|
231
|
+
Write-Host " gfcode init - 重新配置" -ForegroundColor Gray
|
|
232
|
+
Write-Host " gfcode - 启动交互模式" -ForegroundColor Gray
|
|
233
|
+
Write-Host " gfcode '你的问题' - 直接提问" -ForegroundColor Gray
|
|
234
|
+
Write-Host " gfcode explain '代码' - 解释代码" -ForegroundColor Gray
|
|
235
|
+
Write-Host " gfcode debug '代码' - 调试代码" -ForegroundColor Gray
|
|
236
|
+
Write-Host ""
|
|
237
|
+
Write-Host " 文档: https://github.com/Thatgfsj/thatgfsj-code" -ForegroundColor Gray
|
|
238
|
+
Write-Host ""
|
package/install.sh
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Thatgfsj Code Installer for macOS/Linux
|
|
3
|
+
# Usage: curl -sL https://raw.githubusercontent.com/Thatgfsj/thatgfsj-code/main/install.sh | bash
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Colors
|
|
8
|
+
RED='\033[0;31m'
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
YELLOW='\033[1;33m'
|
|
11
|
+
CYAN='\033[0;36m'
|
|
12
|
+
NC='\033[0m' # No Color
|
|
13
|
+
|
|
14
|
+
echo ""
|
|
15
|
+
echo -e "${CYAN} Thatgfsj Code 安装向导${NC}"
|
|
16
|
+
echo -e "${CYAN} =======================${NC}"
|
|
17
|
+
echo ""
|
|
18
|
+
|
|
19
|
+
# ============== Step 1: Check Node.js ==============
|
|
20
|
+
echo -e "${YELLOW}[*] 检查 Node.js...${NC}"
|
|
21
|
+
|
|
22
|
+
if command -v node &> /dev/null; then
|
|
23
|
+
NODE_VERSION=$(node --version)
|
|
24
|
+
MAJOR_VERSION=$(echo $NODE_VERSION | cut -d'v' -f2 | cut -d'.' -f1)
|
|
25
|
+
if [ "$MAJOR_VERSION" -ge 18 ]; then
|
|
26
|
+
echo -e "${GREEN}[✓] Node.js $NODE_VERSION 已安装${NC}"
|
|
27
|
+
else
|
|
28
|
+
echo -e "${RED}[✗] Node.js 版本过低,需要 v18+${NC}"
|
|
29
|
+
echo " 请访问 https://nodejs.org 升级"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
else
|
|
33
|
+
echo -e "${YELLOW}[*] 未检测到 Node.js,开始安装...${NC}"
|
|
34
|
+
|
|
35
|
+
# Try Homebrew (macOS)
|
|
36
|
+
if command -v brew &> /dev/null; then
|
|
37
|
+
echo -e "${YELLOW}[*] 使用 Homebrew 安装...${NC}"
|
|
38
|
+
brew install node
|
|
39
|
+
# Try apt (Ubuntu/Debian)
|
|
40
|
+
elif command -v apt-get &> /dev/null; then
|
|
41
|
+
echo -e "${YELLOW}[*] 使用 apt 安装...${NC}"
|
|
42
|
+
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
43
|
+
sudo apt-get install -y nodejs
|
|
44
|
+
# Try yum (CentOS/RHEL)
|
|
45
|
+
elif command -v yum &> /dev/null; then
|
|
46
|
+
echo -e "${YELLOW}[*] 使用 yum 安装...${NC}"
|
|
47
|
+
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
|
|
48
|
+
sudo yum install -y nodejs
|
|
49
|
+
else
|
|
50
|
+
echo -e "${RED}[✗] 未找到包管理器${NC}"
|
|
51
|
+
echo " 请手动安装: https://nodejs.org"
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# ============== Step 2: Clone/Update ==============
|
|
57
|
+
echo -e "${YELLOW}[*] 准备安装 Thatgfsj Code...${NC}"
|
|
58
|
+
|
|
59
|
+
INSTALL_DIR="$HOME/thatgfsj-code"
|
|
60
|
+
|
|
61
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
62
|
+
echo -e "${YELLOW}[*] 检测到已有安装,正在更新...${NC}"
|
|
63
|
+
cd "$INSTALL_DIR"
|
|
64
|
+
git pull origin main 2>/dev/null || {
|
|
65
|
+
echo -e "${YELLOW}[*] 更新失败,重新克隆...${NC}"
|
|
66
|
+
rm -rf "$INSTALL_DIR"
|
|
67
|
+
}
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [ ! -d "$INSTALL_DIR" ]; then
|
|
71
|
+
echo -e "${YELLOW}[*] 克隆仓库...${NC}"
|
|
72
|
+
git clone https://github.com/Thatgfsj/thatgfsj-code.git "$INSTALL_DIR"
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
cd "$INSTALL_DIR"
|
|
76
|
+
|
|
77
|
+
if [ ! -f "package.json" ]; then
|
|
78
|
+
echo -e "${RED}[✗] 安装目录无效${NC}"
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo -e "${GREEN}[✓] 代码准备完成: $INSTALL_DIR${NC}"
|
|
83
|
+
|
|
84
|
+
# ============== Step 3: Install Dependencies ==============
|
|
85
|
+
echo -e "${YELLOW}[*] 安装依赖...${NC}"
|
|
86
|
+
|
|
87
|
+
npm install
|
|
88
|
+
npm run build
|
|
89
|
+
|
|
90
|
+
echo -e "${GREEN}[✓] 依赖安装完成${NC}"
|
|
91
|
+
|
|
92
|
+
# ============== Step 4: Link Command ==============
|
|
93
|
+
echo -e "${YELLOW}[*] 设置命令...${NC}"
|
|
94
|
+
|
|
95
|
+
npm link
|
|
96
|
+
|
|
97
|
+
echo -e "${GREEN}[✓] 命令 'gfcode' 已可用${NC}"
|
|
98
|
+
|
|
99
|
+
# ============== Done ==============
|
|
100
|
+
echo ""
|
|
101
|
+
echo -e "${CYAN} ======================================${NC}"
|
|
102
|
+
echo -e "${GREEN} 安装完成!${NC}"
|
|
103
|
+
echo -e "${CYAN} ======================================${NC}"
|
|
104
|
+
echo ""
|
|
105
|
+
echo -e " ${WHITE}使用方法:${NC}"
|
|
106
|
+
echo -e " gfcode init - 重新配置"
|
|
107
|
+
echo -e " gfcode - 启动交互模式"
|
|
108
|
+
echo -e " gfcode '你的问题' - 直接提问"
|
|
109
|
+
echo -e " gfcode explain '代码' - 解释代码"
|
|
110
|
+
echo -e " gfcode debug '代码' - 调试代码"
|
|
111
|
+
echo ""
|
|
112
|
+
echo -e " 文档: ${CYAN}https://github.com/Thatgfsj/thatgfsj-code${NC}"
|
|
113
|
+
echo ""
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thatgfsj-code",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Thatgfsj Code - AI Coding Assistant",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Thatgfsj Code - AI Coding Assistant with Reasonix-style prompt caching",
|
|
5
5
|
"main": "dist/cmd/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
"build": "tsc",
|
|
13
13
|
"start": "node dist/cmd/index.js",
|
|
14
14
|
"dev": "tsc && node dist/cmd/index.js",
|
|
15
|
-
"link": "npm link"
|
|
15
|
+
"link": "npm link",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest"
|
|
16
18
|
},
|
|
17
19
|
"keywords": [
|
|
18
20
|
"ai",
|
|
@@ -40,6 +42,7 @@
|
|
|
40
42
|
"@types/marked-terminal": "^6.1.1",
|
|
41
43
|
"@types/node": "^20.10.0",
|
|
42
44
|
"@types/react": "^19.2.17",
|
|
43
|
-
"typescript": "^5.3.0"
|
|
45
|
+
"typescript": "^5.3.0",
|
|
46
|
+
"vitest": "^4.1.10"
|
|
44
47
|
}
|
|
45
48
|
}
|