thatgfsj-code 3.0.3 → 3.0.6
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 +64 -21
- package/dist/app/index.d.ts +93 -22
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +232 -40
- package/dist/app/index.js.map +1 -1
- package/dist/cache/smartModel.d.ts +29 -22
- package/dist/cache/smartModel.d.ts.map +1 -1
- package/dist/cache/smartModel.js +33 -40
- package/dist/cache/smartModel.js.map +1 -1
- package/dist/cmd/index.d.ts +12 -20
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +192 -146
- package/dist/cmd/index.js.map +1 -1
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +9 -6
- package/dist/config/index.js.map +1 -1
- package/dist/config/types.d.ts +5 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/llm/anthropic.d.ts +1 -1
- package/dist/llm/anthropic.d.ts.map +1 -1
- package/dist/llm/anthropic.js +116 -84
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/gemini.d.ts +27 -3
- package/dist/llm/gemini.d.ts.map +1 -1
- package/dist/llm/gemini.js +196 -73
- package/dist/llm/gemini.js.map +1 -1
- package/dist/llm/index.d.ts +20 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +71 -10
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/openai.d.ts +5 -1
- package/dist/llm/openai.d.ts.map +1 -1
- package/dist/llm/openai.js +96 -56
- package/dist/llm/openai.js.map +1 -1
- package/dist/mcp/client.d.ts +84 -34
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +291 -126
- package/dist/mcp/client.js.map +1 -1
- package/dist/session/compactor.d.ts +27 -7
- package/dist/session/compactor.d.ts.map +1 -1
- package/dist/session/compactor.js +78 -23
- package/dist/session/compactor.js.map +1 -1
- package/dist/session/index.d.ts +96 -33
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +278 -60
- package/dist/session/index.js.map +1 -1
- package/dist/tools/file.d.ts +10 -2
- package/dist/tools/file.d.ts.map +1 -1
- package/dist/tools/file.js +54 -5
- package/dist/tools/file.js.map +1 -1
- package/dist/tools/git.d.ts +16 -2
- package/dist/tools/git.d.ts.map +1 -1
- package/dist/tools/git.js +61 -18
- package/dist/tools/git.js.map +1 -1
- package/dist/tools/nwt.d.ts.map +1 -1
- package/dist/tools/nwt.js +8 -1
- package/dist/tools/nwt.js.map +1 -1
- package/dist/tools/search.d.ts +8 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +105 -34
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/shell.d.ts +0 -4
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +11 -26
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/types.d.ts +7 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tui/app.d.ts.map +1 -1
- package/dist/tui/app.js +90 -18
- package/dist/tui/app.js.map +1 -1
- package/dist/tui/components/ChatMessage.d.ts.map +1 -1
- package/dist/tui/components/ChatMessage.js +9 -2
- package/dist/tui/components/ChatMessage.js.map +1 -1
- package/dist/tui/components/ConfirmPrompt.d.ts +21 -0
- package/dist/tui/components/ConfirmPrompt.d.ts.map +1 -0
- package/dist/tui/components/ConfirmPrompt.js +45 -0
- package/dist/tui/components/ConfirmPrompt.js.map +1 -0
- package/dist/tui/components/Header.d.ts +10 -5
- package/dist/tui/components/Header.d.ts.map +1 -1
- package/dist/tui/components/Header.js +13 -5
- package/dist/tui/components/Header.js.map +1 -1
- package/dist/tui/components/InitWizard.d.ts.map +1 -1
- package/dist/tui/components/InitWizard.js +8 -13
- package/dist/tui/components/InitWizard.js.map +1 -1
- package/dist/tui/components/StatusBar.d.ts +7 -0
- package/dist/tui/components/StatusBar.d.ts.map +1 -1
- package/dist/tui/components/StatusBar.js +8 -3
- package/dist/tui/components/StatusBar.js.map +1 -1
- package/dist/tui/components/Thinking.d.ts +5 -0
- package/dist/tui/components/Thinking.d.ts.map +1 -1
- package/dist/tui/components/Thinking.js +24 -2
- package/dist/tui/components/Thinking.js.map +1 -1
- package/dist/tui/components/ToolCall.d.ts +6 -1
- package/dist/tui/components/ToolCall.d.ts.map +1 -1
- package/dist/tui/components/ToolCall.js +50 -22
- package/dist/tui/components/ToolCall.js.map +1 -1
- package/dist/tui/components/UserInput.d.ts +5 -0
- package/dist/tui/components/UserInput.d.ts.map +1 -1
- package/dist/tui/components/UserInput.js +9 -13
- package/dist/tui/components/UserInput.js.map +1 -1
- package/dist/tui/hooks/useChat.d.ts +1 -0
- package/dist/tui/hooks/useChat.d.ts.map +1 -1
- package/dist/tui/hooks/useChat.js +36 -16
- package/dist/tui/hooks/useChat.js.map +1 -1
- package/dist/tui/hooks/useCommands.d.ts +7 -1
- package/dist/tui/hooks/useCommands.d.ts.map +1 -1
- package/dist/tui/hooks/useCommands.js +83 -49
- package/dist/tui/hooks/useCommands.js.map +1 -1
- package/dist/tui/theme.d.ts +34 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +34 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/welcome.d.ts.map +1 -1
- package/dist/tui/welcome.js +9 -7
- package/dist/tui/welcome.js.map +1 -1
- package/dist/types.d.ts +16 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/diff.d.ts +5 -0
- package/dist/utils/diff.d.ts.map +1 -1
- package/dist/utils/diff.js +15 -0
- package/dist/utils/diff.js.map +1 -1
- package/dist/version.d.ts +12 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +29 -0
- package/dist/version.js.map +1 -0
- package/package.json +19 -7
- package/CHANGELOG.md +0 -192
- package/DEVELOPMENT.md +0 -286
- package/ROADMAP.md +0 -91
- package/docs/API_KEY_GUIDE.md +0 -236
- package/docs/FAQ.md +0 -182
- package/install.bat +0 -63
- package/install.ps1 +0 -238
- package/install.sh +0 -113
- package/src/app/index.ts +0 -197
- package/src/cache/fingerprint.ts +0 -101
- package/src/cache/index.ts +0 -21
- package/src/cache/smartModel.ts +0 -145
- package/src/cache/stats.ts +0 -199
- package/src/cache/volatile.ts +0 -47
- package/src/cmd/index.tsx +0 -288
- package/src/config/index.ts +0 -158
- package/src/config/providers.ts +0 -234
- package/src/config/types.ts +0 -71
- package/src/hooks/index.ts +0 -111
- package/src/llm/anthropic.ts +0 -413
- package/src/llm/gemini.ts +0 -169
- package/src/llm/index.ts +0 -302
- package/src/llm/openai.ts +0 -243
- package/src/llm/provider.ts +0 -71
- package/src/mcp/client.ts +0 -330
- package/src/prompts/index.ts +0 -260
- package/src/session/compactor.ts +0 -103
- package/src/session/index.ts +0 -181
- package/src/session/message.ts +0 -42
- package/src/skills/brainstorming.ts +0 -43
- package/src/skills/code-review.ts +0 -45
- package/src/skills/executing-plans.ts +0 -27
- package/src/skills/frontend-design.ts +0 -35
- package/src/skills/git-workflow.ts +0 -36
- package/src/skills/improve-architecture.ts +0 -38
- package/src/skills/index.ts +0 -136
- package/src/skills/neuroweave.ts +0 -47
- package/src/skills/playwright.ts +0 -72
- package/src/skills/prototype.ts +0 -30
- package/src/skills/subagent.ts +0 -28
- package/src/skills/supabase.ts +0 -44
- package/src/skills/systematic-debugging.ts +0 -44
- package/src/skills/tdd.ts +0 -39
- package/src/skills/triage.ts +0 -35
- package/src/skills/verification.ts +0 -31
- package/src/skills/writing-plans.ts +0 -42
- package/src/tools/file.ts +0 -143
- package/src/tools/git.ts +0 -132
- package/src/tools/index.ts +0 -111
- package/src/tools/nwt.ts +0 -598
- package/src/tools/search.ts +0 -263
- package/src/tools/shell.ts +0 -136
- package/src/tools/types.ts +0 -122
- package/src/tui/app.tsx +0 -159
- package/src/tui/components/ChatList.tsx +0 -41
- package/src/tui/components/ChatMessage.tsx +0 -54
- package/src/tui/components/Header.tsx +0 -66
- package/src/tui/components/InitWizard.tsx +0 -251
- package/src/tui/components/Markdown.tsx +0 -35
- package/src/tui/components/ModelSelector.tsx +0 -107
- package/src/tui/components/StatusBar.tsx +0 -30
- package/src/tui/components/Thinking.tsx +0 -17
- package/src/tui/components/ToolCall.tsx +0 -102
- package/src/tui/components/UserInput.tsx +0 -151
- package/src/tui/hooks/useChat.ts +0 -287
- package/src/tui/hooks/useCommands.ts +0 -273
- package/src/tui/index.ts +0 -6
- package/src/tui/welcome.ts +0 -177
- package/src/types.ts +0 -104
- package/src/utils/diff.ts +0 -71
- package/src/utils/project.ts +0 -99
- package/src/utils/stableStringify.ts +0 -47
- package/src/utils/thinking.ts +0 -119
- package/tests/cache/fingerprint.test.ts +0 -75
- package/tests/cache/providerCatalog.test.ts +0 -31
- package/tests/cache/smartModel.test.ts +0 -112
- package/tests/cache/stableStringify.test.ts +0 -43
- package/tests/cache/stats.test.ts +0 -146
- package/tests/cache/volatile.test.ts +0 -75
- package/tests/smoke-pollution.mjs +0 -78
- package/tests/smoke-thinking.mjs +0 -110
- package/tests/smoke-tool-stream.mjs +0 -69
- package/tests/smoke-tool.mjs +0 -117
- package/tsconfig.json +0 -21
package/dist/app/index.js
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* App - Core application singleton
|
|
3
|
-
* Simplified: directly uses LLMService (which has built-in agent loop)
|
|
4
3
|
*
|
|
5
|
-
* v3.0.
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
4
|
+
* v3.0.5 wiring release:
|
|
5
|
+
* - MCP: servers from ~/.thatgfsj/mcp.json are connected at startup
|
|
6
|
+
* (per-server failures are non-fatal) and their tools join the
|
|
7
|
+
* registry before the system prompt is built. Child processes are
|
|
8
|
+
* disconnected on exit.
|
|
9
|
+
* - Permission pipeline: tool confirmations now actually reach the UI —
|
|
10
|
+
* App owns the mode ('ask' default, 'accept' via --yolo) and a
|
|
11
|
+
* pluggable confirmHandler (TUI prompt / headless auto-deny). With no
|
|
12
|
+
* handler and 'ask' mode, write/execute tool calls are DENIED instead
|
|
13
|
+
* of silently executed.
|
|
14
|
+
* - reloadModel(): /model hot-swaps provider+model without restarting;
|
|
15
|
+
* tools and the system prompt are rebuilt, TTL resolution resets.
|
|
16
|
+
* - applyTtl(): /ttl takes effect immediately (config + provider marker).
|
|
17
|
+
* - streamResponse() accepts an AbortSignal that reaches the provider
|
|
18
|
+
* fetch calls, so cancelling a round stops token generation.
|
|
8
19
|
*/
|
|
20
|
+
import { existsSync, readFileSync } from 'fs';
|
|
21
|
+
import { join } from 'path';
|
|
22
|
+
import { homedir } from 'os';
|
|
9
23
|
import { ConfigManager } from '../config/index.js';
|
|
10
24
|
import { LLMService } from '../llm/index.js';
|
|
11
25
|
import { SessionManager } from '../session/index.js';
|
|
@@ -15,6 +29,22 @@ import { SystemPromptBuilder } from '../prompts/index.js';
|
|
|
15
29
|
import { SkillRegistry } from '../skills/index.js';
|
|
16
30
|
import { CacheStatsStore } from '../cache/stats.js';
|
|
17
31
|
import { compressThinking } from '../utils/thinking.js';
|
|
32
|
+
import { MCPServerManager } from '../mcp/client.js';
|
|
33
|
+
/** Read ~/.thatgfsj/mcp.json. Missing or corrupted file = no servers. */
|
|
34
|
+
export function loadMcpConfig() {
|
|
35
|
+
const p = join(homedir(), '.thatgfsj', 'mcp.json');
|
|
36
|
+
if (!existsSync(p))
|
|
37
|
+
return {};
|
|
38
|
+
try {
|
|
39
|
+
const data = JSON.parse(readFileSync(p, 'utf-8'));
|
|
40
|
+
if (data && typeof data === 'object')
|
|
41
|
+
return data;
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
18
48
|
export class App {
|
|
19
49
|
config;
|
|
20
50
|
llm;
|
|
@@ -29,10 +59,13 @@ export class App {
|
|
|
29
59
|
* and the /cache command.
|
|
30
60
|
*/
|
|
31
61
|
cacheStats;
|
|
62
|
+
/** v3.0.5: connected MCP servers (empty manager when none configured). */
|
|
63
|
+
mcp;
|
|
64
|
+
/** v3.0.5: startup results per configured MCP server, for /mcp output. */
|
|
65
|
+
mcpStartupResults = [];
|
|
32
66
|
/**
|
|
33
|
-
* v2.2.5
|
|
34
|
-
*
|
|
35
|
-
* in the REPL.
|
|
67
|
+
* v2.2.5: toggle thinking block compression. Default true. Toggled by
|
|
68
|
+
* `--show-thinking` on the CLI or `/thinking on|off` in the REPL.
|
|
36
69
|
*/
|
|
37
70
|
showThinking = false;
|
|
38
71
|
/**
|
|
@@ -41,7 +74,18 @@ export class App {
|
|
|
41
74
|
* is '5m' or '1h' and stays sticky.
|
|
42
75
|
*/
|
|
43
76
|
resolvedTtl = null;
|
|
44
|
-
|
|
77
|
+
/**
|
|
78
|
+
* v3.0.5: permission mode. 'ask' requires confirmation for write/execute
|
|
79
|
+
* tool actions; 'accept' (--yolo) allows everything.
|
|
80
|
+
*/
|
|
81
|
+
permissionMode = 'ask';
|
|
82
|
+
/**
|
|
83
|
+
* v3.0.5: pluggable confirmation UI. The TUI installs an Ink prompt;
|
|
84
|
+
* headless mode leaves it unset → write/execute actions are denied with
|
|
85
|
+
* a note (add --yolo to allow them).
|
|
86
|
+
*/
|
|
87
|
+
confirmHandler;
|
|
88
|
+
constructor(config, llm, session, tools, hooks, prompts, skills, cacheStats, mcp) {
|
|
45
89
|
this.config = config;
|
|
46
90
|
this.llm = llm;
|
|
47
91
|
this.session = session;
|
|
@@ -50,6 +94,7 @@ export class App {
|
|
|
50
94
|
this.prompts = prompts;
|
|
51
95
|
this.skills = skills;
|
|
52
96
|
this.cacheStats = cacheStats;
|
|
97
|
+
this.mcp = mcp;
|
|
53
98
|
}
|
|
54
99
|
static async create() {
|
|
55
100
|
const config = await ConfigManager.load();
|
|
@@ -57,32 +102,184 @@ export class App {
|
|
|
57
102
|
const llm = LLMService.fromConfig(aiConfig);
|
|
58
103
|
const cacheStats = new CacheStatsStore();
|
|
59
104
|
const session = new SessionManager(config.get().contextLength || 50);
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
console.warn(`\n ⚠️ 上下文较长(${info.currentLength}/${info.max})。` +
|
|
65
|
-
`建议调 /new 开新会话(NWT 已自动归档历史)\n`);
|
|
105
|
+
// Default toast goes to stderr so it can not corrupt the Ink frame;
|
|
106
|
+
// the TUI replaces this with a proper in-app message.
|
|
107
|
+
session.onAutoCompact = (info) => {
|
|
108
|
+
process.stderr.write(`\n ⚠️ 上下文较长(${info.before} 条),已自动压缩到 ${info.after} 条。可随时 /new 开新会话(NWT 已自动归档历史)\n`);
|
|
66
109
|
};
|
|
67
110
|
const tools = new ToolRegistry();
|
|
68
111
|
const hooks = new HookManager();
|
|
69
112
|
const skills = new SkillRegistry();
|
|
70
|
-
|
|
113
|
+
let mcpResults = [];
|
|
114
|
+
// v3.0.5: connect MCP servers BEFORE the prompt is built so their tools
|
|
115
|
+
// are visible to the model from turn one. A failing server is logged,
|
|
116
|
+
// never fatal.
|
|
117
|
+
const mcp = new MCPServerManager();
|
|
118
|
+
const mcpConfig = loadMcpConfig();
|
|
119
|
+
const mcpServerDefs = mcpConfig.mcpServers || mcpConfig.servers || {};
|
|
120
|
+
if (Object.keys(mcpServerDefs).length > 0) {
|
|
121
|
+
appLog('正在连接 MCP 服务器…');
|
|
122
|
+
mcpResults = await mcp.connectFromConfig(mcpConfig);
|
|
123
|
+
for (const r of mcpResults) {
|
|
124
|
+
if (r.ok) {
|
|
125
|
+
appLog(`✓ MCP ${r.name}(${r.tools} 个工具)`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
appLog(`✗ MCP ${r.name}: ${r.error}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
for (const tool of mcp.getAllTools()) {
|
|
132
|
+
tools.register(tool);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Kill MCP child processes on exit (also covers Ctrl+C via 'exit').
|
|
136
|
+
process.on('exit', () => {
|
|
137
|
+
try {
|
|
138
|
+
mcp.disconnectAll();
|
|
139
|
+
}
|
|
140
|
+
catch { /* best-effort */ }
|
|
141
|
+
});
|
|
142
|
+
// Register tools with LLM service (after MCP tools joined the registry)
|
|
71
143
|
llm.registerTools(tools.list());
|
|
72
144
|
// Auto-init NWT timeline
|
|
73
145
|
const nwtTool = tools.get('nwt');
|
|
74
146
|
if (nwtTool) {
|
|
75
147
|
await nwtTool.execute({ action: 'init' });
|
|
76
148
|
}
|
|
77
|
-
// Build system prompt with
|
|
149
|
+
// Build system prompt with the FULL tool list (including MCP tools)
|
|
78
150
|
const prompts = new SystemPromptBuilder({
|
|
79
151
|
cwd: process.cwd(),
|
|
80
152
|
tools: tools.list(),
|
|
81
153
|
permissionMode: 'ask',
|
|
82
154
|
skillsPrompt: skills.getActivePrompts(),
|
|
83
155
|
});
|
|
156
|
+
const app = new App(config, llm, session, tools, hooks, prompts, skills, cacheStats, mcp);
|
|
157
|
+
app.mcpStartupResults = mcpResults;
|
|
158
|
+
// v3.0.5: route tool confirmations through App (mode + handler aware)
|
|
159
|
+
app.applyToolContext();
|
|
84
160
|
session.addMessage('system', prompts.build());
|
|
85
|
-
return
|
|
161
|
+
return app;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* v3.0.5: keep registry and LLMService tool contexts in sync. All asks
|
|
165
|
+
* funnel through requestConfirmation so the permission mode and the
|
|
166
|
+
* active UI handler apply uniformly.
|
|
167
|
+
*/
|
|
168
|
+
applyToolContext() {
|
|
169
|
+
const ctx = {
|
|
170
|
+
workingDirectory: process.cwd(),
|
|
171
|
+
confirmAction: (msg) => this.requestConfirmation({ message: msg }),
|
|
172
|
+
confirmEdit: (info) => this.requestConfirmation({ message: info.message }),
|
|
173
|
+
};
|
|
174
|
+
this.tools.setContext(ctx);
|
|
175
|
+
this.llm.setToolContext(ctx);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* v3.0.5: central permission decision.
|
|
179
|
+
* - 'accept' mode (--yolo): always allowed.
|
|
180
|
+
* - handler installed (TUI): ask it, 60s timeout denies.
|
|
181
|
+
* - no handler (headless): deny with a hint on stderr.
|
|
182
|
+
*/
|
|
183
|
+
async requestConfirmation(req) {
|
|
184
|
+
if (this.permissionMode === 'accept')
|
|
185
|
+
return true;
|
|
186
|
+
if (!this.confirmHandler) {
|
|
187
|
+
process.stderr.write(`\n ⛔ 已拒绝:${firstLine(req.message)}\n (headless 模式默认拒绝写入/执行操作;如需放行请加 --yolo)\n`);
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
const answer = await Promise.race([
|
|
192
|
+
this.confirmHandler(req),
|
|
193
|
+
new Promise((resolve) => {
|
|
194
|
+
const t = setTimeout(() => resolve(false), 60000);
|
|
195
|
+
t.unref?.();
|
|
196
|
+
}),
|
|
197
|
+
]);
|
|
198
|
+
return !!answer;
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* v3.0.5: single entry for toggling auto-accept. Also refreshes the
|
|
206
|
+
* system prompt's permission-mode section so the model knows tool calls
|
|
207
|
+
* no longer need user approval.
|
|
208
|
+
*/
|
|
209
|
+
setYolo(on) {
|
|
210
|
+
this.permissionMode = on ? 'accept' : 'ask';
|
|
211
|
+
this.rebuildSystemPrompt();
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* v3.0.5: hot-swap the model (and provider, if /provider changed it on
|
|
215
|
+
* disk). Rebuilds LLMService, re-registers every current tool, resets TTL
|
|
216
|
+
* resolution and refreshes the system prompt. /model previously only
|
|
217
|
+
* wrote the config file and required a restart.
|
|
218
|
+
*/
|
|
219
|
+
async reloadModel() {
|
|
220
|
+
const aiConfig = this.config.getAIConfig();
|
|
221
|
+
const llm = LLMService.fromConfig(aiConfig);
|
|
222
|
+
llm.registerTools(this.tools.list());
|
|
223
|
+
this.llm = llm;
|
|
224
|
+
this.resolvedTtl = null;
|
|
225
|
+
this.applyToolContext();
|
|
226
|
+
this.rebuildSystemPrompt();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* v3.0.5: apply a TTL pin immediately (config write-through + provider
|
|
230
|
+
* marker). /ttl previously only updated a display value; the wire format
|
|
231
|
+
* kept the old TTL until restart.
|
|
232
|
+
*/
|
|
233
|
+
async applyTtl(ttl) {
|
|
234
|
+
const current = this.config.get().cache ?? { enabled: true, strategy: 'auto' };
|
|
235
|
+
await this.config.save({ cache: { ...current, ttl } });
|
|
236
|
+
this.llm.setTtl(ttl);
|
|
237
|
+
this.resolvedTtl = ttl;
|
|
238
|
+
}
|
|
239
|
+
/** v3.0.5: rebuild the system prompt (tools / permission mode changed). */
|
|
240
|
+
rebuildSystemPrompt() {
|
|
241
|
+
this.prompts.setTools(this.tools.list());
|
|
242
|
+
this.prompts.setPermissionMode(this.permissionMode === 'accept' ? 'accept' : 'ask');
|
|
243
|
+
const built = this.prompts.build();
|
|
244
|
+
this.session.replaceSystemMessage(built);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* v3.0.5: TUI hook-up — show MCP startup results as an in-chat message.
|
|
248
|
+
* Returns a short multi-line report (empty when no servers configured).
|
|
249
|
+
*/
|
|
250
|
+
mcpStatusText() {
|
|
251
|
+
const configured = Object.keys(loadMcpConfig().mcpServers || loadMcpConfig().servers || {}).length;
|
|
252
|
+
if (configured === 0) {
|
|
253
|
+
return [
|
|
254
|
+
'MCP 未配置。配置文件: ~/.thatgfsj/mcp.json',
|
|
255
|
+
'',
|
|
256
|
+
' {',
|
|
257
|
+
' "mcpServers": {',
|
|
258
|
+
' "名称": { "command": "npx", "args": ["-y", "包名"] }',
|
|
259
|
+
' }',
|
|
260
|
+
' }',
|
|
261
|
+
'',
|
|
262
|
+
'(兼容 "servers" 键名;修改后重启生效)',
|
|
263
|
+
].join('\n');
|
|
264
|
+
}
|
|
265
|
+
const lines = ['MCP 服务器:'];
|
|
266
|
+
for (const r of this.mcpStartupResults) {
|
|
267
|
+
lines.push(r.ok
|
|
268
|
+
? ` ✓ ${r.name} — ${r.tools} 个工具`
|
|
269
|
+
: ` ✗ ${r.name} — ${r.error}`);
|
|
270
|
+
}
|
|
271
|
+
const status = this.mcp.getStatus();
|
|
272
|
+
if (status.length > 0) {
|
|
273
|
+
lines.push('');
|
|
274
|
+
lines.push('当前状态:');
|
|
275
|
+
for (const s of status) {
|
|
276
|
+
const toolList = s.tools.length > 0
|
|
277
|
+
? s.tools.slice(0, 8).join(', ') + (s.tools.length > 8 ? ` 等 ${s.tools.length} 个` : '')
|
|
278
|
+
: '(无工具)';
|
|
279
|
+
lines.push(` ${s.connected ? '●' : '○'} ${s.name}: ${toolList}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return lines.join('\n');
|
|
86
283
|
}
|
|
87
284
|
/**
|
|
88
285
|
* Stream a response for the current session messages.
|
|
@@ -91,15 +288,12 @@ export class App {
|
|
|
91
288
|
* Yields structured StreamChunks. Returns the final ChatResponse (with usage
|
|
92
289
|
* if the provider reported it) so the caller can record cache stats.
|
|
93
290
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* generator's return value. Using yield* doesn't carry the return value
|
|
97
|
-
* through TS's AsyncGenerator<T, R> type inference in this version of
|
|
98
|
-
* TypeScript, so we wrap with an inner for-await and explicit return.
|
|
291
|
+
* v3.0.5: accepts { signal } — propagated into provider fetch calls so
|
|
292
|
+
* cancellation actually aborts the HTTP request.
|
|
99
293
|
*/
|
|
100
|
-
async *streamResponse(messages) {
|
|
294
|
+
async *streamResponse(messages, opts) {
|
|
101
295
|
const msgs = messages || this.session.getMessages();
|
|
102
|
-
const inner = this.llm.chatStream(msgs);
|
|
296
|
+
const inner = this.llm.chatStream(msgs, { signal: opts?.signal });
|
|
103
297
|
const debugUsage = !!process.env.GFCODE_DEBUG_USAGE;
|
|
104
298
|
// v3.0.3: read TTL the LLMService resolved this round (sticky per session).
|
|
105
299
|
this.resolvedTtl = this.llm.getResolvedTTL();
|
|
@@ -113,32 +307,22 @@ export class App {
|
|
|
113
307
|
}
|
|
114
308
|
catch { /* best-effort */ }
|
|
115
309
|
if (debugUsage) {
|
|
116
|
-
// v3.0.0 DEBUG: dump raw usage fields to stderr so the user can
|
|
117
|
-
// confirm whether the upstream provider/relay forwards cache stats.
|
|
118
|
-
// Enable with: GFCODE_DEBUG_USAGE=1 gfcode ...
|
|
119
310
|
process.stderr.write('[debug_usage] ' + JSON.stringify(next.value.usage) + '\n');
|
|
120
311
|
}
|
|
121
312
|
}
|
|
122
313
|
yield next.value;
|
|
123
314
|
next = await inner.next();
|
|
124
315
|
}
|
|
125
|
-
// The generator's return value (ChatResponse with usage) is propagated
|
|
126
|
-
// to callers via `for await ... await streamResponse.next()` semantics.
|
|
127
316
|
return next.value;
|
|
128
317
|
}
|
|
129
318
|
/**
|
|
130
319
|
* Run a single prompt (non-interactive mode)
|
|
131
320
|
*
|
|
132
|
-
* v2.2.4
|
|
133
|
-
*
|
|
134
|
-
* pollution markers like "[已中断]".
|
|
321
|
+
* v2.2.4: persistence of the assistant message uses addMessageSafe, which
|
|
322
|
+
* drops the message if it contains pollution markers like "[已中断]".
|
|
135
323
|
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* so the conversation log stays compact.
|
|
139
|
-
*
|
|
140
|
-
* v3.0.0: yields structured StreamChunks; final usage is captured
|
|
141
|
-
* into onUsage callback for cache stats persistence.
|
|
324
|
+
* v3.0.0: yields structured StreamChunks; final usage is captured.
|
|
325
|
+
* v3.0.5: persists the session to disk when the round completes.
|
|
142
326
|
*/
|
|
143
327
|
async runPrompt(prompt, onUsage) {
|
|
144
328
|
this.session.addMessage('user', prompt);
|
|
@@ -162,10 +346,9 @@ export class App {
|
|
|
162
346
|
throw err;
|
|
163
347
|
}
|
|
164
348
|
console.log();
|
|
165
|
-
// v2.2.5: compress blocks before persisting.
|
|
166
349
|
const toPersist = compressThinking(fullResponse, this.showThinking);
|
|
167
350
|
this.session.addMessageSafe('assistant', toPersist);
|
|
168
|
-
|
|
351
|
+
this.session.persist();
|
|
169
352
|
if (finalUsage && onUsage) {
|
|
170
353
|
try {
|
|
171
354
|
onUsage(finalUsage);
|
|
@@ -175,4 +358,13 @@ export class App {
|
|
|
175
358
|
return fullResponse;
|
|
176
359
|
}
|
|
177
360
|
}
|
|
361
|
+
// ---- helpers ------------------------------------------------------------
|
|
362
|
+
function appLog(msg) {
|
|
363
|
+
// Startup messages go to stderr so they never corrupt Ink / --json stdout.
|
|
364
|
+
process.stderr.write(` ${msg}\n`);
|
|
365
|
+
}
|
|
366
|
+
function firstLine(s) {
|
|
367
|
+
const line = s.split('\n').find(l => l.trim()) || s;
|
|
368
|
+
return line.length > 120 ? line.slice(0, 120) + '…' : line;
|
|
369
|
+
}
|
|
178
370
|
//# sourceMappingURL=index.js.map
|
package/dist/app/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/app/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
* Tool-heavy turns → main model
|
|
11
11
|
*
|
|
12
12
|
* 2. Cache TTL
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* v3.0.4: default to 1h (long-task TTL). We cannot predict task
|
|
14
|
+
* length at round 0, so we choose the TTL that cannot expire
|
|
15
|
+
* mid-task. 5m is opt-in only (user pins it via /ttl 5m or the
|
|
16
|
+
* init wizard).
|
|
16
17
|
*
|
|
17
18
|
* Why TTL is decided per-ROUND but CHANGES per-CONVERSATION:
|
|
18
19
|
* The Anthropic cache_control marker is part of the request body.
|
|
@@ -24,14 +25,11 @@
|
|
|
24
25
|
* round) and never change it. Subsequent rounds get the same TTL,
|
|
25
26
|
* which keeps the cache prefix stable and lets Anthropic match it.
|
|
26
27
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* defaults to 5m. If the conversation then grows long, future rounds
|
|
33
|
-
* still use 5m for the system-token cache (because we already wrote
|
|
34
|
-
* it with 5m). The tool definition cache gets the same TTL.
|
|
28
|
+
* Trade-off: 1h write costs 2x input price (vs 1.25x for 5m), but
|
|
29
|
+
* reads are the same 0.1x. A long task hitting cache 2-3 times pays
|
|
30
|
+
* back the extra write cost; a short task pays it once and moves on.
|
|
31
|
+
* That is strictly better than guessing 5m and having the cache expire
|
|
32
|
+
* mid-task.
|
|
35
33
|
*/
|
|
36
34
|
import type { ChatMessage } from '../types.js';
|
|
37
35
|
export interface SmartModelDecision {
|
|
@@ -67,19 +65,28 @@ export declare function totalConversationChars(messages: ChatMessage[]): number;
|
|
|
67
65
|
/**
|
|
68
66
|
* Decide the cache TTL for the current round.
|
|
69
67
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
68
|
+
* v3.0.4: The previous implementation tried to *predict* the task length
|
|
69
|
+
* from the conversation so far (short sessions → 5m, long → 1h). That
|
|
70
|
+
* was wrong: at the moment the decision is made (first round), the task
|
|
71
|
+
* hasn't started yet — there is no way to know whether it will be a
|
|
72
|
+
* 30-second question or a 3-hour refactor. Predicting 5m for a task
|
|
73
|
+
* that turns out to be long means the cache expires mid-task (5-minute
|
|
74
|
+
* TTL counts from the last HIT, and agent work often has >5m gaps while
|
|
75
|
+
* tools run / user reads output), so every round after the gap re-writes
|
|
76
|
+
* the whole prefix at full price.
|
|
73
77
|
*
|
|
74
|
-
*
|
|
75
|
-
* -
|
|
76
|
-
*
|
|
77
|
-
* -
|
|
78
|
+
* Correct rule: DEFAULT TO THE LONG TTL (1h) and don't guess.
|
|
79
|
+
* - 1h costs 2x input price to WRITE (vs 1.25x for 5m), but reads are
|
|
80
|
+
* the same 0.1x for both.
|
|
81
|
+
* - A long task that hits cache even 2-3 times pays back the extra
|
|
82
|
+
* write cost. A short task only pays the extra write once.
|
|
83
|
+
* - Users who are SURE the session is short can pin 5m via
|
|
84
|
+
* /ttl 5m or the init wizard — the default stays 1h.
|
|
78
85
|
*
|
|
79
|
-
* Stability rule: once a TTL is chosen, it is reused for
|
|
80
|
-
* subsequent round in the same session. Changing TTL between
|
|
81
|
-
* would invalidate the Anthropic cache prefix and cost more
|
|
82
|
-
* saves.
|
|
86
|
+
* Stability rule (unchanged): once a TTL is chosen, it is reused for
|
|
87
|
+
* every subsequent round in the same session. Changing TTL between
|
|
88
|
+
* rounds would invalidate the Anthropic cache prefix and cost more
|
|
89
|
+
* than it saves.
|
|
83
90
|
*
|
|
84
91
|
* The `isFirstDecision` flag tells the caller whether to apply the
|
|
85
92
|
* decision (first round) or reuse the previous one (later rounds).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smartModel.d.ts","sourceRoot":"","sources":["../../src/cache/smartModel.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"smartModel.d.ts","sourceRoot":"","sources":["../../src/cache/smartModel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,SAAS,EAAE,OAAO,CAAC;IACnB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAUlG;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAYtE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,WAAW,EAAE,EACvB,WAAW,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAC9B,gBAAgB,CAQlB"}
|
package/dist/cache/smartModel.js
CHANGED
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
* Tool-heavy turns → main model
|
|
11
11
|
*
|
|
12
12
|
* 2. Cache TTL
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* v3.0.4: default to 1h (long-task TTL). We cannot predict task
|
|
14
|
+
* length at round 0, so we choose the TTL that cannot expire
|
|
15
|
+
* mid-task. 5m is opt-in only (user pins it via /ttl 5m or the
|
|
16
|
+
* init wizard).
|
|
16
17
|
*
|
|
17
18
|
* Why TTL is decided per-ROUND but CHANGES per-CONVERSATION:
|
|
18
19
|
* The Anthropic cache_control marker is part of the request body.
|
|
@@ -24,14 +25,11 @@
|
|
|
24
25
|
* round) and never change it. Subsequent rounds get the same TTL,
|
|
25
26
|
* which keeps the cache prefix stable and lets Anthropic match it.
|
|
26
27
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* defaults to 5m. If the conversation then grows long, future rounds
|
|
33
|
-
* still use 5m for the system-token cache (because we already wrote
|
|
34
|
-
* it with 5m). The tool definition cache gets the same TTL.
|
|
28
|
+
* Trade-off: 1h write costs 2x input price (vs 1.25x for 5m), but
|
|
29
|
+
* reads are the same 0.1x. A long task hitting cache 2-3 times pays
|
|
30
|
+
* back the extra write cost; a short task pays it once and moves on.
|
|
31
|
+
* That is strictly better than guessing 5m and having the cache expire
|
|
32
|
+
* mid-task.
|
|
35
33
|
*/
|
|
36
34
|
/**
|
|
37
35
|
* Heuristic: downgrade when
|
|
@@ -78,19 +76,28 @@ export function totalConversationChars(messages) {
|
|
|
78
76
|
/**
|
|
79
77
|
* Decide the cache TTL for the current round.
|
|
80
78
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
79
|
+
* v3.0.4: The previous implementation tried to *predict* the task length
|
|
80
|
+
* from the conversation so far (short sessions → 5m, long → 1h). That
|
|
81
|
+
* was wrong: at the moment the decision is made (first round), the task
|
|
82
|
+
* hasn't started yet — there is no way to know whether it will be a
|
|
83
|
+
* 30-second question or a 3-hour refactor. Predicting 5m for a task
|
|
84
|
+
* that turns out to be long means the cache expires mid-task (5-minute
|
|
85
|
+
* TTL counts from the last HIT, and agent work often has >5m gaps while
|
|
86
|
+
* tools run / user reads output), so every round after the gap re-writes
|
|
87
|
+
* the whole prefix at full price.
|
|
84
88
|
*
|
|
85
|
-
*
|
|
86
|
-
* -
|
|
87
|
-
*
|
|
88
|
-
* -
|
|
89
|
+
* Correct rule: DEFAULT TO THE LONG TTL (1h) and don't guess.
|
|
90
|
+
* - 1h costs 2x input price to WRITE (vs 1.25x for 5m), but reads are
|
|
91
|
+
* the same 0.1x for both.
|
|
92
|
+
* - A long task that hits cache even 2-3 times pays back the extra
|
|
93
|
+
* write cost. A short task only pays the extra write once.
|
|
94
|
+
* - Users who are SURE the session is short can pin 5m via
|
|
95
|
+
* /ttl 5m or the init wizard — the default stays 1h.
|
|
89
96
|
*
|
|
90
|
-
* Stability rule: once a TTL is chosen, it is reused for
|
|
91
|
-
* subsequent round in the same session. Changing TTL between
|
|
92
|
-
* would invalidate the Anthropic cache prefix and cost more
|
|
93
|
-
* saves.
|
|
97
|
+
* Stability rule (unchanged): once a TTL is chosen, it is reused for
|
|
98
|
+
* every subsequent round in the same session. Changing TTL between
|
|
99
|
+
* rounds would invalidate the Anthropic cache prefix and cost more
|
|
100
|
+
* than it saves.
|
|
94
101
|
*
|
|
95
102
|
* The `isFirstDecision` flag tells the caller whether to apply the
|
|
96
103
|
* decision (first round) or reuse the previous one (later rounds).
|
|
@@ -99,23 +106,9 @@ export function decideTTL(messages, previousTTL) {
|
|
|
99
106
|
if (previousTTL) {
|
|
100
107
|
return { ttl: previousTTL, reason: 'reused-from-previous-round', isFirstDecision: false };
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
return { ttl: '5m', reason: 'first-round-default', isFirstDecision: true };
|
|
107
|
-
}
|
|
108
|
-
// Multi-turn but small conversation → 5m
|
|
109
|
-
if (turnCount < 15 && totalChars < 50_000) {
|
|
110
|
-
return { ttl: '5m', reason: `short-session-${turnCount}-turns`, isFirstDecision: true };
|
|
111
|
-
}
|
|
112
|
-
// Long conversations → 1h
|
|
113
|
-
if (turnCount >= 15) {
|
|
114
|
-
return { ttl: '1h', reason: `long-session-${turnCount}-turns`, isFirstDecision: true };
|
|
115
|
-
}
|
|
116
|
-
if (totalChars >= 50_000) {
|
|
117
|
-
return { ttl: '1h', reason: `long-context-${totalChars}-chars`, isFirstDecision: true };
|
|
118
|
-
}
|
|
119
|
-
return { ttl: '5m', reason: 'fallback', isFirstDecision: true };
|
|
109
|
+
// Default: long-task TTL. We cannot know the task length upfront, so
|
|
110
|
+
// we pick the TTL that cannot expire mid-task. 5m is only used when
|
|
111
|
+
// the user explicitly pins it.
|
|
112
|
+
return { ttl: '1h', reason: 'default-long-task', isFirstDecision: true };
|
|
120
113
|
}
|
|
121
114
|
//# sourceMappingURL=smartModel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smartModel.js","sourceRoot":"","sources":["../../src/cache/smartModel.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"smartModel.js","sourceRoot":"","sources":["../../src/cache/smartModel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAkBH;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB,EAAE,aAAqB;IAC5E,IAAI,aAAa,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC/B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrF,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC1D,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AACvD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAuB;IAC5D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAClC,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QAC5B,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;oBAAE,KAAK,IAAK,GAAW,CAAC,IAAI,CAAC,MAAM,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,SAAS,CACvB,QAAuB,EACvB,WAA+B;IAE/B,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,4BAA4B,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;IAC5F,CAAC;IACD,qEAAqE;IACrE,oEAAoE;IACpE,+BAA+B;IAC/B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,mBAAmB,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;AAC3E,CAAC"}
|