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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +325 -2
  3. package/assets/surfcode-logo.gif +0 -0
  4. package/dist/cli/auth.js +315 -0
  5. package/dist/cli/auth.js.map +1 -0
  6. package/dist/cli/config.js +228 -0
  7. package/dist/cli/config.js.map +1 -0
  8. package/dist/cli/headless.js +355 -0
  9. package/dist/cli/headless.js.map +1 -0
  10. package/dist/cli/inspect.js +462 -0
  11. package/dist/cli/inspect.js.map +1 -0
  12. package/dist/cli/interactive.js +130 -0
  13. package/dist/cli/interactive.js.map +1 -0
  14. package/dist/cli/sessions.js +170 -0
  15. package/dist/cli/sessions.js.map +1 -0
  16. package/dist/cli/sync.js +190 -0
  17. package/dist/cli/sync.js.map +1 -0
  18. package/dist/cli/util.js +345 -0
  19. package/dist/cli/util.js.map +1 -0
  20. package/dist/cli.js +485 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/core/agent.js +298 -0
  23. package/dist/core/agent.js.map +1 -0
  24. package/dist/core/agents.js +55 -0
  25. package/dist/core/agents.js.map +1 -0
  26. package/dist/core/auth.js +107 -0
  27. package/dist/core/auth.js.map +1 -0
  28. package/dist/core/catalog.js +306 -0
  29. package/dist/core/catalog.js.map +1 -0
  30. package/dist/core/chat/anthropic.js +222 -0
  31. package/dist/core/chat/anthropic.js.map +1 -0
  32. package/dist/core/chat/common.js +367 -0
  33. package/dist/core/chat/common.js.map +1 -0
  34. package/dist/core/chat/google.js +180 -0
  35. package/dist/core/chat/google.js.map +1 -0
  36. package/dist/core/chat/index.js +80 -0
  37. package/dist/core/chat/index.js.map +1 -0
  38. package/dist/core/chat/openai.js +164 -0
  39. package/dist/core/chat/openai.js.map +1 -0
  40. package/dist/core/chat/types.js +2 -0
  41. package/dist/core/chat/types.js.map +1 -0
  42. package/dist/core/clipboard.js +34 -0
  43. package/dist/core/clipboard.js.map +1 -0
  44. package/dist/core/compact.js +39 -0
  45. package/dist/core/compact.js.map +1 -0
  46. package/dist/core/config.js +211 -0
  47. package/dist/core/config.js.map +1 -0
  48. package/dist/core/delegate.js +184 -0
  49. package/dist/core/delegate.js.map +1 -0
  50. package/dist/core/effort.js +80 -0
  51. package/dist/core/effort.js.map +1 -0
  52. package/dist/core/errors.js +32 -0
  53. package/dist/core/errors.js.map +1 -0
  54. package/dist/core/free.js +21 -0
  55. package/dist/core/free.js.map +1 -0
  56. package/dist/core/github.js +445 -0
  57. package/dist/core/github.js.map +1 -0
  58. package/dist/core/paths.js +51 -0
  59. package/dist/core/paths.js.map +1 -0
  60. package/dist/core/prompt.js +95 -0
  61. package/dist/core/prompt.js.map +1 -0
  62. package/dist/core/provider.js +298 -0
  63. package/dist/core/provider.js.map +1 -0
  64. package/dist/core/session.js +159 -0
  65. package/dist/core/session.js.map +1 -0
  66. package/dist/core/sync.js +126 -0
  67. package/dist/core/sync.js.map +1 -0
  68. package/dist/core/types.js +2 -0
  69. package/dist/core/types.js.map +1 -0
  70. package/dist/core/usage.js +127 -0
  71. package/dist/core/usage.js.map +1 -0
  72. package/dist/core/workspace.js +70 -0
  73. package/dist/core/workspace.js.map +1 -0
  74. package/dist/data/models.json +1 -0
  75. package/dist/sync/server.js +179 -0
  76. package/dist/sync/server.js.map +1 -0
  77. package/dist/tools/diff.js +21 -0
  78. package/dist/tools/diff.js.map +1 -0
  79. package/dist/tools/files.js +227 -0
  80. package/dist/tools/files.js.map +1 -0
  81. package/dist/tools/github.js +238 -0
  82. package/dist/tools/github.js.map +1 -0
  83. package/dist/tools/index.js +34 -0
  84. package/dist/tools/index.js.map +1 -0
  85. package/dist/tools/search.js +231 -0
  86. package/dist/tools/search.js.map +1 -0
  87. package/dist/tools/shell.js +118 -0
  88. package/dist/tools/shell.js.map +1 -0
  89. package/dist/tools/todos.js +50 -0
  90. package/dist/tools/todos.js.map +1 -0
  91. package/dist/tools/webfetch.js +108 -0
  92. package/dist/tools/webfetch.js.map +1 -0
  93. package/dist/tui/App.js +2984 -0
  94. package/dist/tui/App.js.map +1 -0
  95. package/dist/tui/ansi.js +151 -0
  96. package/dist/tui/ansi.js.map +1 -0
  97. package/dist/tui/commands.js +61 -0
  98. package/dist/tui/commands.js.map +1 -0
  99. package/dist/tui/explorer.js +152 -0
  100. package/dist/tui/explorer.js.map +1 -0
  101. package/dist/tui/icons.js +21 -0
  102. package/dist/tui/icons.js.map +1 -0
  103. package/dist/tui/layout.js +324 -0
  104. package/dist/tui/layout.js.map +1 -0
  105. package/dist/tui/markdown.js +355 -0
  106. package/dist/tui/markdown.js.map +1 -0
  107. package/dist/tui/overlays.js +316 -0
  108. package/dist/tui/overlays.js.map +1 -0
  109. package/dist/tui/render.js +234 -0
  110. package/dist/tui/render.js.map +1 -0
  111. package/dist/tui/theme.js +148 -0
  112. package/dist/tui/theme.js.map +1 -0
  113. package/dist/tui/types.js +73 -0
  114. package/dist/tui/types.js.map +1 -0
  115. package/dist/version.js +3 -0
  116. package/dist/version.js.map +1 -0
  117. package/package.json +75 -4
