surfcode 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +325 -2
- package/assets/surfcode-logo.gif +0 -0
- package/dist/cli/auth.js +315 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/config.js +228 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/headless.js +355 -0
- package/dist/cli/headless.js.map +1 -0
- package/dist/cli/inspect.js +462 -0
- package/dist/cli/inspect.js.map +1 -0
- package/dist/cli/interactive.js +130 -0
- package/dist/cli/interactive.js.map +1 -0
- package/dist/cli/sessions.js +170 -0
- package/dist/cli/sessions.js.map +1 -0
- package/dist/cli/sync.js +190 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/util.js +345 -0
- package/dist/cli/util.js.map +1 -0
- package/dist/cli.js +485 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/agent.js +298 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/agents.js +55 -0
- package/dist/core/agents.js.map +1 -0
- package/dist/core/auth.js +107 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/catalog.js +306 -0
- package/dist/core/catalog.js.map +1 -0
- package/dist/core/chat/anthropic.js +222 -0
- package/dist/core/chat/anthropic.js.map +1 -0
- package/dist/core/chat/common.js +367 -0
- package/dist/core/chat/common.js.map +1 -0
- package/dist/core/chat/google.js +180 -0
- package/dist/core/chat/google.js.map +1 -0
- package/dist/core/chat/index.js +80 -0
- package/dist/core/chat/index.js.map +1 -0
- package/dist/core/chat/openai.js +164 -0
- package/dist/core/chat/openai.js.map +1 -0
- package/dist/core/chat/types.js +2 -0
- package/dist/core/chat/types.js.map +1 -0
- package/dist/core/clipboard.js +34 -0
- package/dist/core/clipboard.js.map +1 -0
- package/dist/core/compact.js +39 -0
- package/dist/core/compact.js.map +1 -0
- package/dist/core/config.js +211 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/delegate.js +184 -0
- package/dist/core/delegate.js.map +1 -0
- package/dist/core/effort.js +80 -0
- package/dist/core/effort.js.map +1 -0
- package/dist/core/errors.js +32 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/free.js +21 -0
- package/dist/core/free.js.map +1 -0
- package/dist/core/github.js +445 -0
- package/dist/core/github.js.map +1 -0
- package/dist/core/paths.js +51 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/prompt.js +95 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/provider.js +298 -0
- package/dist/core/provider.js.map +1 -0
- package/dist/core/session.js +159 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/sync.js +126 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage.js +127 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/core/workspace.js +70 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/data/models.json +1 -0
- package/dist/sync/server.js +179 -0
- package/dist/sync/server.js.map +1 -0
- package/dist/tools/diff.js +21 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/files.js +227 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/github.js +238 -0
- package/dist/tools/github.js.map +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/search.js +231 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/shell.js +118 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/tools/todos.js +50 -0
- package/dist/tools/todos.js.map +1 -0
- package/dist/tools/webfetch.js +108 -0
- package/dist/tools/webfetch.js.map +1 -0
- package/dist/tui/App.js +2984 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/ansi.js +151 -0
- package/dist/tui/ansi.js.map +1 -0
- package/dist/tui/commands.js +61 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/explorer.js +152 -0
- package/dist/tui/explorer.js.map +1 -0
- package/dist/tui/icons.js +21 -0
- package/dist/tui/icons.js.map +1 -0
- package/dist/tui/layout.js +324 -0
- package/dist/tui/layout.js.map +1 -0
- package/dist/tui/markdown.js +355 -0
- package/dist/tui/markdown.js.map +1 -0
- package/dist/tui/overlays.js +316 -0
- package/dist/tui/overlays.js.map +1 -0
- package/dist/tui/render.js +234 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/theme.js +148 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/types.js +73 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +75 -4
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { SurfError } from '../core/errors.js';
|
|
2
|
+
import { createGithubRepository, ensureGitRepository, gitRemote, githubGitState, githubTokenStatus, publishToGithub, requireGithubToken, setGithubRemote } from '../core/github.js';
|
|
3
|
+
function stringArray(value) {
|
|
4
|
+
if (!Array.isArray(value))
|
|
5
|
+
return undefined;
|
|
6
|
+
const items = value
|
|
7
|
+
.map((entry) => (typeof entry === 'string' ? entry.trim() : ''))
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
return items.length > 0 ? items : undefined;
|
|
10
|
+
}
|
|
11
|
+
function summary(files, limit = 12) {
|
|
12
|
+
if (files.length === 0)
|
|
13
|
+
return 'no file changes';
|
|
14
|
+
const shown = files.slice(0, limit).join(', ');
|
|
15
|
+
return files.length > limit ? `${shown}, +${files.length - limit} more` : shown;
|
|
16
|
+
}
|
|
17
|
+
export const githubStatusTool = {
|
|
18
|
+
name: 'github_status',
|
|
19
|
+
description: 'Check whether a GitHub token is configured and inspect the local git repository: branch, origin remote, dirty state, and commit count. Read-only; never prints the token. Use this before creating or publishing a repository.',
|
|
20
|
+
readOnly: true,
|
|
21
|
+
action: 'read',
|
|
22
|
+
parameters: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {},
|
|
25
|
+
additionalProperties: false
|
|
26
|
+
},
|
|
27
|
+
async execute(_args, context) {
|
|
28
|
+
const [token, git] = await Promise.all([githubTokenStatus(), githubGitState(context.cwd)]);
|
|
29
|
+
const tokenLine = token.configured
|
|
30
|
+
? `GitHub token: configured (${token.source === 'env' ? token.envName : 'auth.json'} · ${token.masked ?? 'saved'})`
|
|
31
|
+
: 'GitHub token: not configured. Ask the user to run /github login or `surf auth github`; never ask them to paste it in chat.';
|
|
32
|
+
const lines = [
|
|
33
|
+
tokenLine,
|
|
34
|
+
`Local repository: ${git.repo ? 'yes' : 'no'}`,
|
|
35
|
+
`Branch: ${git.branch ?? '—'}`,
|
|
36
|
+
`Origin: ${git.remote ?? '—'}`,
|
|
37
|
+
`Working tree: ${git.repo ? (git.dirty ? 'dirty' : 'clean') : '—'}`,
|
|
38
|
+
`Commits: ${git.repo ? git.commits : '—'}`
|
|
39
|
+
];
|
|
40
|
+
return {
|
|
41
|
+
output: lines.join('\n'),
|
|
42
|
+
title: 'GitHub status',
|
|
43
|
+
display: { summary: token.configured ? 'token ready' : 'token missing' }
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
export const githubCreateRepoTool = {
|
|
48
|
+
name: 'github_create_repo',
|
|
49
|
+
description: 'Create a new GitHub repository for the current project. The user must explicitly choose private or public. Uses the saved GitHub token, optionally initializes local git, and points origin at the new repository. Does not commit or push code; call github_upload next.',
|
|
50
|
+
readOnly: false,
|
|
51
|
+
action: 'shell',
|
|
52
|
+
permission(args) {
|
|
53
|
+
const name = typeof args.name === 'string' ? args.name.trim() : 'repository';
|
|
54
|
+
const visibility = args.private === true ? 'private' : args.private === false ? 'public' : 'visibility not specified';
|
|
55
|
+
const description = typeof args.description === 'string' ? args.description.trim() : '';
|
|
56
|
+
return {
|
|
57
|
+
title: 'Create GitHub repository',
|
|
58
|
+
detail: `${name} · ${visibility}${description ? `\n${description}` : ''}`,
|
|
59
|
+
risk: 'medium',
|
|
60
|
+
rule: `github:create:${name}`
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
parameters: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
name: { type: 'string', description: 'Repository name, or owner/name. Use kebab-case unless the user asks otherwise.' },
|
|
67
|
+
private: {
|
|
68
|
+
type: 'boolean',
|
|
69
|
+
description: 'Required. true for a private repository, false for a public repository.'
|
|
70
|
+
},
|
|
71
|
+
description: { type: 'string', description: 'Optional short repository description.' },
|
|
72
|
+
owner: { type: 'string', description: 'Optional organization or user. Defaults to the authenticated user.' },
|
|
73
|
+
set_remote: {
|
|
74
|
+
type: 'boolean',
|
|
75
|
+
description: 'Point origin at the new repository. Defaults to true.'
|
|
76
|
+
},
|
|
77
|
+
replace_remote: {
|
|
78
|
+
type: 'boolean',
|
|
79
|
+
description: 'Replace an existing origin remote. Defaults to false so an existing project remote is never clobbered.'
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
required: ['name', 'private']
|
|
83
|
+
},
|
|
84
|
+
async execute(args, context) {
|
|
85
|
+
const token = await requireGithubToken();
|
|
86
|
+
const name = String(args.name ?? '').trim();
|
|
87
|
+
if (!name)
|
|
88
|
+
throw new SurfError('A repository name is required.');
|
|
89
|
+
if (typeof args.private !== 'boolean') {
|
|
90
|
+
throw new SurfError('Specify whether the repository should be private.', {
|
|
91
|
+
hint: 'Pass private: true for private or private: false for public. Ask the user if they have not said.'
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const repo = await createGithubRepository({
|
|
95
|
+
token,
|
|
96
|
+
name,
|
|
97
|
+
private: args.private,
|
|
98
|
+
description: typeof args.description === 'string' ? args.description.trim() : undefined,
|
|
99
|
+
owner: typeof args.owner === 'string' ? args.owner.trim() : undefined
|
|
100
|
+
});
|
|
101
|
+
const setRemote = args.set_remote !== false;
|
|
102
|
+
const replaceRemote = args.replace_remote === true;
|
|
103
|
+
let remoteNote = 'Origin was not changed.';
|
|
104
|
+
if (setRemote) {
|
|
105
|
+
await ensureGitRepository(context.cwd);
|
|
106
|
+
const existing = await gitRemote(context.cwd);
|
|
107
|
+
if (existing && !replaceRemote) {
|
|
108
|
+
remoteNote =
|
|
109
|
+
existing === repo.cloneUrl
|
|
110
|
+
? `origin already points to ${repo.cloneUrl}.`
|
|
111
|
+
: `origin already points to ${existing}; left it unchanged. Pass replace_remote: true only if the user wants to replace it.`;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const updated = await setGithubRemote(context.cwd, repo.cloneUrl, replaceRemote);
|
|
115
|
+
remoteNote = `origin ${updated.changed ? 'set to' : 'already at'} ${updated.remote}.`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
output: [
|
|
120
|
+
`Created ${repo.private ? 'private' : 'public'} repository ${repo.fullName}.`,
|
|
121
|
+
repo.htmlUrl,
|
|
122
|
+
remoteNote,
|
|
123
|
+
'Next: use github_upload to stage, commit, and push the code.'
|
|
124
|
+
].join('\n'),
|
|
125
|
+
title: `github · ${repo.fullName}`,
|
|
126
|
+
display: { summary: `${repo.private ? 'private' : 'public'} · ${repo.fullName}` }
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
export const githubUploadTool = {
|
|
131
|
+
name: 'github_upload',
|
|
132
|
+
description: 'Commit and push code to the origin GitHub repository. Use with no files to upload the whole workspace (common build directories are excluded), or pass files/directories to upload a selected set. This is a publish action: only use it when the user explicitly asks. Never include a token in arguments or commit messages.',
|
|
133
|
+
readOnly: false,
|
|
134
|
+
action: 'shell',
|
|
135
|
+
permission(args) {
|
|
136
|
+
const files = stringArray(args.files);
|
|
137
|
+
const message = typeof args.message === 'string' ? args.message.trim() : 'Upload from SurfCode';
|
|
138
|
+
return {
|
|
139
|
+
title: 'Upload code to GitHub',
|
|
140
|
+
detail: `Commit: ${message}\nFiles: ${files ? files.join(', ') : 'all workspace changes (build dirs excluded)'}\nPush: ${args.push === false ? 'no' : 'yes'}`,
|
|
141
|
+
risk: 'high',
|
|
142
|
+
rule: `github:upload:${message}`
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
parameters: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
properties: {
|
|
148
|
+
message: { type: 'string', description: 'Commit message. Write a clear summary of the project or changes.' },
|
|
149
|
+
files: {
|
|
150
|
+
type: 'array',
|
|
151
|
+
items: { type: 'string' },
|
|
152
|
+
description: 'Optional workspace-relative files or directories. Omit to upload everything.'
|
|
153
|
+
},
|
|
154
|
+
push: { type: 'boolean', description: 'Push after committing. Defaults to true.' },
|
|
155
|
+
branch: { type: 'string', description: 'Optional branch to push. Defaults to the current branch.' }
|
|
156
|
+
},
|
|
157
|
+
required: ['message']
|
|
158
|
+
},
|
|
159
|
+
async execute(args, context) {
|
|
160
|
+
const message = String(args.message ?? '').trim();
|
|
161
|
+
if (!message)
|
|
162
|
+
throw new SurfError('A commit message is required.');
|
|
163
|
+
const result = await publishToGithub(context.cwd, {
|
|
164
|
+
message,
|
|
165
|
+
files: stringArray(args.files),
|
|
166
|
+
push: args.push !== false,
|
|
167
|
+
branch: typeof args.branch === 'string' ? args.branch : undefined
|
|
168
|
+
});
|
|
169
|
+
return publishResult(result);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
export const githubCommitTool = {
|
|
173
|
+
name: 'github_commit',
|
|
174
|
+
description: 'Commit changes and push them to the origin GitHub repository. Use after the user asks to commit or save progress. Pass files to commit only those paths, or omit files to commit every workspace change. Never commit or push unless the user explicitly asks.',
|
|
175
|
+
readOnly: false,
|
|
176
|
+
action: 'shell',
|
|
177
|
+
permission(args) {
|
|
178
|
+
const files = stringArray(args.files);
|
|
179
|
+
const message = typeof args.message === 'string' ? args.message.trim() : 'Commit from SurfCode';
|
|
180
|
+
return {
|
|
181
|
+
title: 'Commit and push to GitHub',
|
|
182
|
+
detail: `Commit: ${message}\nFiles: ${files ? files.join(', ') : 'all workspace changes'}\nPush: ${args.push === false ? 'no' : 'yes'}`,
|
|
183
|
+
risk: 'high',
|
|
184
|
+
rule: `github:commit:${message}`
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
parameters: {
|
|
188
|
+
type: 'object',
|
|
189
|
+
properties: {
|
|
190
|
+
message: { type: 'string', description: 'Commit message describing the change.' },
|
|
191
|
+
files: {
|
|
192
|
+
type: 'array',
|
|
193
|
+
items: { type: 'string' },
|
|
194
|
+
description: 'Optional workspace-relative files or directories. Omit to commit everything.'
|
|
195
|
+
},
|
|
196
|
+
push: { type: 'boolean', description: 'Push after committing. Defaults to true.' },
|
|
197
|
+
branch: { type: 'string', description: 'Optional branch to push. Defaults to the current branch.' }
|
|
198
|
+
},
|
|
199
|
+
required: ['message']
|
|
200
|
+
},
|
|
201
|
+
async execute(args, context) {
|
|
202
|
+
const message = String(args.message ?? '').trim();
|
|
203
|
+
if (!message)
|
|
204
|
+
throw new SurfError('A commit message is required.');
|
|
205
|
+
const result = await publishToGithub(context.cwd, {
|
|
206
|
+
message,
|
|
207
|
+
files: stringArray(args.files),
|
|
208
|
+
push: args.push !== false,
|
|
209
|
+
branch: typeof args.branch === 'string' ? args.branch : undefined
|
|
210
|
+
});
|
|
211
|
+
return publishResult(result);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
function publishResult(result) {
|
|
215
|
+
const status = result.nothingToCommit
|
|
216
|
+
? 'Nothing new to commit; the working tree is clean.'
|
|
217
|
+
: `Committed ${result.files.length} file${result.files.length === 1 ? '' : 's'}${result.commit ? ` as ${result.commit}` : ''}.`;
|
|
218
|
+
const push = result.pushed
|
|
219
|
+
? `Pushed ${result.branch} to origin.`
|
|
220
|
+
: 'Commit created but not pushed.';
|
|
221
|
+
return {
|
|
222
|
+
output: [
|
|
223
|
+
status,
|
|
224
|
+
push,
|
|
225
|
+
result.remote ? `Repository: ${result.remote}` : '',
|
|
226
|
+
result.files.length > 0 ? `Files: ${summary(result.files)}` : ''
|
|
227
|
+
]
|
|
228
|
+
.filter(Boolean)
|
|
229
|
+
.join('\n'),
|
|
230
|
+
title: result.pushed ? `github · pushed ${result.branch}` : `github · committed ${result.branch}`,
|
|
231
|
+
display: {
|
|
232
|
+
summary: result.nothingToCommit
|
|
233
|
+
? 'nothing to commit'
|
|
234
|
+
: `${result.files.length} file${result.files.length === 1 ? '' : 's'}${result.pushed ? ' · pushed' : ''}`
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/tools/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { editTool, listTool, readTool, writeTool } from './files.js';
|
|
2
|
+
import { githubCommitTool, githubCreateRepoTool, githubStatusTool, githubUploadTool } from './github.js';
|
|
3
|
+
import { globTool, grepTool } from './search.js';
|
|
4
|
+
import { shellTool } from './shell.js';
|
|
5
|
+
import { todoTool } from './todos.js';
|
|
6
|
+
import { webfetchTool } from './webfetch.js';
|
|
7
|
+
export function createTools() {
|
|
8
|
+
return [
|
|
9
|
+
readTool,
|
|
10
|
+
writeTool,
|
|
11
|
+
editTool,
|
|
12
|
+
listTool,
|
|
13
|
+
globTool,
|
|
14
|
+
grepTool,
|
|
15
|
+
shellTool,
|
|
16
|
+
webfetchTool,
|
|
17
|
+
todoTool,
|
|
18
|
+
githubStatusTool,
|
|
19
|
+
githubCreateRepoTool,
|
|
20
|
+
githubUploadTool,
|
|
21
|
+
githubCommitTool
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
export function toolSchemas(tools) {
|
|
25
|
+
return tools.map((tool) => ({
|
|
26
|
+
name: tool.name,
|
|
27
|
+
description: tool.description,
|
|
28
|
+
parameters: tool.parameters
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
export function findTool(tools, name) {
|
|
32
|
+
return tools.find((tool) => tool.name === name);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,QAAQ;QACR,SAAS;QACT,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,SAAS;QACT,YAAY;QACZ,QAAQ;QACR,gBAAgB;QAChB,oBAAoB;QACpB,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAuB,EAAE,IAAY;IAC5D,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { glob } from 'tinyglobby';
|
|
5
|
+
import { SurfError } from '../core/errors.js';
|
|
6
|
+
import { displayPath, filterIgnored, isProbablyBinary, loadIgnore, normalizeOutput, resolveWorkspacePath } from '../core/workspace.js';
|
|
7
|
+
const BASE_IGNORES = [
|
|
8
|
+
'**/node_modules/**',
|
|
9
|
+
'**/.git/**',
|
|
10
|
+
'**/dist/**',
|
|
11
|
+
'**/build/**',
|
|
12
|
+
'**/coverage/**',
|
|
13
|
+
'**/.next/**',
|
|
14
|
+
'**/.turbo/**'
|
|
15
|
+
];
|
|
16
|
+
export const globTool = {
|
|
17
|
+
name: 'glob',
|
|
18
|
+
description: 'Find files by glob pattern, recursively. Examples: "**/*.ts", "src/**/*.{ts,tsx}", "**/package.json". Results are sorted and gitignore-aware.',
|
|
19
|
+
readOnly: true,
|
|
20
|
+
action: 'read',
|
|
21
|
+
parameters: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
pattern: { type: 'string', description: 'Glob pattern, e.g. "**/*.ts".' },
|
|
25
|
+
path: { type: 'string', description: 'Directory to search from. Defaults to the workspace root.' },
|
|
26
|
+
limit: { type: 'number', description: 'Maximum files to return (default 200, max 1000).' }
|
|
27
|
+
},
|
|
28
|
+
required: ['pattern']
|
|
29
|
+
},
|
|
30
|
+
async execute(args, context) {
|
|
31
|
+
const pattern = String(args.pattern ?? '**/*');
|
|
32
|
+
if (pattern.startsWith('/'))
|
|
33
|
+
throw new SurfError('Glob patterns must be relative to the workspace.');
|
|
34
|
+
const rawPath = String(args.path ?? '.');
|
|
35
|
+
const { absolute, relative: searchRel } = resolveWorkspacePath(rawPath, context.cwd, context.allowOutsideWorkspace);
|
|
36
|
+
const info = await stat(absolute).catch(() => undefined);
|
|
37
|
+
if (!info?.isDirectory())
|
|
38
|
+
throw new SurfError(`Not a directory: ${rawPath}`);
|
|
39
|
+
const limit = Math.max(1, Math.min(Number(args.limit) || 200, 1000));
|
|
40
|
+
const matcher = await loadIgnore(context.cwd);
|
|
41
|
+
const matches = await glob(pattern, {
|
|
42
|
+
cwd: absolute,
|
|
43
|
+
dot: false,
|
|
44
|
+
onlyFiles: true,
|
|
45
|
+
followSymbolicLinks: false,
|
|
46
|
+
ignore: BASE_IGNORES
|
|
47
|
+
});
|
|
48
|
+
const mapped = matches
|
|
49
|
+
.map((entry) => (searchRel === '.' ? entry : `${searchRel}/${entry}`).split('\\').join('/'))
|
|
50
|
+
.filter((entry) => !matcher.ignores(entry))
|
|
51
|
+
.sort();
|
|
52
|
+
const selected = mapped.slice(0, limit);
|
|
53
|
+
return {
|
|
54
|
+
output: mapped.length === 0
|
|
55
|
+
? `No files matched ${pattern}.`
|
|
56
|
+
: `${mapped.length} match${mapped.length === 1 ? '' : 'es'}${mapped.length > selected.length ? ` (showing first ${selected.length})` : ''}:\n${selected.join('\n')}`,
|
|
57
|
+
title: pattern,
|
|
58
|
+
display: {
|
|
59
|
+
kind: 'files',
|
|
60
|
+
summary: `${mapped.length} ${mapped.length === 1 ? 'file' : 'files'}`,
|
|
61
|
+
lines: mapped.length,
|
|
62
|
+
truncated: mapped.length > selected.length
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
export const grepTool = {
|
|
68
|
+
name: 'grep',
|
|
69
|
+
description: 'Search file contents using a regular expression. Returns file, line, column and matching line. Prefer this over reading many files. Uses ripgrep when available.',
|
|
70
|
+
readOnly: true,
|
|
71
|
+
action: 'read',
|
|
72
|
+
parameters: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
pattern: { type: 'string', description: 'Regular expression (or literal string when fixedStrings is true).' },
|
|
76
|
+
path: { type: 'string', description: 'File or directory to search. Defaults to the workspace root.' },
|
|
77
|
+
include: { type: 'string', description: 'Only search files matching this glob, e.g. "*.ts".' },
|
|
78
|
+
caseSensitive: { type: 'boolean', description: 'Case-sensitive search. Default false.' },
|
|
79
|
+
fixedStrings: { type: 'boolean', description: 'Treat pattern as a literal string. Default false.' },
|
|
80
|
+
limit: { type: 'number', description: 'Maximum matches (default 200, max 1000).' }
|
|
81
|
+
},
|
|
82
|
+
required: ['pattern']
|
|
83
|
+
},
|
|
84
|
+
async execute(args, context) {
|
|
85
|
+
const pattern = String(args.pattern ?? '');
|
|
86
|
+
if (!pattern)
|
|
87
|
+
throw new SurfError('A search pattern is required.');
|
|
88
|
+
const rawPath = String(args.path ?? '.');
|
|
89
|
+
const { absolute, relative: rel } = resolveWorkspacePath(rawPath, context.cwd, context.allowOutsideWorkspace);
|
|
90
|
+
const info = await stat(absolute).catch(() => undefined);
|
|
91
|
+
if (!info)
|
|
92
|
+
throw new SurfError(`Path not found: ${rawPath}`);
|
|
93
|
+
const limit = Math.max(1, Math.min(Number(args.limit) || 200, 1000));
|
|
94
|
+
const include = args.include ? String(args.include) : undefined;
|
|
95
|
+
const caseSensitive = Boolean(args.caseSensitive);
|
|
96
|
+
const fixedStrings = Boolean(args.fixedStrings);
|
|
97
|
+
try {
|
|
98
|
+
new RegExp(pattern, caseSensitive ? 'g' : 'gi');
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (!fixedStrings) {
|
|
102
|
+
throw new SurfError(`Invalid regular expression: ${error.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const rg = await runRipgrep({
|
|
106
|
+
pattern,
|
|
107
|
+
cwd: context.cwd,
|
|
108
|
+
target: info.isDirectory() ? absolute : absolute,
|
|
109
|
+
include,
|
|
110
|
+
caseSensitive,
|
|
111
|
+
fixedStrings,
|
|
112
|
+
limit,
|
|
113
|
+
signal: context.signal
|
|
114
|
+
});
|
|
115
|
+
if (rg !== undefined) {
|
|
116
|
+
const lines = normalizeOutput(rg.stdout).split('\n').filter(Boolean);
|
|
117
|
+
const trimmed = lines.slice(0, limit);
|
|
118
|
+
return formatMatches(trimmed, lines.length, pattern, context.cwd, rel);
|
|
119
|
+
}
|
|
120
|
+
const files = info.isDirectory()
|
|
121
|
+
? await glob(include ?? '**/*', {
|
|
122
|
+
cwd: absolute,
|
|
123
|
+
dot: false,
|
|
124
|
+
onlyFiles: true,
|
|
125
|
+
followSymbolicLinks: false,
|
|
126
|
+
ignore: BASE_IGNORES
|
|
127
|
+
})
|
|
128
|
+
: ['.'];
|
|
129
|
+
const matcher = await loadIgnore(context.cwd);
|
|
130
|
+
const matches = [];
|
|
131
|
+
const regex = new RegExp(pattern, caseSensitive ? 'g' : 'gi');
|
|
132
|
+
for (const file of files) {
|
|
133
|
+
if (context.signal.aborted)
|
|
134
|
+
break;
|
|
135
|
+
const fileAbs = info.isDirectory() ? resolve(absolute, file) : absolute;
|
|
136
|
+
const fileRel = displayPath(context.cwd, fileAbs);
|
|
137
|
+
if (info.isDirectory() && matcher.ignores(file.split('\\').join('/')))
|
|
138
|
+
continue;
|
|
139
|
+
const fileStat = await stat(fileAbs).catch(() => undefined);
|
|
140
|
+
if (!fileStat?.isFile() || fileStat.size > 1_500_000)
|
|
141
|
+
continue;
|
|
142
|
+
const buffer = await readFile(fileAbs).catch(() => undefined);
|
|
143
|
+
if (!buffer || isProbablyBinary(buffer))
|
|
144
|
+
continue;
|
|
145
|
+
const content = normalizeOutput(buffer.toString('utf8'));
|
|
146
|
+
const lines = content.split('\n');
|
|
147
|
+
for (let index = 0; index < lines.length && matches.length < limit; index += 1) {
|
|
148
|
+
const line = lines[index];
|
|
149
|
+
regex.lastIndex = 0;
|
|
150
|
+
const match = regex.exec(line);
|
|
151
|
+
if (match) {
|
|
152
|
+
matches.push(`${fileRel}:${index + 1}:${(match.index ?? 0) + 1}: ${line.trim().slice(0, 500)}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (matches.length >= limit)
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
return formatMatches(matches, matches.length, pattern, context.cwd, rel);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
function formatMatches(lines, total, pattern, cwd, searchPath) {
|
|
162
|
+
const cleaned = lines.map((line) => {
|
|
163
|
+
if (cwd === '/')
|
|
164
|
+
return line;
|
|
165
|
+
return line;
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
output: cleaned.length === 0
|
|
169
|
+
? `No matches for /${pattern}/ in ${searchPath}.`
|
|
170
|
+
: `${total} match${total === 1 ? '' : 'es'} for /${pattern}/:\n${cleaned.slice(0, 200).join('\n')}${total > 200 ? `\n… ${total - 200} more` : ''}`,
|
|
171
|
+
title: pattern,
|
|
172
|
+
display: {
|
|
173
|
+
kind: 'search',
|
|
174
|
+
summary: `${total} ${total === 1 ? 'match' : 'matches'}`,
|
|
175
|
+
lines: total
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async function runRipgrep(options) {
|
|
180
|
+
const args = ['--line-number', '--column', '--no-heading', '--color', 'never', '--max-columns', '500', '--max-columns-preview'];
|
|
181
|
+
if (!options.caseSensitive)
|
|
182
|
+
args.push('--ignore-case');
|
|
183
|
+
if (options.fixedStrings)
|
|
184
|
+
args.push('--fixed-strings');
|
|
185
|
+
for (const ignored of BASE_IGNORES)
|
|
186
|
+
args.push('--glob', `!${ignored.replace('**/', '')}`);
|
|
187
|
+
if (options.include)
|
|
188
|
+
args.push('--glob', options.include);
|
|
189
|
+
args.push('--', options.pattern, options.target);
|
|
190
|
+
return await new Promise((resolvePromise) => {
|
|
191
|
+
const child = spawn('rg', args, { cwd: options.cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
192
|
+
let stdout = '';
|
|
193
|
+
let stderr = '';
|
|
194
|
+
let missing = false;
|
|
195
|
+
let settled = false;
|
|
196
|
+
const finish = (value) => {
|
|
197
|
+
if (settled)
|
|
198
|
+
return;
|
|
199
|
+
settled = true;
|
|
200
|
+
options.signal.removeEventListener('abort', abort);
|
|
201
|
+
resolvePromise(value);
|
|
202
|
+
};
|
|
203
|
+
const abort = () => {
|
|
204
|
+
child.kill('SIGTERM');
|
|
205
|
+
finish(undefined);
|
|
206
|
+
};
|
|
207
|
+
options.signal.addEventListener('abort', abort, { once: true });
|
|
208
|
+
child.on('error', (error) => {
|
|
209
|
+
if (error.code === 'ENOENT')
|
|
210
|
+
missing = true;
|
|
211
|
+
finish(undefined);
|
|
212
|
+
});
|
|
213
|
+
child.stdout.on('data', (chunk) => {
|
|
214
|
+
stdout += chunk.toString('utf8');
|
|
215
|
+
if (stdout.length > 500_000)
|
|
216
|
+
child.kill('SIGTERM');
|
|
217
|
+
});
|
|
218
|
+
child.stderr.on('data', (chunk) => {
|
|
219
|
+
stderr += chunk.toString('utf8');
|
|
220
|
+
});
|
|
221
|
+
child.on('close', (code) => {
|
|
222
|
+
if (missing)
|
|
223
|
+
return finish(undefined);
|
|
224
|
+
finish({ stdout, stderr, code: code ?? 0 });
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
export function filterByIgnore(cwd, paths) {
|
|
229
|
+
return loadIgnore(cwd).then((matcher) => filterIgnored(matcher, cwd, paths));
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"}
|