mistagent 0.1.21 → 0.1.23
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/dist/src/api/auth.d.ts +15 -2
- package/dist/src/api/auth.js +16 -6
- package/dist/src/api/client.js +13 -9
- package/dist/src/api/quota.d.ts +3 -0
- package/dist/src/api/quota.js +3 -0
- package/dist/src/components/LoginPrompt.d.ts +1 -1
- package/dist/src/components/LoginPrompt.js +10 -10
- package/dist/src/hooks/useSlashCommand.js +5 -5
- package/dist/src/main.js +12 -4
- package/dist/src/tools/code-analyzer/core/ingestion/call-processor.js +56 -7
- package/dist/src/tools/code-analyzer/core/ingestion/parsing-processor.js +5 -1
- package/dist/src/tools/code-analyzer/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/src/tools/code-analyzer/core/ingestion/tree-sitter-queries.js +15 -0
- package/dist/src/types/api.d.ts +0 -11
- package/dist/src/utils/config.d.ts +1 -1
- package/dist/src/utils/config.js +2 -2
- package/dist/src/utils/constants.d.ts +1 -1
- package/dist/src/utils/constants.js +1 -1
- package/package.json +1 -1
package/dist/src/api/auth.d.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import type { AuthStatus,
|
|
1
|
+
import type { AuthStatus, UserInfo } from '../types/api.js';
|
|
2
2
|
export declare const authApi: {
|
|
3
3
|
getStatus(): Promise<AuthStatus>;
|
|
4
|
-
login(username: string, password: string): Promise<LoginResponse>;
|
|
5
4
|
getMe(): Promise<UserInfo>;
|
|
6
5
|
};
|
|
6
|
+
/** Supabase 直连登录 — POST /auth/v1/token?grant_type=password */
|
|
7
|
+
export interface SupabaseLoginResult {
|
|
8
|
+
access_token: string;
|
|
9
|
+
refresh_token: string;
|
|
10
|
+
user: {
|
|
11
|
+
id: string;
|
|
12
|
+
email: string;
|
|
13
|
+
user_metadata: {
|
|
14
|
+
username?: string;
|
|
15
|
+
display_name?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function supabaseLogin(supabaseUrl: string, anonKey: string, email: string, password: string): Promise<SupabaseLoginResult>;
|
|
7
20
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/src/api/auth.js
CHANGED
|
@@ -3,14 +3,24 @@ export const authApi = {
|
|
|
3
3
|
getStatus() {
|
|
4
4
|
return getClient().get('/api/v1/auth/status');
|
|
5
5
|
},
|
|
6
|
-
login(username, password) {
|
|
7
|
-
return getClient().post('/api/v1/auth/login', {
|
|
8
|
-
username,
|
|
9
|
-
password,
|
|
10
|
-
});
|
|
11
|
-
},
|
|
12
6
|
getMe() {
|
|
13
7
|
return getClient().get('/api/v1/auth/me');
|
|
14
8
|
},
|
|
15
9
|
};
|
|
10
|
+
export async function supabaseLogin(supabaseUrl, anonKey, email, password) {
|
|
11
|
+
const res = await fetch(`${supabaseUrl}/auth/v1/token?grant_type=password`, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
'apikey': anonKey,
|
|
16
|
+
},
|
|
17
|
+
body: JSON.stringify({ email, password }),
|
|
18
|
+
});
|
|
19
|
+
if (!res.ok) {
|
|
20
|
+
const body = await res.json().catch(() => null);
|
|
21
|
+
const msg = body?.error_description || body?.msg || 'Login failed';
|
|
22
|
+
throw new Error(msg);
|
|
23
|
+
}
|
|
24
|
+
return res.json();
|
|
25
|
+
}
|
|
16
26
|
//# sourceMappingURL=auth.js.map
|
package/dist/src/api/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Base HTTP client with JWT auth support
|
|
2
|
+
import { VERSION } from '../utils/constants.js';
|
|
2
3
|
export class ApiError extends Error {
|
|
3
4
|
status;
|
|
4
5
|
body;
|
|
@@ -9,6 +10,14 @@ export class ApiError extends Error {
|
|
|
9
10
|
this.name = 'ApiError';
|
|
10
11
|
}
|
|
11
12
|
}
|
|
13
|
+
// Client-identity headers attached to every request so the backend can
|
|
14
|
+
// distinguish CLI sessions from the web UI and tailor the system prompt
|
|
15
|
+
// (e.g. expose bash_shell_run, file tunnel, etc.).
|
|
16
|
+
const CLIENT_HEADERS = Object.freeze({
|
|
17
|
+
'X-Mist-Client': 'cli',
|
|
18
|
+
'X-Mist-Client-Version': VERSION,
|
|
19
|
+
'User-Agent': `mistagent-cli/${VERSION}`,
|
|
20
|
+
});
|
|
12
21
|
export class ApiClient {
|
|
13
22
|
baseUrl;
|
|
14
23
|
token = null;
|
|
@@ -22,7 +31,7 @@ export class ApiClient {
|
|
|
22
31
|
return this.token;
|
|
23
32
|
}
|
|
24
33
|
authHeaders() {
|
|
25
|
-
const headers = {};
|
|
34
|
+
const headers = { ...CLIENT_HEADERS };
|
|
26
35
|
if (this.token) {
|
|
27
36
|
headers['Authorization'] = `Bearer ${this.token}`;
|
|
28
37
|
}
|
|
@@ -89,11 +98,9 @@ export class ApiClient {
|
|
|
89
98
|
for (const [k, v] of Object.entries(params)) {
|
|
90
99
|
url.searchParams.set(k, v);
|
|
91
100
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
const res = await fetch(url.toString());
|
|
101
|
+
const res = await fetch(url.toString(), {
|
|
102
|
+
headers: this.authHeaders(),
|
|
103
|
+
});
|
|
97
104
|
if (!res.ok) {
|
|
98
105
|
throw new ApiError(res.status, await res.text());
|
|
99
106
|
}
|
|
@@ -105,9 +112,6 @@ export class ApiClient {
|
|
|
105
112
|
// SSE streaming via POST - for large payloads (e.g. messages with file contents)
|
|
106
113
|
async streamPost(path, body) {
|
|
107
114
|
const url = new URL(path, this.baseUrl);
|
|
108
|
-
if (this.token) {
|
|
109
|
-
url.searchParams.set('token', this.token);
|
|
110
|
-
}
|
|
111
115
|
const res = await fetch(url.toString(), {
|
|
112
116
|
method: 'POST',
|
|
113
117
|
headers: {
|
package/dist/src/api/quota.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export interface QuotaBalance {
|
|
|
2
2
|
usd_balance: number;
|
|
3
3
|
usd_total_granted: number;
|
|
4
4
|
usd_total_consumed: number;
|
|
5
|
+
}
|
|
6
|
+
export interface UsageSummary {
|
|
5
7
|
usage_today_tokens: number;
|
|
6
8
|
usage_this_month_tokens: number;
|
|
7
9
|
cost_today_usd: number;
|
|
@@ -9,5 +11,6 @@ export interface QuotaBalance {
|
|
|
9
11
|
}
|
|
10
12
|
export declare const quotaApi: {
|
|
11
13
|
balance(): Promise<QuotaBalance>;
|
|
14
|
+
usageSummary(): Promise<UsageSummary>;
|
|
12
15
|
};
|
|
13
16
|
//# sourceMappingURL=quota.d.ts.map
|
package/dist/src/api/quota.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
interface LoginPromptProps {
|
|
3
|
-
onLogin: (
|
|
3
|
+
onLogin: (email: string, password: string) => Promise<void>;
|
|
4
4
|
error?: string | null;
|
|
5
5
|
}
|
|
6
6
|
export declare const LoginPrompt: React.FC<LoginPromptProps>;
|
|
@@ -46,8 +46,8 @@ const SimpleInput = ({ value, onChange, onSubmit, mask }) => {
|
|
|
46
46
|
// ── LoginPrompt ──────────────────────────────────────────
|
|
47
47
|
export const LoginPrompt = ({ onLogin, error, }) => {
|
|
48
48
|
const { subscribe, unsubscribe } = useKeypressContext();
|
|
49
|
-
const [step, setStep] = useState('
|
|
50
|
-
const [
|
|
49
|
+
const [step, setStep] = useState('email');
|
|
50
|
+
const [email, setEmail] = useState('');
|
|
51
51
|
const [password, setPassword] = useState('');
|
|
52
52
|
const [isLoading, setIsLoading] = useState(false);
|
|
53
53
|
const [ctrlCPressedOnce, setCtrlCPressedOnce] = useState(false);
|
|
@@ -72,9 +72,9 @@ export const LoginPrompt = ({ onLogin, error, }) => {
|
|
|
72
72
|
subscribe(ctrlCHandler, KeypressPriority.Normal);
|
|
73
73
|
return () => unsubscribe(ctrlCHandler);
|
|
74
74
|
}, [ctrlCHandler, subscribe, unsubscribe]);
|
|
75
|
-
const
|
|
75
|
+
const handleEmailSubmit = useCallback((val) => {
|
|
76
76
|
if (val.trim()) {
|
|
77
|
-
|
|
77
|
+
setEmail(val.trim());
|
|
78
78
|
setStep('password');
|
|
79
79
|
}
|
|
80
80
|
}, []);
|
|
@@ -83,19 +83,19 @@ export const LoginPrompt = ({ onLogin, error, }) => {
|
|
|
83
83
|
setPassword(val.trim());
|
|
84
84
|
setIsLoading(true);
|
|
85
85
|
try {
|
|
86
|
-
await onLogin(
|
|
86
|
+
await onLogin(email, val.trim());
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
finally {
|
|
89
89
|
setIsLoading(false);
|
|
90
|
-
setStep('
|
|
91
|
-
|
|
90
|
+
setStep('email');
|
|
91
|
+
setEmail('');
|
|
92
92
|
setPassword('');
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
}, [onLogin,
|
|
95
|
+
}, [onLogin, email]);
|
|
96
96
|
return (_jsxs(Box, { flexDirection: "column", alignItems: "center", padding: 1, children: [_jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [BANNER_LINES.map((line, i) => {
|
|
97
97
|
const gradient = getBannerGradient();
|
|
98
98
|
return (_jsx(Text, { color: gradient[i] ?? gradient[0], children: line }, i));
|
|
99
|
-
}), _jsx(Text, { color: palette.textMuted, children: BANNER_SUBTITLE }), _jsx(Text, { color: palette.textDim, children: ' v' + VERSION })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: error ? palette.error : palette.border, paddingX: 3, paddingY: 1, width: 48, children: [error && (_jsx(Box, { marginBottom: 1, justifyContent: "center", children: _jsxs(Text, { color: palette.error, children: ['✗ ', error] }) })), isLoading ? (_jsx(Box, { justifyContent: "center", paddingY: 1, children: _jsx(Spinner, { label: "Authenticating..." }) })) : step === '
|
|
99
|
+
}), _jsx(Text, { color: palette.textMuted, children: BANNER_SUBTITLE }), _jsx(Text, { color: palette.textDim, children: ' v' + VERSION })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: error ? palette.error : palette.border, paddingX: 3, paddingY: 1, width: 48, children: [error && (_jsx(Box, { marginBottom: 1, justifyContent: "center", children: _jsxs(Text, { color: palette.error, children: ['✗ ', error] }) })), isLoading ? (_jsx(Box, { justifyContent: "center", paddingY: 1, children: _jsx(Spinner, { label: "Authenticating..." }) })) : step === 'email' ? (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: palette.primary, bold: true, children: ' ❯ Email ' }), _jsx(SimpleInput, { value: email, onChange: setEmail, onSubmit: handleEmailSubmit })] }), _jsx(Box, { children: _jsx(Text, { color: palette.textDim, children: ' ○ Password' }) })] })) : (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: palette.success, children: ' ✓ ' }), _jsx(Text, { color: palette.textMuted, children: 'Email ' }), _jsx(Text, { children: email })] }), _jsxs(Box, { children: [_jsx(Text, { color: palette.primary, bold: true, children: ' ❯ Password ' }), _jsx(SimpleInput, { value: password, onChange: setPassword, onSubmit: handlePasswordSubmit, mask: "\u2022" })] })] })), _jsx(Box, { justifyContent: "center", marginTop: 1, children: ctrlCPressedOnce ? (_jsx(Text, { color: palette.warning, bold: true, children: "Press Ctrl-C again to exit" })) : (_jsxs(Text, { color: palette.textDim, dimColor: true, children: ["Press ", _jsx(Text, { color: palette.textMuted, children: "Enter" }), " to continue"] })) })] })] }));
|
|
100
100
|
};
|
|
101
101
|
//# sourceMappingURL=LoginPrompt.js.map
|
|
@@ -109,7 +109,7 @@ export function useSlashCommand() {
|
|
|
109
109
|
if (trimmed === '/usage') {
|
|
110
110
|
dispatch({ type: 'SET_BUSY', busy: true });
|
|
111
111
|
try {
|
|
112
|
-
const b = await quotaApi.balance();
|
|
112
|
+
const [b, u] = await Promise.all([quotaApi.balance(), quotaApi.usageSummary()]);
|
|
113
113
|
const fmt = (v) => `$${v.toFixed(4)}`;
|
|
114
114
|
const fmtTokens = (v) => v >= 1_000_000
|
|
115
115
|
? `${(v / 1_000_000).toFixed(1)}M`
|
|
@@ -123,12 +123,12 @@ export function useSlashCommand() {
|
|
|
123
123
|
` 总消耗: ${fmt(b.usd_total_consumed)}`,
|
|
124
124
|
``,
|
|
125
125
|
`**今日用量**`,
|
|
126
|
-
` Tokens: ${fmtTokens(
|
|
127
|
-
` 费用: ${fmt(
|
|
126
|
+
` Tokens: ${fmtTokens(u.usage_today_tokens)}`,
|
|
127
|
+
` 费用: ${fmt(u.cost_today_usd)}`,
|
|
128
128
|
``,
|
|
129
129
|
`**本月用量**`,
|
|
130
|
-
` Tokens: ${fmtTokens(
|
|
131
|
-
` 费用: ${fmt(
|
|
130
|
+
` Tokens: ${fmtTokens(u.usage_this_month_tokens)}`,
|
|
131
|
+
` 费用: ${fmt(u.cost_this_month_usd)}`,
|
|
132
132
|
];
|
|
133
133
|
dispatch({
|
|
134
134
|
type: 'ADD_ITEM',
|
package/dist/src/main.js
CHANGED
|
@@ -3,7 +3,7 @@ import { render } from 'ink';
|
|
|
3
3
|
import yargs from 'yargs';
|
|
4
4
|
import { hideBin } from 'yargs/helpers';
|
|
5
5
|
import { initClient } from './api/client.js';
|
|
6
|
-
import { authApi } from './api/auth.js';
|
|
6
|
+
import { authApi, supabaseLogin } from './api/auth.js';
|
|
7
7
|
import { modelsApi } from './api/models.js';
|
|
8
8
|
import { toolsApi } from './api/tools.js';
|
|
9
9
|
import { skillsApi } from './api/skills.js';
|
|
@@ -211,16 +211,24 @@ export async function main() {
|
|
|
211
211
|
terminalHeight: process.stdout.rows || 24,
|
|
212
212
|
});
|
|
213
213
|
const renderApp = (overrides = {}) => (_jsx(App, { serverUrl: serverUrl, token: overrides.token ?? token, username: overrides.username ?? username, authEnabled: authStatus.auth_enabled, version: healthData?.version ?? VERSION, healthData: healthData, availableCommands: commands, availableTools: tools, initialModels: models, initialCurrentModel: currentModel, initialSessions: initialSessions, initialTheme: initialTheme, onLogin: handleLogin, onLogout: handleLogout, loginError: overrides.loginError ?? loginError, isAuthenticated: overrides.isAuthenticated ?? isAuthenticated, ...getTerminalSize() }));
|
|
214
|
-
const handleLogin = async (
|
|
214
|
+
const handleLogin = async (email, pass) => {
|
|
215
|
+
const sbUrl = authStatus.supabase_url;
|
|
216
|
+
const sbKey = authStatus.supabase_anon_key;
|
|
217
|
+
if (!sbUrl || !sbKey) {
|
|
218
|
+
loginError = 'Supabase not configured on server';
|
|
219
|
+
rerender(renderApp({ token: null, username: null, isAuthenticated: false, loginError }));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
215
222
|
try {
|
|
216
|
-
const res = await
|
|
223
|
+
const res = await supabaseLogin(sbUrl, sbKey, email, pass);
|
|
217
224
|
client.setToken(res.access_token);
|
|
218
225
|
saveToken(res.access_token);
|
|
219
226
|
if (res.refresh_token) {
|
|
220
227
|
saveRefreshToken(res.refresh_token);
|
|
221
228
|
}
|
|
222
229
|
token = res.access_token;
|
|
223
|
-
|
|
230
|
+
const meta = res.user?.user_metadata ?? {};
|
|
231
|
+
username = meta.display_name || meta.username || email;
|
|
224
232
|
isAuthenticated = true;
|
|
225
233
|
loginError = null;
|
|
226
234
|
startTokenRefresh();
|
|
@@ -3,6 +3,7 @@ import { loadParser, loadLanguage } from '../tree-sitter/parser-loader.js';
|
|
|
3
3
|
import { LANGUAGE_QUERIES } from './tree-sitter-queries.js';
|
|
4
4
|
import { generateId } from '../../lib/utils.js';
|
|
5
5
|
import { getLanguageFromFilename, yieldToEventLoop } from './utils.js';
|
|
6
|
+
import { SupportedLanguages } from '../../config/supported-languages.js';
|
|
6
7
|
/**
|
|
7
8
|
* Node types that represent function/method definitions across languages.
|
|
8
9
|
* Used to find the enclosing function for a call site.
|
|
@@ -50,8 +51,35 @@ const findEnclosingFunction = (node, filePath, symbolTable) => {
|
|
|
50
51
|
current.type === 'generator_function_declaration' ||
|
|
51
52
|
current.type === 'function_item') { // Rust function
|
|
52
53
|
// Named function: function foo() {}
|
|
53
|
-
|
|
54
|
+
// (patch-05) C/C++ function_definition has no 'name' field — the name
|
|
55
|
+
// lives at declarator.declarator.identifier (or .field_identifier for
|
|
56
|
+
// C++ qualified names). The tree-sitter query in tree-sitter-queries.ts
|
|
57
|
+
// does this correctly; here in the AST walker we must mirror it.
|
|
58
|
+
let nameNode = current.childForFieldName?.('name') ||
|
|
54
59
|
current.children?.find((c) => c.type === 'identifier' || c.type === 'property_identifier');
|
|
60
|
+
if (!nameNode && current.type === 'function_definition') {
|
|
61
|
+
// C/C++ path: walk declarator → declarator → identifier|field_identifier
|
|
62
|
+
let decl = current.childForFieldName?.('declarator');
|
|
63
|
+
// Strip pointer_declarator / reference_declarator wrappers
|
|
64
|
+
while (decl && (decl.type === 'pointer_declarator' || decl.type === 'reference_declarator')) {
|
|
65
|
+
decl = decl.childForFieldName?.('declarator') || decl.children?.find((c) => c.type !== '*' && c.type !== '&');
|
|
66
|
+
}
|
|
67
|
+
if (decl?.type === 'function_declarator') {
|
|
68
|
+
let inner = decl.childForFieldName?.('declarator');
|
|
69
|
+
// Some C++ qualified names look like (qualified_identifier scope::name)
|
|
70
|
+
while (inner && (inner.type === 'parenthesized_declarator' || inner.type === 'pointer_declarator')) {
|
|
71
|
+
inner = inner.childForFieldName?.('declarator') || inner.children?.find((c) => c.type === 'identifier' || c.type === 'field_identifier' || c.type === 'qualified_identifier');
|
|
72
|
+
}
|
|
73
|
+
if (inner?.type === 'identifier' || inner?.type === 'field_identifier') {
|
|
74
|
+
nameNode = inner;
|
|
75
|
+
}
|
|
76
|
+
else if (inner?.type === 'qualified_identifier') {
|
|
77
|
+
// C++ Class::method — take rightmost identifier
|
|
78
|
+
nameNode = inner.descendantsOfType?.('identifier')?.pop() ||
|
|
79
|
+
inner.children?.find((c) => c.type === 'identifier');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
55
83
|
funcName = nameNode?.text;
|
|
56
84
|
}
|
|
57
85
|
else if (current.type === 'impl_item') {
|
|
@@ -136,9 +164,10 @@ export const processCalls = async (graph, files, astCache, symbolTable, importMa
|
|
|
136
164
|
let wasReparsed = false;
|
|
137
165
|
if (!tree) {
|
|
138
166
|
// Cache Miss: Re-parse
|
|
139
|
-
//
|
|
167
|
+
// (patch-05) 4MB buffer 覆盖 filesystem-walker 允许的 2MB 文件上限;
|
|
168
|
+
// 见 parsing-processor.ts 同位 comment
|
|
140
169
|
try {
|
|
141
|
-
tree = parser.parse(file.content, undefined, { bufferSize: 1024 *
|
|
170
|
+
tree = parser.parse(file.content, undefined, { bufferSize: 1024 * 1024 * 4 });
|
|
142
171
|
}
|
|
143
172
|
catch (parseError) {
|
|
144
173
|
// Skip files that can't be parsed
|
|
@@ -174,7 +203,7 @@ export const processCalls = async (graph, files, astCache, symbolTable, importMa
|
|
|
174
203
|
if (isBuiltInOrNoise(calledName))
|
|
175
204
|
return;
|
|
176
205
|
// 4. Resolve the target using priority strategy (returns confidence)
|
|
177
|
-
const resolved = resolveCallTarget(calledName, file.path, symbolTable, importMap);
|
|
206
|
+
const resolved = resolveCallTarget(calledName, file.path, symbolTable, importMap, language);
|
|
178
207
|
if (!resolved)
|
|
179
208
|
return;
|
|
180
209
|
// 5. Find the enclosing function (caller)
|
|
@@ -201,9 +230,23 @@ export const processCalls = async (graph, files, astCache, symbolTable, importMa
|
|
|
201
230
|
* B. Check local file definitions
|
|
202
231
|
* C. Fuzzy global search (lowest confidence)
|
|
203
232
|
*
|
|
204
|
-
*
|
|
233
|
+
* C/C++ special-case (patch C — 2026-05-15):
|
|
234
|
+
* In C/C++, function symbols are linker-visible across the whole binary; the
|
|
235
|
+
* `#include` graph is only a compile-time convenience that conveys prototypes,
|
|
236
|
+
* not the actual call topology. Many C projects (vim, linux kernel) use a
|
|
237
|
+
* single proto.h or auto-generated <name>.pro forward-declares so callers
|
|
238
|
+
* never #include the implementing .c file directly. Treating those as
|
|
239
|
+
* fuzzy-global low-confidence (0.3-0.5) under-counts genuine cross-file
|
|
240
|
+
* calls and pushes them below mist-analyzer's 0.35 dfs threshold, dropping
|
|
241
|
+
* chains like vim's `serverSendToVim → ... → call_internal_func → f_system`.
|
|
242
|
+
*
|
|
243
|
+
* For C/C++ we promote:
|
|
244
|
+
* - globally-unique (1 def in project) → 'c-global-unique' @ 0.85
|
|
245
|
+
* (same level as same-file: the linker resolves these identically)
|
|
246
|
+
* - ambiguous (>1 def with same name) → keep fuzzy-global semantics
|
|
247
|
+
* since we can't pick the right one without preprocessor evaluation.
|
|
205
248
|
*/
|
|
206
|
-
const resolveCallTarget = (calledName, currentFile, symbolTable, importMap) => {
|
|
249
|
+
const resolveCallTarget = (calledName, currentFile, symbolTable, importMap, language) => {
|
|
207
250
|
// Strategy B first (cheapest — single map lookup): Check local file
|
|
208
251
|
const localNodeId = symbolTable.lookupExact(currentFile, calledName);
|
|
209
252
|
if (localNodeId) {
|
|
@@ -222,6 +265,11 @@ const resolveCallTarget = (calledName, currentFile, symbolTable, importMap) => {
|
|
|
222
265
|
}
|
|
223
266
|
}
|
|
224
267
|
}
|
|
268
|
+
// C/C++ patch: globally-unique symbols are linker-visible; promote to high.
|
|
269
|
+
if ((language === SupportedLanguages.C || language === SupportedLanguages.CPlusPlus) &&
|
|
270
|
+
allDefs.length === 1) {
|
|
271
|
+
return { nodeId: allDefs[0].nodeId, confidence: 0.85, reason: 'c-global-unique' };
|
|
272
|
+
}
|
|
225
273
|
// Strategy C: Fuzzy global (no import match found)
|
|
226
274
|
const confidence = allDefs.length === 1 ? 0.5 : 0.3;
|
|
227
275
|
return { nodeId: allDefs[0].nodeId, confidence, reason: 'fuzzy-global' };
|
|
@@ -309,7 +357,8 @@ export const processCallsFromExtracted = async (graph, extractedCalls, symbolTab
|
|
|
309
357
|
await yieldToEventLoop();
|
|
310
358
|
}
|
|
311
359
|
for (const call of calls) {
|
|
312
|
-
const
|
|
360
|
+
const callLang = getLanguageFromFilename(call.filePath);
|
|
361
|
+
const resolved = resolveCallTarget(call.calledName, call.filePath, symbolTable, importMap, callLang);
|
|
313
362
|
if (!resolved)
|
|
314
363
|
continue;
|
|
315
364
|
const relId = generateId('CALLS', `${call.sourceId}:${call.calledName}->${resolved.nodeId}`);
|
|
@@ -162,7 +162,11 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, onF
|
|
|
162
162
|
await loadLanguage(language, file.path);
|
|
163
163
|
let tree;
|
|
164
164
|
try {
|
|
165
|
-
|
|
165
|
+
// (patch-05) bufferSize 必须 ≥ 文件大小;原 256KB 对 vim evalfunc.c (315KB)
|
|
166
|
+
// 这种"单一巨大 C 文件"导致 tree-sitter 静默截断 → parse 出几百个 ERROR
|
|
167
|
+
// + 0 函数抽出。filesystem-walker 拒 > 2MB 文件,所以 4MB buffer 覆盖
|
|
168
|
+
// 所有合法 input。
|
|
169
|
+
tree = parser.parse(file.content, undefined, { bufferSize: 1024 * 1024 * 4 });
|
|
166
170
|
}
|
|
167
171
|
catch (parseError) {
|
|
168
172
|
console.warn(`Skipping unparseable file: ${file.path}`);
|
|
@@ -3,9 +3,9 @@ export declare const TYPESCRIPT_QUERIES = "\n(class_declaration\n name: (type_i
|
|
|
3
3
|
export declare const JAVASCRIPT_QUERIES = "\n(class_declaration\n name: (identifier) @name) @definition.class\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n(import_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Heritage queries - class extends (JavaScript uses different AST than TypeScript)\n; In tree-sitter-javascript, class_heritage directly contains the parent identifier\n(class_declaration\n name: (identifier) @heritage.class\n (class_heritage\n (identifier) @heritage.extends)) @heritage\n";
|
|
4
4
|
export declare const PYTHON_QUERIES = "\n(class_definition\n name: (identifier) @name) @definition.class\n\n(function_definition\n name: (identifier) @name) @definition.function\n\n(import_statement\n name: (dotted_name) @import.source) @import\n\n(import_from_statement\n module_name: (dotted_name) @import.source) @import\n\n(call\n function: (identifier) @call.name) @call\n\n(call\n function: (attribute\n attribute: (identifier) @call.name)) @call\n\n; Heritage queries - Python class inheritance\n(class_definition\n name: (identifier) @heritage.class\n superclasses: (argument_list\n (identifier) @heritage.extends)) @heritage\n";
|
|
5
5
|
export declare const JAVA_QUERIES = "\n; Classes, Interfaces, Enums, Annotations\n(class_declaration name: (identifier) @name) @definition.class\n(interface_declaration name: (identifier) @name) @definition.interface\n(enum_declaration name: (identifier) @name) @definition.enum\n(annotation_type_declaration name: (identifier) @name) @definition.annotation\n\n; Methods & Constructors\n(method_declaration name: (identifier) @name) @definition.method\n(constructor_declaration name: (identifier) @name) @definition.constructor\n\n; Imports - capture any import declaration child as source\n(import_declaration (_) @import.source) @import\n\n; Calls\n(method_invocation name: (identifier) @call.name) @call\n(method_invocation object: (_) name: (identifier) @call.name) @call\n\n; Heritage - extends class\n(class_declaration name: (identifier) @heritage.class\n (superclass (type_identifier) @heritage.extends)) @heritage\n\n; Heritage - implements interfaces\n(class_declaration name: (identifier) @heritage.class\n (super_interfaces (type_list (type_identifier) @heritage.implements))) @heritage.impl\n";
|
|
6
|
-
export declare const C_QUERIES = "\n; Functions\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n\n; Structs, Unions, Enums, Typedefs\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(union_specifier name: (type_identifier) @name) @definition.union\n(enum_specifier name: (type_identifier) @name) @definition.enum\n(type_definition declarator: (type_identifier) @name) @definition.typedef\n\n; Macros\n(preproc_function_def name: (identifier) @name) @definition.macro\n(preproc_def name: (identifier) @name) @definition.macro\n\n; Includes\n(preproc_include path: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n";
|
|
6
|
+
export declare const C_QUERIES = "\n; Functions\n; (patch-05) cover return-by-pointer / pointer-to-pointer styles common in vim,\n; the kernel, OpenSSL, etc. AST shape for \"char *foo(...)\" is\n; function_definition\n; declarator: pointer_declarator (the leading *)\n; declarator: function_declarator\n; declarator: identifier (name)\n; Repeat for char **foo, char ***foo (pointer-of-pointer).\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @definition.function\n(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(declaration declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n\n; Structs, Unions, Enums, Typedefs\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(union_specifier name: (type_identifier) @name) @definition.union\n(enum_specifier name: (type_identifier) @name) @definition.enum\n(type_definition declarator: (type_identifier) @name) @definition.typedef\n\n; Macros\n(preproc_function_def name: (identifier) @name) @definition.macro\n(preproc_def name: (identifier) @name) @definition.macro\n\n; Includes\n(preproc_include path: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n";
|
|
7
7
|
export declare const GO_QUERIES = "\n; Functions & Methods\n(function_declaration name: (identifier) @name) @definition.function\n(method_declaration name: (field_identifier) @name) @definition.method\n\n; Types\n(type_declaration (type_spec name: (type_identifier) @name type: (struct_type))) @definition.struct\n(type_declaration (type_spec name: (type_identifier) @name type: (interface_type))) @definition.interface\n(type_declaration (type_spec name: (type_identifier) @name)) @definition.type\n\n; Imports\n(import_declaration (import_spec path: (interpreted_string_literal) @import.source)) @import\n(import_declaration (import_spec_list (import_spec path: (interpreted_string_literal) @import.source))) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (selector_expression field: (field_identifier) @call.name)) @call\n";
|
|
8
|
-
export declare const CPP_QUERIES = "\n; Classes, Structs, Namespaces\n(class_specifier name: (type_identifier) @name) @definition.class\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(namespace_definition name: (namespace_identifier) @name) @definition.namespace\n(enum_specifier name: (type_identifier) @name) @definition.enum\n\n; Functions & Methods\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))) @definition.method\n\n; Templates\n(template_declaration (class_specifier name: (type_identifier) @name)) @definition.template\n(template_declaration (function_definition declarator: (function_declarator declarator: (identifier) @name))) @definition.template\n\n; Includes\n(preproc_include path: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n(call_expression function: (qualified_identifier name: (identifier) @call.name)) @call\n(call_expression function: (template_function name: (identifier) @call.name)) @call\n\n; Heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (type_identifier) @heritage.extends)) @heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (access_specifier) (type_identifier) @heritage.extends)) @heritage\n";
|
|
8
|
+
export declare const CPP_QUERIES = "\n; Classes, Structs, Namespaces\n(class_specifier name: (type_identifier) @name) @definition.class\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(namespace_definition name: (namespace_identifier) @name) @definition.namespace\n(enum_specifier name: (type_identifier) @name) @definition.enum\n\n; Functions & Methods\n; (patch-05) same return-by-pointer/reference cases as C, plus C++ qualified names.\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))) @definition.method\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method\n(function_definition declarator: (reference_declarator (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (reference_declarator (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method\n\n; Templates\n(template_declaration (class_specifier name: (type_identifier) @name)) @definition.template\n(template_declaration (function_definition declarator: (function_declarator declarator: (identifier) @name))) @definition.template\n\n; Includes\n(preproc_include path: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n(call_expression function: (qualified_identifier name: (identifier) @call.name)) @call\n(call_expression function: (template_function name: (identifier) @call.name)) @call\n\n; Heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (type_identifier) @heritage.extends)) @heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (access_specifier) (type_identifier) @heritage.extends)) @heritage\n";
|
|
9
9
|
export declare const CSHARP_QUERIES = "\n; Types\n(class_declaration name: (identifier) @name) @definition.class\n(interface_declaration name: (identifier) @name) @definition.interface\n(struct_declaration name: (identifier) @name) @definition.struct\n(enum_declaration name: (identifier) @name) @definition.enum\n(record_declaration name: (identifier) @name) @definition.record\n(delegate_declaration name: (identifier) @name) @definition.delegate\n\n; Namespaces\n(namespace_declaration name: (identifier) @name) @definition.namespace\n(namespace_declaration name: (qualified_name) @name) @definition.namespace\n\n; Methods & Properties\n(method_declaration name: (identifier) @name) @definition.method\n(local_function_statement name: (identifier) @name) @definition.function\n(constructor_declaration name: (identifier) @name) @definition.constructor\n(property_declaration name: (identifier) @name) @definition.property\n\n; Using\n(using_directive (qualified_name) @import.source) @import\n(using_directive (identifier) @import.source) @import\n\n; Calls\n(invocation_expression function: (identifier) @call.name) @call\n(invocation_expression function: (member_access_expression name: (identifier) @call.name)) @call\n\n; Heritage\n(class_declaration name: (identifier) @heritage.class\n (base_list (simple_base_type (identifier) @heritage.extends))) @heritage\n(class_declaration name: (identifier) @heritage.class\n (base_list (simple_base_type (generic_name (identifier) @heritage.extends)))) @heritage\n";
|
|
10
10
|
export declare const RUST_QUERIES = "\n; Functions & Items\n(function_item name: (identifier) @name) @definition.function\n(struct_item name: (type_identifier) @name) @definition.struct\n(enum_item name: (type_identifier) @name) @definition.enum\n(trait_item name: (type_identifier) @name) @definition.trait\n(impl_item type: (type_identifier) @name) @definition.impl\n(mod_item name: (identifier) @name) @definition.module\n\n; Type aliases, const, static, macros\n(type_item name: (type_identifier) @name) @definition.type\n(const_item name: (identifier) @name) @definition.const\n(static_item name: (identifier) @name) @definition.static\n(macro_definition name: (identifier) @name) @definition.macro\n\n; Use statements\n(use_declaration argument: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n(call_expression function: (scoped_identifier name: (identifier) @call.name)) @call\n(call_expression function: (generic_function function: (identifier) @call.name)) @call\n\n; Heritage (trait implementation)\n(impl_item trait: (type_identifier) @heritage.trait type: (type_identifier) @heritage.class) @heritage\n(impl_item trait: (generic_type type: (type_identifier) @heritage.trait) type: (type_identifier) @heritage.class) @heritage\n";
|
|
11
11
|
export declare const SOLIDITY_QUERIES = "\n; Contracts, Libraries, Interfaces\n(contract_declaration name: (identifier) @name) @definition.class\n(library_declaration name: (identifier) @name) @definition.class\n(interface_declaration name: (identifier) @name) @definition.interface\n\n; Functions, Constructors, Modifiers\n(function_definition name: (identifier) @name) @definition.function\n(modifier_definition name: (identifier) @name) @definition.function\n\n; Events, Errors\n(event_definition name: (identifier) @name) @definition.function\n(error_declaration name: (identifier) @name) @definition.function\n\n; Structs, Enums\n(struct_declaration name: (identifier) @name) @definition.struct\n(enum_declaration name: (identifier) @name) @definition.enum\n\n; Imports\n(import_directive source: (string) @import.source) @import\n\n; Calls (Solidity call_expression uses 'expression' child, not 'function' field)\n(call_expression (expression (identifier) @call.name)) @call\n(call_expression (expression (member_expression property: (identifier) @call.name))) @call\n\n; Heritage - contract inheritance (contract X is Y, Z)\n(contract_declaration\n name: (identifier) @heritage.class\n (inheritance_specifier ancestor: (user_defined_type (identifier) @heritage.extends))) @heritage\n(interface_declaration\n name: (identifier) @heritage.class\n (inheritance_specifier ancestor: (user_defined_type (identifier) @heritage.extends))) @heritage\n";
|
|
@@ -173,8 +173,18 @@ export const JAVA_QUERIES = `
|
|
|
173
173
|
// C queries - works with tree-sitter-c
|
|
174
174
|
export const C_QUERIES = `
|
|
175
175
|
; Functions
|
|
176
|
+
; (patch-05) cover return-by-pointer / pointer-to-pointer styles common in vim,
|
|
177
|
+
; the kernel, OpenSSL, etc. AST shape for "char *foo(...)" is
|
|
178
|
+
; function_definition
|
|
179
|
+
; declarator: pointer_declarator (the leading *)
|
|
180
|
+
; declarator: function_declarator
|
|
181
|
+
; declarator: identifier (name)
|
|
182
|
+
; Repeat for char **foo, char ***foo (pointer-of-pointer).
|
|
176
183
|
(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function
|
|
184
|
+
(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function
|
|
185
|
+
(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @definition.function
|
|
177
186
|
(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function
|
|
187
|
+
(declaration declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function
|
|
178
188
|
|
|
179
189
|
; Structs, Unions, Enums, Typedefs
|
|
180
190
|
(struct_specifier name: (type_identifier) @name) @definition.struct
|
|
@@ -221,8 +231,13 @@ export const CPP_QUERIES = `
|
|
|
221
231
|
(enum_specifier name: (type_identifier) @name) @definition.enum
|
|
222
232
|
|
|
223
233
|
; Functions & Methods
|
|
234
|
+
; (patch-05) same return-by-pointer/reference cases as C, plus C++ qualified names.
|
|
224
235
|
(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function
|
|
225
236
|
(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))) @definition.method
|
|
237
|
+
(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function
|
|
238
|
+
(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method
|
|
239
|
+
(function_definition declarator: (reference_declarator (function_declarator declarator: (identifier) @name))) @definition.function
|
|
240
|
+
(function_definition declarator: (reference_declarator (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method
|
|
226
241
|
|
|
227
242
|
; Templates
|
|
228
243
|
(template_declaration (class_specifier name: (type_identifier) @name)) @definition.template
|
package/dist/src/types/api.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
export interface LoginResponse {
|
|
2
|
-
success: boolean;
|
|
3
|
-
access_token: string;
|
|
4
|
-
refresh_token?: string;
|
|
5
|
-
token_type: string;
|
|
6
|
-
user: {
|
|
7
|
-
user_id: string;
|
|
8
|
-
username: string;
|
|
9
|
-
display_name: string;
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
1
|
export interface UserInfo {
|
|
13
2
|
success: boolean;
|
|
14
3
|
user_id: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const DEFAULT_SERVER_URL = "https://
|
|
1
|
+
export declare const DEFAULT_SERVER_URL = "https://agent.slowmist.ai";
|
|
2
2
|
export declare function getServerUrl(cliArg?: string): string;
|
|
3
3
|
export declare function saveToken(token: string): void;
|
|
4
4
|
export declare function loadToken(): string | null;
|
package/dist/src/utils/config.js
CHANGED
|
@@ -9,8 +9,8 @@ const TOKEN_FILE = join(CONFIG_DIR, 'token');
|
|
|
9
9
|
// Supabase refresh token(用于自动续期 access_token)
|
|
10
10
|
const REFRESH_TOKEN_FILE = join(CONFIG_DIR, 'refresh_token');
|
|
11
11
|
// 后端服务器默认地址,可通过 CLI 参数或环境变量 MISTAGENT_SERVER 覆盖
|
|
12
|
-
// 发布时由 publish.sh 自动切换为 'https://
|
|
13
|
-
export const DEFAULT_SERVER_URL = 'https://
|
|
12
|
+
// 发布时由 publish.sh 自动切换为 'https://agent.slowmist.ai',发布后自动改回
|
|
13
|
+
export const DEFAULT_SERVER_URL = 'https://agent.slowmist.ai';
|
|
14
14
|
// 获取后端服务器地址,优先级: CLI 参数 > 环境变量 > 默认值
|
|
15
15
|
// 非 localhost 地址强制要求 HTTPS,防止中间人攻击导致 token 泄露
|
|
16
16
|
export function getServerUrl(cliArg) {
|