@@ -0,0 +1,179 @@
1
+ import { createServer } from 'node:http';
2
+ import { mkdir, readFile } from 'node:fs/promises';
3
+ import { timingSafeEqual } from 'node:crypto';
4
+ import { join } from 'node:path';
5
+ import { z } from 'zod';
6
+ import { SurfError } from '../core/errors.js';
7
+ import { getPaths, writeFileAtomic } from '../core/paths.js';
8
+ import { sessionRecordSchema } from '../core/session.js';
9
+ const MAX_BODY_BYTES = 8 * 1024 * 1024;
10
+ const storedSessionSchema = z.object({
11
+ cursor: z.number().int().min(0),
12
+ session: sessionRecordSchema
13
+ });
14
+ const stateSchema = z.object({
15
+ version: z.literal(1),
16
+ cursor: z.number().int().min(0),
17
+ sessions: z.record(z.string(), storedSessionSchema)
18
+ });
19
+ const requestSchema = z.object({
20
+ since: z.number().int().min(0).default(0),
21
+ pull: z.boolean().default(true),
22
+ sessions: z.array(sessionRecordSchema).default([])
23
+ });
24
+ export async function startSyncServer(options) {
25
+ const token = options.token.trim();
26
+ if (!token)
27
+ throw new SurfError('The sync server requires a token.');
28
+ const host = options.host?.trim() || '127.0.0.1';
29
+ const port = options.port ?? 8787;
30
+ const dataDir = options.dataDir?.trim() || join(getPaths().dataDir, 'sync-server');
31
+ const stateFile = join(dataDir, 'sessions.json');
32
+ await mkdir(dataDir, { recursive: true, mode: 0o700 });
33
+ let state = await loadState(stateFile);
34
+ let queue = Promise.resolve();
35
+ const server = createServer(async (request, response) => {
36
+ try {
37
+ const url = new URL(request.url ?? '/', 'http://sync.local');
38
+ if (request.method === 'GET' && url.pathname === '/v1/health') {
39
+ json(response, 200, { ok: true, sessions: Object.keys(state.sessions).length });
40
+ return;
41
+ }
42
+ if (url.pathname !== '/v1/sync') {
43
+ json(response, 404, { error: 'not_found' });
44
+ return;
45
+ }
46
+ if (request.method !== 'POST') {
47
+ json(response, 405, { error: 'method_not_allowed' });
48
+ return;
49
+ }
50
+ if (!authorized(request, token)) {
51
+ json(response, 401, { error: 'unauthorized' });
52
+ return;
53
+ }
54
+ const raw = await readBody(request);
55
+ let body;
56
+ try {
57
+ body = requestSchema.parse(JSON.parse(raw));
58
+ }
59
+ catch {
60
+ json(response, 400, { error: 'invalid_request' });
61
+ return;
62
+ }
63
+ const result = await mutate(async () => {
64
+ let accepted = 0;
65
+ for (const session of body.sessions) {
66
+ const current = state.sessions[session.id];
67
+ if (current && current.session.updatedAt >= session.updatedAt)
68
+ continue;
69
+ state.cursor += 1;
70
+ state.sessions[session.id] = { cursor: state.cursor, session };
71
+ accepted += 1;
72
+ }
73
+ if (accepted > 0)
74
+ await saveState(stateFile, state);
75
+ const changed = body.pull
76
+ ? Object.values(state.sessions)
77
+ .filter((entry) => entry.cursor > body.since)
78
+ .sort((a, b) => a.cursor - b.cursor)
79
+ .map((entry) => entry.session)
80
+ : [];
81
+ return {
82
+ accepted,
83
+ cursor: state.cursor,
84
+ sessions: changed
85
+ };
86
+ });
87
+ json(response, 200, result);
88
+ }
89
+ catch (error) {
90
+ if (!response.headersSent) {
91
+ json(response, 500, {
92
+ error: 'internal_error',
93
+ message: error instanceof Error ? error.message : String(error)
94
+ });
95
+ }
96
+ else {
97
+ response.destroy();
98
+ }
99
+ }
100
+ });
101
+ await new Promise((resolve, reject) => {
102
+ server.once('error', reject);
103
+ server.listen(port, host, () => {
104
+ server.off('error', reject);
105
+ resolve();
106
+ });
107
+ });
108
+ const address = server.address();
109
+ const actualPort = typeof address === 'object' && address ? address.port : port;
110
+ const displayHost = host === '0.0.0.0' || host === '::' ? '127.0.0.1' : host;
111
+ return {
112
+ url: `http://${displayHost}:${actualPort}`,
113
+ host,
114
+ port: actualPort,
115
+ sessions: Object.keys(state.sessions).length,
116
+ close: () => closeServer(server)
117
+ };
118
+ function mutate(run) {
119
+ const next = queue.then(run, run);
120
+ queue = next.then(() => undefined, () => undefined);
121
+ return next;
122
+ }
123
+ }
124
+ function authorized(request, token) {
125
+ const header = request.headers.authorization ?? '';
126
+ const match = /^Bearer\s+(.+)$/i.exec(header);
127
+ if (!match)
128
+ return false;
129
+ const supplied = Buffer.from(match[1].trim());
130
+ const expected = Buffer.from(token);
131
+ return supplied.length === expected.length && timingSafeEqual(supplied, expected);
132
+ }
133
+ async function readBody(request) {
134
+ const chunks = [];
135
+ let total = 0;
136
+ for await (const chunk of request) {
137
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
138
+ total += buffer.length;
139
+ if (total > MAX_BODY_BYTES) {
140
+ throw new SurfError('Sync request body is too large.');
141
+ }
142
+ chunks.push(buffer);
143
+ }
144
+ return Buffer.concat(chunks).toString('utf8');
145
+ }
146
+ async function loadState(path) {
147
+ try {
148
+ const parsed = stateSchema.safeParse(JSON.parse(await readFile(path, 'utf8')));
149
+ if (!parsed.success)
150
+ throw new Error('invalid state');
151
+ return parsed.data;
152
+ }
153
+ catch (error) {
154
+ if (error.code === 'ENOENT') {
155
+ return { version: 1, cursor: 0, sessions: {} };
156
+ }
157
+ throw new SurfError(`Could not read sync state at ${path}.`, {
158
+ hint: 'Move the file aside to start a fresh sync store.'
159
+ });
160
+ }
161
+ }
162
+ async function saveState(path, state) {
163
+ await writeFileAtomic(path, `${JSON.stringify(state, null, 2)}\n`);
164
+ }
165
+ function json(response, status, value) {
166
+ const body = `${JSON.stringify(value)}\n`;
167
+ response.writeHead(status, {
168
+ 'content-type': 'application/json; charset=utf-8',
169
+ 'content-length': Buffer.byteLength(body),
170
+ 'cache-control': 'no-store'
171
+ });
172
+ response.end(body);
173
+ }
174
+ function closeServer(server) {
175
+ return new Promise((resolve, reject) => {
176
+ server.close((error) => (error ? reject(error) : resolve()));
177
+ });
178
+ }
179
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/sync/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { structuredPatch } from 'diff';
2
+ export function buildDiff(oldText, newText, path, context = 3) {
3
+ if (oldText === newText)
4
+ return { patch: '', additions: 0, deletions: 0 };
5
+ const patch = structuredPatch(path, path, oldText, newText, '', '', { context });
6
+ let additions = 0;
7
+ let deletions = 0;
8
+ const lines = [];
9
+ for (const hunk of patch.hunks) {
10
+ lines.push(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`);
11
+ for (const line of hunk.lines) {
12
+ if (line.startsWith('+'))
13
+ additions += 1;
14
+ else if (line.startsWith('-'))
15
+ deletions += 1;
16
+ lines.push(line);
17
+ }
18
+ }
19
+ return { patch: lines.join('\n'), additions, deletions };
20
+ }
21
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAQvC,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,OAAe,EAAE,IAAY,EAAE,OAAO,GAAG,CAAC;IACnF,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC1E,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACjF,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC;QAC1F,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS,IAAI,CAAC,CAAC;iBACpC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS,IAAI,CAAC,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,227 @@
1
+ import { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
2
+ import { dirname, relative } from 'node:path';
3
+ import { SurfError } from '../core/errors.js';
4
+ import { displayPath, isProbablyBinary, loadIgnore, normalizeOutput, resolveWorkspacePath } from '../core/workspace.js';
5
+ import { buildDiff } from './diff.js';
6
+ export const readTool = {
7
+ name: 'read',
8
+ description: 'Read a text file from the workspace. Returns numbered lines. Use offset and limit for large files. Always read a file before editing it.',
9
+ readOnly: true,
10
+ action: 'read',
11
+ parameters: {
12
+ type: 'object',
13
+ properties: {
14
+ path: { type: 'string', description: 'File path relative to the workspace (or absolute).' },
15
+ offset: { type: 'number', description: '1-based line to start at. Defaults to 1.' },
16
+ limit: { type: 'number', description: 'Maximum number of lines to return. Defaults to 2000.' }
17
+ },
18
+ required: ['path']
19
+ },
20
+ async execute(args, context) {
21
+ const path = String(args.path ?? '');
22
+ const { absolute } = resolveWorkspacePath(path, context.cwd, context.allowOutsideWorkspace);
23
+ const info = await stat(absolute).catch(() => undefined);
24
+ if (!info)
25
+ throw new SurfError(`File not found: ${path}`);
26
+ if (info.isDirectory())
27
+ throw new SurfError(`${path} is a directory`, { hint: 'Use the ls tool instead.' });
28
+ if (info.size > 2_000_000) {
29
+ throw new SurfError(`File is too large to read (${Math.round(info.size / 1024)} KB)`, {
30
+ hint: 'Read a smaller file or use grep to locate the relevant section.'
31
+ });
32
+ }
33
+ const buffer = await readFile(absolute);
34
+ if (isProbablyBinary(buffer))
35
+ throw new SurfError(`${path} appears to be a binary file.`);
36
+ const content = normalizeOutput(buffer.toString('utf8'));
37
+ const allLines = content.split('\n');
38
+ if (allLines.at(-1) === '')
39
+ allLines.pop();
40
+ const offset = Math.max(1, Math.min(Number(args.offset) || 1, Math.max(allLines.length, 1)));
41
+ const limit = Math.max(1, Math.min(Number(args.limit) || 2000, 5000));
42
+ const selected = allLines.slice(offset - 1, offset - 1 + limit);
43
+ const width = String(offset + selected.length - 1).length;
44
+ const numbered = selected
45
+ .map((line, index) => `${String(offset + index).padStart(width)}│ ${line.length > 4000 ? `${line.slice(0, 4000)}…` : line}`)
46
+ .join('\n');
47
+ const header = allLines.length > selected.length
48
+ ? `${path} (lines ${offset}-${offset + selected.length - 1} of ${allLines.length})`
49
+ : `${path} (${allLines.length} lines)`;
50
+ return {
51
+ output: `${header}\n${numbered}`,
52
+ title: path,
53
+ display: {
54
+ kind: 'text',
55
+ summary: `${selected.length}${selected.length !== allLines.length ? ` of ${allLines.length}` : ''} lines`,
56
+ lines: selected.length
57
+ }
58
+ };
59
+ }
60
+ };
61
+ export const writeTool = {
62
+ name: 'write',
63
+ description: 'Write a complete text file, creating parent directories as needed. Overwrites existing files. For changing part of a file, prefer edit.',
64
+ readOnly: false,
65
+ action: 'write',
66
+ parameters: {
67
+ type: 'object',
68
+ properties: {
69
+ path: { type: 'string', description: 'File path relative to the workspace.' },
70
+ content: { type: 'string', description: 'The complete new file content.' }
71
+ },
72
+ required: ['path', 'content']
73
+ },
74
+ async execute(args, context) {
75
+ const path = String(args.path ?? '');
76
+ const content = String(args.content ?? '');
77
+ const { absolute, relative: rel } = resolveWorkspacePath(path, context.cwd, context.allowOutsideWorkspace);
78
+ const existing = await readFile(absolute, 'utf8').catch((error) => {
79
+ if (error.code === 'ENOENT')
80
+ return '';
81
+ throw error;
82
+ });
83
+ if (existing === content) {
84
+ return {
85
+ output: `No changes: ${path} already has this content.`,
86
+ title: path,
87
+ display: { summary: 'unchanged' }
88
+ };
89
+ }
90
+ await mkdir(dirname(absolute), { recursive: true });
91
+ await writeFile(absolute, content, 'utf8');
92
+ const diff = buildDiff(existing, content, relative(context.cwd, absolute));
93
+ const summary = `+${diff.additions} −${diff.deletions}`;
94
+ return {
95
+ output: `Wrote ${content.length} bytes to ${path} (${summary}).`,
96
+ title: path,
97
+ display: {
98
+ kind: 'diff',
99
+ summary,
100
+ diff: diff.patch,
101
+ additions: diff.additions,
102
+ deletions: diff.deletions,
103
+ lines: content.split('\n').length
104
+ }
105
+ };
106
+ }
107
+ };
108
+ export const editTool = {
109
+ name: 'edit',
110
+ description: 'Replace an exact string in a file. oldString must match exactly, including whitespace. Read the file first. Use replaceAll to change every occurrence; otherwise oldString must be unique.',
111
+ readOnly: false,
112
+ action: 'write',
113
+ parameters: {
114
+ type: 'object',
115
+ properties: {
116
+ path: { type: 'string', description: 'File path relative to the workspace.' },
117
+ oldString: { type: 'string', description: 'Exact text to replace.' },
118
+ newString: { type: 'string', description: 'Replacement text.' },
119
+ replaceAll: { type: 'boolean', description: 'Replace every occurrence (default false).' }
120
+ },
121
+ required: ['path', 'oldString', 'newString']
122
+ },
123
+ async execute(args, context) {
124
+ const path = String(args.path ?? '');
125
+ const oldString = String(args.oldString ?? '');
126
+ const newString = String(args.newString ?? '');
127
+ const replaceAll = Boolean(args.replaceAll);
128
+ if (!oldString)
129
+ throw new SurfError('oldString must not be empty.');
130
+ const { absolute } = resolveWorkspacePath(path, context.cwd, context.allowOutsideWorkspace);
131
+ const existing = await readFile(absolute, 'utf8').catch(() => {
132
+ throw new SurfError(`File not found: ${path}`);
133
+ });
134
+ const occurrences = countOccurrences(existing, oldString);
135
+ if (occurrences === 0) {
136
+ throw new SurfError(`oldString was not found in ${path}`, {
137
+ hint: 'Re-read the file and copy the exact text, including indentation. The file may also have changed.'
138
+ });
139
+ }
140
+ if (!replaceAll && occurrences > 1) {
141
+ throw new SurfError(`oldString occurs ${occurrences} times in ${path}`, {
142
+ hint: 'Add more surrounding context to make it unique, or pass replaceAll: true.'
143
+ });
144
+ }
145
+ const updated = replaceAll ? existing.split(oldString).join(newString) : existing.replace(oldString, newString);
146
+ if (updated === existing) {
147
+ return { output: `No changes made to ${path}.`, title: path, display: { summary: 'unchanged' } };
148
+ }
149
+ await writeFile(absolute, updated, 'utf8');
150
+ const diff = buildDiff(existing, updated, path);
151
+ const summary = `+${diff.additions} −${diff.deletions}`;
152
+ return {
153
+ output: `Edited ${path} (${occurrences} replacement${occurrences === 1 ? '' : 's'}, ${summary}).`,
154
+ title: path,
155
+ display: {
156
+ kind: 'diff',
157
+ summary,
158
+ diff: diff.patch,
159
+ additions: diff.additions,
160
+ deletions: diff.deletions
161
+ }
162
+ };
163
+ }
164
+ };
165
+ export const listTool = {
166
+ name: 'ls',
167
+ description: 'List files and directories in a workspace directory. Use glob to find files recursively.',
168
+ readOnly: true,
169
+ action: 'read',
170
+ parameters: {
171
+ type: 'object',
172
+ properties: {
173
+ path: { type: 'string', description: 'Directory path. Defaults to the workspace root.' }
174
+ }
175
+ },
176
+ async execute(args, context) {
177
+ const rawPath = String(args.path ?? '.');
178
+ const { absolute } = resolveWorkspacePath(rawPath, context.cwd, context.allowOutsideWorkspace);
179
+ const entries = await readdir(absolute, { withFileTypes: true }).catch(() => {
180
+ throw new SurfError(`Directory not found: ${rawPath}`);
181
+ });
182
+ const matcher = await loadIgnore(context.cwd);
183
+ const visible = entries
184
+ .filter((entry) => {
185
+ const rel = relative(context.cwd, `${absolute}/${entry.name}`).split('\\').join('/');
186
+ return !matcher.ignores(rel) || entry.name === '.surfcodeignore';
187
+ })
188
+ .sort((a, b) => Number(b.isDirectory()) - Number(a.isDirectory()) || a.name.localeCompare(b.name))
189
+ .slice(0, 300);
190
+ const lines = [];
191
+ for (const entry of visible) {
192
+ if (entry.isDirectory()) {
193
+ lines.push(` ${entry.name}/`);
194
+ }
195
+ else {
196
+ const info = await stat(`${absolute}/${entry.name}`).catch(() => undefined);
197
+ const size = info ? formatSize(info.size) : '';
198
+ lines.push(` ${entry.name}${size ? ` ${size}` : ''}`);
199
+ }
200
+ }
201
+ const path = displayPath(context.cwd, absolute);
202
+ return {
203
+ output: lines.length > 0 ? `${path}/\n${lines.join('\n')}` : `${path}/ is empty.`,
204
+ title: path,
205
+ display: { kind: 'files', summary: `${visible.length} entries`, lines: visible.length }
206
+ };
207
+ }
208
+ };
209
+ function countOccurrences(haystack, needle) {
210
+ if (!needle)
211
+ return 0;
212
+ let count = 0;
213
+ let index = 0;
214
+ while ((index = haystack.indexOf(needle, index)) !== -1) {
215
+ count += 1;
216
+ index += needle.length;
217
+ }
218
+ return count;
219
+ }
220
+ function formatSize(bytes) {
221
+ if (bytes < 1024)
222
+ return `${bytes} B`;
223
+ if (bytes < 1024 * 1024)
224
+ return `${(bytes / 1024).toFixed(1)} KB`;
225
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
226
+ }
227
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/tools/files.ts"],"names":[],"mappings":"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"}