@datename/fastcode-termux 0.1.6 → 0.1.8-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +4 -0
- package/README.md +67 -16
- package/dist/agent/approval-json.d.ts +43 -0
- package/dist/agent/approval-json.js +69 -0
- package/dist/agent/approval-native.d.ts +3 -0
- package/dist/agent/approval-native.js +165 -0
- package/dist/agent/approval-store.d.ts +16 -0
- package/dist/agent/approval-store.js +21 -0
- package/dist/agent/approval.d.ts +83 -0
- package/dist/agent/approval.js +42 -0
- package/dist/agent/compaction.d.ts +41 -0
- package/dist/agent/compaction.js +270 -0
- package/dist/agent/context.d.ts +29 -0
- package/dist/agent/context.js +62 -0
- package/dist/agent/guards.d.ts +24 -16
- package/dist/agent/guards.js +1167 -18
- package/dist/agent/ignore.d.ts +11 -0
- package/dist/agent/ignore.js +129 -0
- package/dist/agent/policy/defaults.d.ts +16 -0
- package/dist/agent/policy/defaults.js +17 -0
- package/dist/agent/policy/egress.d.ts +32 -0
- package/dist/agent/policy/egress.js +280 -0
- package/dist/agent/process-tree.d.ts +22 -0
- package/dist/agent/process-tree.js +102 -0
- package/dist/agent/protocol-mode.d.ts +6 -0
- package/dist/agent/protocol-mode.js +51 -0
- package/dist/agent/protocol.d.ts +20 -1
- package/dist/agent/protocol.js +169 -39
- package/dist/agent/registry.d.ts +19 -0
- package/dist/agent/registry.js +247 -0
- package/dist/agent/runner.d.ts +127 -0
- package/dist/agent/runner.js +391 -0
- package/dist/agent/shell-ast.d.ts +11 -0
- package/dist/agent/shell-ast.js +204 -0
- package/dist/agent/shell-session.d.ts +51 -0
- package/dist/agent/shell-session.js +611 -0
- package/dist/agent/stream.d.ts +29 -0
- package/dist/agent/stream.js +103 -0
- package/dist/agent/tool-schemas.d.ts +2 -0
- package/dist/agent/tool-schemas.js +82 -0
- package/dist/agent/tools/append_file.d.ts +2 -0
- package/dist/agent/tools/append_file.js +28 -0
- package/dist/agent/tools/apply_patch.d.ts +10 -0
- package/dist/agent/tools/apply_patch.js +92 -0
- package/dist/agent/tools/copy_file.d.ts +2 -0
- package/dist/agent/tools/copy_file.js +53 -0
- package/dist/agent/tools/delete_file.d.ts +2 -0
- package/dist/agent/tools/delete_file.js +43 -0
- package/dist/agent/tools/grep.d.ts +2 -0
- package/dist/agent/tools/grep.js +54 -0
- package/dist/agent/tools/index.d.ts +2 -0
- package/dist/agent/tools/index.js +32 -0
- package/dist/agent/tools/list_files.d.ts +2 -0
- package/dist/agent/tools/list_files.js +17 -0
- package/dist/agent/tools/make_dir.d.ts +2 -0
- package/dist/agent/tools/make_dir.js +26 -0
- package/dist/agent/tools/move_path.d.ts +9 -0
- package/dist/agent/tools/move_path.js +73 -0
- package/dist/agent/tools/paths.d.ts +7 -0
- package/dist/agent/tools/paths.js +84 -0
- package/dist/agent/tools/pwd.d.ts +2 -0
- package/dist/agent/tools/pwd.js +10 -0
- package/dist/agent/tools/read_file.d.ts +2 -0
- package/dist/agent/tools/read_file.js +81 -0
- package/dist/agent/tools/read_many.d.ts +2 -0
- package/dist/agent/tools/read_many.js +43 -0
- package/dist/agent/tools/readers.d.ts +58 -0
- package/dist/agent/tools/readers.js +426 -0
- package/dist/agent/tools/replace_in_file.d.ts +2 -0
- package/dist/agent/tools/replace_in_file.js +63 -0
- package/dist/agent/tools/shell.d.ts +2 -0
- package/dist/agent/tools/shell.js +48 -0
- package/dist/agent/tools/stat_path.d.ts +2 -0
- package/dist/agent/tools/stat_path.js +31 -0
- package/dist/agent/tools/types.d.ts +65 -0
- package/dist/agent/tools/types.js +1 -0
- package/dist/agent/tools/validate.d.ts +19 -0
- package/dist/agent/tools/validate.js +92 -0
- package/dist/agent/tools/write_file.d.ts +2 -0
- package/dist/agent/tools/write_file.js +28 -0
- package/dist/agent/tools.d.ts +3 -1
- package/dist/agent/tools.js +2 -377
- package/dist/app.d.ts +2 -1
- package/dist/app.js +846 -173
- package/dist/cli-main.js +363 -0
- package/dist/cli.js +444 -333
- package/dist/commands/about.js +1 -1
- package/dist/commands/attach.d.ts +9 -0
- package/dist/commands/attach.js +15 -0
- package/dist/commands/bg.d.ts +7 -0
- package/dist/commands/bg.js +9 -0
- package/dist/commands/cancel.d.ts +10 -0
- package/dist/commands/cancel.js +10 -0
- package/dist/commands/clear.d.ts +1 -0
- package/dist/commands/clear.js +1 -1
- package/dist/commands/compact.d.ts +22 -0
- package/dist/commands/compact.js +34 -0
- package/dist/commands/context.d.ts +7 -0
- package/dist/commands/context.js +25 -0
- package/dist/commands/edit.d.ts +10 -0
- package/dist/commands/edit.js +36 -0
- package/dist/commands/effort.d.ts +25 -0
- package/dist/commands/effort.js +48 -0
- package/dist/commands/expand.d.ts +10 -0
- package/dist/commands/expand.js +8 -0
- package/dist/commands/index.js +24 -0
- package/dist/commands/jobs.d.ts +7 -0
- package/dist/commands/jobs.js +17 -0
- package/dist/commands/kill.d.ts +7 -0
- package/dist/commands/kill.js +13 -0
- package/dist/commands/login.d.ts +6 -4
- package/dist/commands/login.js +24 -22
- package/dist/commands/logout.js +8 -16
- package/dist/commands/model.d.ts +1 -0
- package/dist/commands/model.js +10 -22
- package/dist/commands/provider.d.ts +1 -2
- package/dist/commands/provider.js +4 -11
- package/dist/commands/skills.js +34 -4
- package/dist/commands/steer.d.ts +11 -0
- package/dist/commands/steer.js +13 -0
- package/dist/commands/threads.d.ts +9 -0
- package/dist/commands/threads.js +26 -0
- package/dist/commands/whoami.js +6 -5
- package/dist/config/store.d.ts +53 -12
- package/dist/config/store.js +163 -73
- package/dist/config/trust.d.ts +30 -8
- package/dist/config/trust.js +139 -14
- package/dist/headless.d.ts +7 -0
- package/dist/headless.js +213 -0
- package/dist/index.js +19 -3
- package/dist/lib/debug.d.ts +2 -0
- package/dist/lib/debug.js +22 -0
- package/dist/lib/diagnostics.d.ts +48 -4
- package/dist/lib/diagnostics.js +90 -8
- package/dist/lib/highlight-subset.d.ts +21 -0
- package/dist/lib/highlight-subset.js +88 -0
- package/dist/lib/http.d.ts +11 -1
- package/dist/lib/http.js +62 -4
- package/dist/lib/lifecycle.d.ts +5 -0
- package/dist/lib/lifecycle.js +62 -0
- package/dist/lib/markdown.js +22 -4
- package/dist/lib/model-meta.d.ts +19 -0
- package/dist/lib/model-meta.js +113 -0
- package/dist/lib/native-tools.d.ts +12 -0
- package/dist/lib/native-tools.js +21 -0
- package/dist/lib/net.d.ts +33 -0
- package/dist/lib/net.js +168 -0
- package/dist/patch/apply.d.ts +15 -0
- package/dist/patch/apply.js +172 -0
- package/dist/patch/parse.d.ts +29 -0
- package/dist/patch/parse.js +112 -0
- package/dist/patch/plan.d.ts +49 -0
- package/dist/patch/plan.js +273 -0
- package/dist/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.js +12 -0
- package/dist/providers/custom.d.ts +9 -0
- package/dist/providers/deepseek.d.ts +10 -0
- package/dist/providers/deepseek.js +3 -2
- package/dist/providers/google.d.ts +9 -0
- package/dist/providers/groq.d.ts +10 -0
- package/dist/providers/groq.js +2 -1
- package/dist/providers/index.d.ts +10 -201
- package/dist/providers/index.js +30 -0
- package/dist/providers/mistral.d.ts +10 -0
- package/dist/providers/mistral.js +2 -1
- package/dist/providers/moonshot.d.ts +10 -0
- package/dist/providers/moonshot.js +2 -1
- package/dist/providers/ollama.d.ts +9 -0
- package/dist/providers/openai.d.ts +10 -0
- package/dist/providers/openai.js +2 -1
- package/dist/providers/openaiCompatible.d.ts +33 -2
- package/dist/providers/openaiCompatible.js +78 -16
- package/dist/providers/openrouter.d.ts +10 -0
- package/dist/providers/openrouter.js +2 -1
- package/dist/providers/qwen.d.ts +10 -0
- package/dist/providers/qwen.js +2 -1
- package/dist/providers/spec.d.ts +12 -0
- package/dist/providers/spec.js +29 -0
- package/dist/providers/xai.d.ts +10 -0
- package/dist/providers/xai.js +2 -1
- package/dist/providers/zhipu.d.ts +10 -0
- package/dist/providers/zhipu.js +2 -1
- package/dist/session/log.d.ts +49 -14
- package/dist/session/log.js +236 -11
- package/dist/session/projection.d.ts +76 -0
- package/dist/session/projection.js +526 -0
- package/dist/skills/manager.d.ts +15 -0
- package/dist/skills/manager.js +135 -18
- package/dist/types.d.ts +75 -1
- package/dist/ui/Message.d.ts +1 -7
- package/dist/ui/Message.js +13 -2
- package/dist/ui/Picker.d.ts +8 -0
- package/dist/ui/Picker.js +24 -0
- package/dist/ui/Prompt.d.ts +1 -2
- package/dist/ui/Prompt.js +2 -2
- package/dist/ui/Spinner.js +11 -5
- package/dist/ui/StatusBar.d.ts +2 -1
- package/dist/ui/StatusBar.js +6 -5
- package/package.json +3 -2
- package/src/agent/approval-json.ts +103 -0
- package/src/agent/approval-native.ts +168 -0
- package/src/agent/approval-store.ts +38 -0
- package/src/agent/approval.ts +94 -0
- package/src/agent/compaction.ts +321 -0
- package/src/agent/context.ts +97 -0
- package/src/agent/guards.ts +1239 -19
- package/src/agent/ignore.ts +147 -0
- package/src/agent/policy/defaults.ts +34 -0
- package/src/agent/policy/egress.ts +335 -0
- package/src/agent/process-tree.ts +114 -0
- package/src/agent/protocol-mode.ts +59 -0
- package/src/agent/protocol.ts +191 -40
- package/src/agent/registry.ts +270 -0
- package/src/agent/runner.ts +486 -0
- package/src/agent/shell-ast.ts +227 -0
- package/src/agent/shell-session.ts +673 -0
- package/src/agent/stream.ts +143 -0
- package/src/agent/tool-schemas.ts +86 -0
- package/src/agent/tools/append_file.ts +30 -0
- package/src/agent/tools/apply_patch.ts +95 -0
- package/src/agent/tools/copy_file.ts +56 -0
- package/src/agent/tools/delete_file.ts +45 -0
- package/src/agent/tools/grep.ts +57 -0
- package/src/agent/tools/index.ts +34 -0
- package/src/agent/tools/list_files.ts +19 -0
- package/src/agent/tools/make_dir.ts +28 -0
- package/src/agent/tools/move_path.ts +83 -0
- package/src/agent/tools/paths.ts +92 -0
- package/src/agent/tools/pwd.ts +12 -0
- package/src/agent/tools/read_file.ts +84 -0
- package/src/agent/tools/read_many.ts +45 -0
- package/src/agent/tools/readers.ts +491 -0
- package/src/agent/tools/replace_in_file.ts +66 -0
- package/src/agent/tools/shell.ts +53 -0
- package/src/agent/tools/stat_path.ts +33 -0
- package/src/agent/tools/types.ts +84 -0
- package/src/agent/tools/validate.ts +104 -0
- package/src/agent/tools/write_file.ts +30 -0
- package/src/agent/tools.ts +3 -377
- package/src/app.ts +853 -170
- package/src/{cli.ts → cli-main.ts} +64 -9
- package/src/commands/about.ts +1 -1
- package/src/commands/attach.ts +16 -0
- package/src/commands/bg.ts +9 -0
- package/src/commands/cancel.ts +10 -0
- package/src/commands/clear.ts +1 -1
- package/src/commands/compact.ts +35 -0
- package/src/commands/context.ts +26 -0
- package/src/commands/edit.ts +37 -0
- package/src/commands/effort.ts +49 -0
- package/src/commands/expand.ts +8 -0
- package/src/commands/index.ts +24 -0
- package/src/commands/jobs.ts +18 -0
- package/src/commands/kill.ts +14 -0
- package/src/commands/login.ts +24 -22
- package/src/commands/logout.ts +8 -16
- package/src/commands/model.ts +10 -22
- package/src/commands/provider.ts +4 -11
- package/src/commands/skills.ts +34 -4
- package/src/commands/steer.ts +13 -0
- package/src/commands/threads.ts +28 -0
- package/src/commands/whoami.ts +6 -5
- package/src/config/store.ts +168 -77
- package/src/config/trust.ts +181 -22
- package/src/headless.ts +225 -0
- package/src/index.ts +19 -3
- package/src/lib/debug.ts +24 -0
- package/src/lib/diagnostics.ts +90 -8
- package/src/lib/highlight-subset.ts +93 -0
- package/src/lib/http.ts +66 -4
- package/src/lib/lifecycle.ts +69 -0
- package/src/lib/markdown.ts +22 -4
- package/src/lib/model-meta.ts +138 -0
- package/src/lib/native-tools.ts +32 -0
- package/src/lib/net.ts +204 -0
- package/src/patch/apply.ts +194 -0
- package/src/patch/parse.ts +131 -0
- package/src/patch/plan.ts +317 -0
- package/src/providers/anthropic.ts +13 -1
- package/src/providers/deepseek.ts +3 -2
- package/src/providers/groq.ts +2 -1
- package/src/providers/index.ts +32 -1
- package/src/providers/mistral.ts +2 -1
- package/src/providers/moonshot.ts +2 -1
- package/src/providers/openai.ts +2 -1
- package/src/providers/openaiCompatible.ts +104 -19
- package/src/providers/openrouter.ts +2 -1
- package/src/providers/qwen.ts +2 -1
- package/src/providers/spec.ts +42 -0
- package/src/providers/xai.ts +2 -1
- package/src/providers/zhipu.ts +2 -1
- package/src/session/log.ts +311 -29
- package/src/session/projection.ts +621 -0
- package/src/skills/manager.ts +140 -18
- package/src/types/highlight-shims.d.ts +14 -0
- package/src/types.ts +79 -2
- package/src/ui/Message.ts +13 -2
- package/src/ui/Picker.ts +24 -0
- package/src/ui/Prompt.ts +2 -2
- package/src/ui/Spinner.ts +11 -5
- package/src/ui/StatusBar.ts +6 -5
- package/tsconfig.json +1 -0
- /package/dist/{cli.d.ts → cli-main.d.ts} +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { cp, mkdir, rename, rm } from "node:fs/promises";
|
|
2
|
+
import { lstatSync } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { sandboxPath } from "./paths.js";
|
|
5
|
+
import type { Tool } from "./types.js";
|
|
6
|
+
import { invalid, preparePath, requiredString } from "./validate.js";
|
|
7
|
+
|
|
8
|
+
function exists(path: string): boolean {
|
|
9
|
+
try {
|
|
10
|
+
lstatSync(path);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MoveOps {
|
|
19
|
+
rename: typeof rename;
|
|
20
|
+
cp: typeof cp;
|
|
21
|
+
rm: typeof rm;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function moveWithFallback(from: string, to: string, ops: MoveOps = { rename, cp, rm }): Promise<"rename" | "copy"> {
|
|
25
|
+
try {
|
|
26
|
+
await ops.rename(from, to);
|
|
27
|
+
return "rename";
|
|
28
|
+
}
|
|
29
|
+
catch (err: any) {
|
|
30
|
+
if (err?.code !== "EXDEV")
|
|
31
|
+
throw err;
|
|
32
|
+
await ops.cp(from, to, { recursive: true, force: false, errorOnExist: true });
|
|
33
|
+
try {
|
|
34
|
+
await ops.rm(from, { recursive: true, force: false });
|
|
35
|
+
}
|
|
36
|
+
catch (cleanup: any) {
|
|
37
|
+
throw Object.assign(new Error(`copied ${from} to ${to}, but could not remove the source: ${cleanup?.message ?? String(cleanup)}`), {
|
|
38
|
+
code: "UNKNOWN",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return "copy";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const movePathTool: Tool = {
|
|
46
|
+
name: "move_path",
|
|
47
|
+
requiresTrust: true,
|
|
48
|
+
stateScope: "turn",
|
|
49
|
+
revalidate: ["trust", "sandboxRoots"],
|
|
50
|
+
prepare(call, ctx) {
|
|
51
|
+
try {
|
|
52
|
+
const from = requiredString(call, "from");
|
|
53
|
+
const to = requiredString(call, "to");
|
|
54
|
+
const checkedFrom = preparePath(ctx.cwd, from);
|
|
55
|
+
if (!checkedFrom.ok)
|
|
56
|
+
return checkedFrom;
|
|
57
|
+
const checkedTo = preparePath(ctx.cwd, to);
|
|
58
|
+
if (!checkedTo.ok)
|
|
59
|
+
return checkedTo;
|
|
60
|
+
if (exists(to))
|
|
61
|
+
return invalid(`move target exists: ${to}`, "EEXIST", "Choose a target that does not exist.");
|
|
62
|
+
return { ok: true };
|
|
63
|
+
}
|
|
64
|
+
catch (err: any) {
|
|
65
|
+
return invalid(err.message);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
async execute(call, ctx) {
|
|
69
|
+
const from = sandboxPath(ctx.cwd, requiredString(call, "from"));
|
|
70
|
+
const to = sandboxPath(ctx.cwd, requiredString(call, "to"));
|
|
71
|
+
if (exists(to))
|
|
72
|
+
return { ok: false, output: `move target exists: ${to}`, code: "EEXIST", hint: "Choose a target that does not exist." };
|
|
73
|
+
await mkdir(dirname(to), { recursive: true });
|
|
74
|
+
const method = await moveWithFallback(from, to);
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
output: method === "copy"
|
|
78
|
+
? `moved ${from} to ${to} (cross-device copy + remove)`
|
|
79
|
+
: `moved ${from} to ${to}`,
|
|
80
|
+
sideEffects: { removed: [from], touched: [to] },
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
+
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
|
+
import { detectPlatform, safeHome } from "../../lib/platform.js";
|
|
4
|
+
import { loadConfig } from "../../config/store.js";
|
|
5
|
+
import type { ToolCall } from "./types.js";
|
|
6
|
+
|
|
7
|
+
export function allowedRoots(cwd: string): string[] {
|
|
8
|
+
const roots = [resolve(cwd)];
|
|
9
|
+
const configured = (process.env["FASTCODE_ALLOW_PATHS"] ?? "")
|
|
10
|
+
.split(delimiter)
|
|
11
|
+
.map((entry) => entry.trim())
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
for (const entry of configured)
|
|
14
|
+
roots.push(resolve(entry));
|
|
15
|
+
const sharedDirs = loadConfig().sharedDirs;
|
|
16
|
+
if (Array.isArray(sharedDirs)) {
|
|
17
|
+
for (const entry of sharedDirs) {
|
|
18
|
+
if (typeof entry !== "string" || !entry.trim())
|
|
19
|
+
continue;
|
|
20
|
+
roots.push(resolveSharedDir(cwd, entry.trim()));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (detectPlatform() === "termux" && !isDisabled(process.env["FASTCODE_ALLOW_SHARED_STORAGE"])) {
|
|
24
|
+
const home = process.env["HOME"];
|
|
25
|
+
if (home) {
|
|
26
|
+
const shared = join(home, "storage", "shared");
|
|
27
|
+
if (existsSync(shared))
|
|
28
|
+
roots.push(shared);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return roots;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function resolveSharedDir(cwd: string, entry: string): string {
|
|
35
|
+
const expanded = entry === "~" || entry.startsWith("~/") || entry.startsWith("~\\")
|
|
36
|
+
? join(safeHome(), entry.slice(1))
|
|
37
|
+
: entry;
|
|
38
|
+
return isAbsolute(expanded) ? resolve(expanded) : resolve(cwd, expanded);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isDisabled(value: string | undefined): boolean {
|
|
42
|
+
if (value === undefined)
|
|
43
|
+
return false;
|
|
44
|
+
return ["0", "false", "no", "off"].includes(value.trim().toLowerCase());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function isInsideAny(child: string, roots: string[]): boolean {
|
|
48
|
+
return roots.some((root) => {
|
|
49
|
+
const rel = relative(root, child);
|
|
50
|
+
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function resolvePath(cwd: string, call: ToolCall, fallback = ""): string {
|
|
55
|
+
const raw = typeof call.path === "string" ? call.path : fallback;
|
|
56
|
+
return sandboxPath(cwd, raw);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function sandboxPath(cwd: string, raw: string): string {
|
|
60
|
+
const target = resolve(cwd, raw);
|
|
61
|
+
const roots = allowedRoots(cwd);
|
|
62
|
+
const realRoots = roots.map((root) => realpathOf(root)).filter(Boolean) as string[];
|
|
63
|
+
const realTarget = realpathOf(target);
|
|
64
|
+
if (realTarget) {
|
|
65
|
+
if (isInsideAny(realTarget, realRoots))
|
|
66
|
+
return target;
|
|
67
|
+
throw new Error("path outside sandbox: " + raw);
|
|
68
|
+
}
|
|
69
|
+
if (isInsideAny(target, roots))
|
|
70
|
+
return target;
|
|
71
|
+
throw new Error("path outside sandbox: " + raw);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function realpathOf(input: string): string | undefined {
|
|
75
|
+
let current = resolve(input);
|
|
76
|
+
const missing: string[] = [];
|
|
77
|
+
for (;;) {
|
|
78
|
+
if (existsSync(current)) {
|
|
79
|
+
try {
|
|
80
|
+
return join(realpathSync(current), ...missing.slice().reverse());
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const parent = dirname(current);
|
|
87
|
+
if (parent === current)
|
|
88
|
+
return undefined;
|
|
89
|
+
missing.push(basename(current));
|
|
90
|
+
current = parent;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { readFileRange, readTextFileResult } from "./readers.js";
|
|
2
|
+
import { resolvePath } from "./paths.js";
|
|
3
|
+
import type { Tool } from "./types.js";
|
|
4
|
+
import { clampInt, invalid, optionalNumber, preparePath, requiredString } from "./validate.js";
|
|
5
|
+
|
|
6
|
+
const MAX_READ_LINES = 2000;
|
|
7
|
+
|
|
8
|
+
export const readFileTool: Tool = {
|
|
9
|
+
name: "read_file",
|
|
10
|
+
stateScope: "call",
|
|
11
|
+
revalidate: ["sandboxRoots"],
|
|
12
|
+
prepare(call, ctx) {
|
|
13
|
+
let path: string;
|
|
14
|
+
try {
|
|
15
|
+
path = requiredString(call, "path");
|
|
16
|
+
const offset = optionalNumber(call, "offset");
|
|
17
|
+
const limit = optionalNumber(call, "limit");
|
|
18
|
+
if (offset !== undefined && offset < 1)
|
|
19
|
+
return invalid("offset must be >= 1");
|
|
20
|
+
if (limit !== undefined && limit < 1)
|
|
21
|
+
return invalid("limit must be >= 1");
|
|
22
|
+
}
|
|
23
|
+
catch (err: any) {
|
|
24
|
+
return invalid(err.message);
|
|
25
|
+
}
|
|
26
|
+
return preparePath(ctx.cwd, path);
|
|
27
|
+
},
|
|
28
|
+
async execute(call, ctx) {
|
|
29
|
+
const file = resolvePath(ctx.cwd, call);
|
|
30
|
+
const offset = optionalNumber(call, "offset");
|
|
31
|
+
const limit = optionalNumber(call, "limit");
|
|
32
|
+
if (offset === undefined && limit === undefined) {
|
|
33
|
+
const result = await readTextFileResult(file);
|
|
34
|
+
const output = result.truncated
|
|
35
|
+
? `${result.text}\n[... truncated at ${result.returnedBytes} of ${result.totalBytes} bytes; use offset/limit, grep, or a narrower file ...]`
|
|
36
|
+
: result.text;
|
|
37
|
+
return {
|
|
38
|
+
ok: true,
|
|
39
|
+
output,
|
|
40
|
+
truncated: result.truncated,
|
|
41
|
+
totalLines: result.totalLines,
|
|
42
|
+
returnedLines: result.returnedLines,
|
|
43
|
+
totalBytes: result.totalBytes,
|
|
44
|
+
returnedBytes: result.returnedBytes,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const start = clampInt(offset, 1, 1, 1_000_000);
|
|
48
|
+
const count = clampInt(limit, MAX_READ_LINES, 1, MAX_READ_LINES);
|
|
49
|
+
const result = await readFileRange(file, start, count, { signal: ctx.signal });
|
|
50
|
+
if (result.binary) {
|
|
51
|
+
return {
|
|
52
|
+
ok: true,
|
|
53
|
+
output: result.text,
|
|
54
|
+
truncated: false,
|
|
55
|
+
totalLines: 0,
|
|
56
|
+
returnedLines: 0,
|
|
57
|
+
totalBytes: result.totalBytes,
|
|
58
|
+
returnedBytes: 0,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (result.returnedLines === 0 && start > result.totalLines) {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
output: `offset ${start} is beyond the end of ${file} (${result.totalLines} lines)`,
|
|
65
|
+
code: "NOT_FOUND",
|
|
66
|
+
hint: "Use a smaller offset or read without offset.",
|
|
67
|
+
totalLines: result.totalLines,
|
|
68
|
+
returnedLines: 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const end = start + result.returnedLines - 1;
|
|
72
|
+
const header = `[lines ${start}-${end} of ${result.totalLines}${result.scannedAll ? "" : "+"}]\n`;
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
output: header + result.text,
|
|
76
|
+
truncated: result.truncated,
|
|
77
|
+
hint: result.scannedAll ? undefined : "totalLines is a lower bound; the file scan hit FASTCODE_READ_SCAN_MAX_BYTES.",
|
|
78
|
+
totalLines: result.totalLines,
|
|
79
|
+
returnedLines: result.returnedLines,
|
|
80
|
+
totalBytes: result.totalBytes,
|
|
81
|
+
returnedBytes: result.returnedBytes,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readManyResult } from "./readers.js";
|
|
2
|
+
import type { Tool } from "./types.js";
|
|
3
|
+
import { invalid, optionalNumber, preparePath, stringArray } from "./validate.js";
|
|
4
|
+
|
|
5
|
+
export const readManyTool: Tool = {
|
|
6
|
+
name: "read_many",
|
|
7
|
+
stateScope: "call",
|
|
8
|
+
revalidate: ["sandboxRoots"],
|
|
9
|
+
prepare(call, ctx) {
|
|
10
|
+
let paths: string[];
|
|
11
|
+
try {
|
|
12
|
+
paths = stringArray(call, "paths");
|
|
13
|
+
if (paths.length === 0)
|
|
14
|
+
return invalid("paths must contain at least one path");
|
|
15
|
+
const maxBytes = optionalNumber(call, "maxBytes");
|
|
16
|
+
if (maxBytes !== undefined && maxBytes < 1)
|
|
17
|
+
return invalid("maxBytes must be >= 1");
|
|
18
|
+
}
|
|
19
|
+
catch (err: any) {
|
|
20
|
+
return invalid(err.message);
|
|
21
|
+
}
|
|
22
|
+
for (const path of paths) {
|
|
23
|
+
const checked = preparePath(ctx.cwd, path);
|
|
24
|
+
if (!checked.ok)
|
|
25
|
+
return checked;
|
|
26
|
+
}
|
|
27
|
+
return { ok: true };
|
|
28
|
+
},
|
|
29
|
+
async execute(call, ctx) {
|
|
30
|
+
const paths = stringArray(call, "paths");
|
|
31
|
+
const requested = optionalNumber(call, "maxBytes");
|
|
32
|
+
const maxBytes = requested === undefined ? undefined : Math.max(1, Math.floor(requested));
|
|
33
|
+
const result = await readManyResult(ctx.cwd, paths, maxBytes);
|
|
34
|
+
return {
|
|
35
|
+
ok: true,
|
|
36
|
+
output: result.text,
|
|
37
|
+
truncated: result.truncated,
|
|
38
|
+
totalBytes: result.totalBytes,
|
|
39
|
+
returnedBytes: result.returnedBytes,
|
|
40
|
+
filesRead: result.filesRead,
|
|
41
|
+
filesSkipped: result.filesSkipped,
|
|
42
|
+
hint: result.filesSkipped > 0 ? `${result.filesSkipped} file(s) skipped by the read_many byte budget.` : undefined,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
};
|