@datename/fastcode-termux 0.1.6-beta → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -24
- package/dist/agent/guards.d.ts +0 -8
- package/dist/agent/guards.js +0 -195
- package/dist/agent/protocol.js +1 -4
- package/dist/agent/tools.d.ts +1 -3
- package/dist/agent/tools.js +377 -2
- package/dist/app.js +103 -335
- package/dist/cli.js +311 -362
- package/dist/commands/index.js +0 -22
- package/dist/commands/login.d.ts +2 -4
- package/dist/commands/login.js +10 -12
- package/dist/commands/logout.js +16 -8
- package/dist/commands/model.d.ts +0 -13
- package/dist/commands/model.js +22 -42
- package/dist/commands/provider.d.ts +0 -13
- package/dist/commands/provider.js +9 -20
- package/dist/commands/whoami.js +5 -6
- package/dist/config/store.d.ts +12 -32
- package/dist/config/store.js +65 -117
- package/dist/config/trust.d.ts +8 -21
- package/dist/config/trust.js +13 -99
- package/dist/lib/diagnostics.d.ts +4 -29
- package/dist/lib/diagnostics.js +4 -60
- package/dist/lib/http.d.ts +1 -11
- package/dist/lib/http.js +4 -62
- package/dist/providers/anthropic.d.ts +0 -1
- package/dist/providers/anthropic.js +0 -12
- package/dist/providers/custom.d.ts +0 -9
- package/dist/providers/deepseek.d.ts +0 -10
- package/dist/providers/deepseek.js +1 -2
- package/dist/providers/google.d.ts +0 -9
- package/dist/providers/groq.d.ts +0 -10
- package/dist/providers/groq.js +1 -2
- package/dist/providers/index.d.ts +201 -10
- package/dist/providers/index.js +0 -30
- package/dist/providers/mistral.d.ts +0 -10
- package/dist/providers/mistral.js +1 -2
- package/dist/providers/moonshot.d.ts +0 -10
- package/dist/providers/moonshot.js +1 -2
- package/dist/providers/ollama.d.ts +0 -9
- package/dist/providers/openai.d.ts +0 -10
- package/dist/providers/openai.js +1 -2
- package/dist/providers/openaiCompatible.d.ts +0 -9
- package/dist/providers/openaiCompatible.js +10 -58
- package/dist/providers/openrouter.d.ts +0 -10
- package/dist/providers/openrouter.js +1 -2
- package/dist/providers/qwen.d.ts +0 -10
- package/dist/providers/qwen.js +1 -2
- package/dist/providers/xai.d.ts +0 -10
- package/dist/providers/xai.js +1 -2
- package/dist/providers/zhipu.d.ts +0 -10
- package/dist/providers/zhipu.js +1 -2
- package/dist/session/log.d.ts +12 -35
- package/dist/session/log.js +10 -206
- package/dist/types.d.ts +1 -60
- package/dist/ui/Message.d.ts +7 -1
- package/dist/ui/Message.js +2 -13
- package/dist/ui/Prompt.d.ts +2 -1
- package/dist/ui/Prompt.js +2 -2
- package/dist/ui/Spinner.js +5 -11
- package/dist/ui/StatusBar.d.ts +1 -2
- package/dist/ui/StatusBar.js +5 -6
- package/package.json +1 -1
- package/src/agent/guards.ts +0 -196
- package/src/agent/protocol.ts +1 -4
- package/src/agent/tools.ts +377 -3
- package/src/app.ts +103 -335
- package/src/cli.ts +3 -30
- package/src/commands/index.ts +0 -22
- package/src/commands/login.ts +10 -12
- package/src/commands/logout.ts +16 -8
- package/src/commands/model.ts +22 -42
- package/src/commands/provider.ts +9 -20
- package/src/commands/whoami.ts +5 -6
- package/src/config/store.ts +69 -122
- package/src/config/trust.ts +21 -137
- package/src/lib/diagnostics.ts +4 -60
- package/src/lib/http.ts +4 -66
- package/src/providers/anthropic.ts +1 -13
- package/src/providers/deepseek.ts +1 -2
- package/src/providers/groq.ts +1 -2
- package/src/providers/index.ts +1 -32
- package/src/providers/mistral.ts +1 -2
- package/src/providers/moonshot.ts +1 -2
- package/src/providers/openai.ts +1 -2
- package/src/providers/openaiCompatible.ts +10 -58
- package/src/providers/openrouter.ts +1 -2
- package/src/providers/qwen.ts +1 -2
- package/src/providers/xai.ts +1 -2
- package/src/providers/zhipu.ts +1 -2
- package/src/session/log.ts +28 -267
- package/src/types.ts +1 -63
- package/src/ui/Message.ts +2 -13
- package/src/ui/Prompt.ts +2 -2
- package/src/ui/Spinner.ts +5 -11
- package/src/ui/StatusBar.ts +5 -6
- package/dist/agent/approval.d.ts +0 -50
- package/dist/agent/approval.js +0 -7
- package/dist/agent/compaction.d.ts +0 -39
- package/dist/agent/compaction.js +0 -227
- package/dist/agent/context.d.ts +0 -29
- package/dist/agent/context.js +0 -62
- package/dist/agent/ignore.d.ts +0 -11
- package/dist/agent/ignore.js +0 -129
- package/dist/agent/process-tree.d.ts +0 -2
- package/dist/agent/process-tree.js +0 -31
- package/dist/agent/protocol-mode.d.ts +0 -6
- package/dist/agent/protocol-mode.js +0 -51
- package/dist/agent/registry.d.ts +0 -17
- package/dist/agent/registry.js +0 -90
- package/dist/agent/runner.d.ts +0 -106
- package/dist/agent/runner.js +0 -352
- package/dist/agent/shell-session.d.ts +0 -37
- package/dist/agent/shell-session.js +0 -400
- package/dist/agent/stream.d.ts +0 -29
- package/dist/agent/stream.js +0 -103
- package/dist/agent/tool-schemas.d.ts +0 -2
- package/dist/agent/tool-schemas.js +0 -63
- package/dist/agent/tools/append_file.d.ts +0 -2
- package/dist/agent/tools/append_file.js +0 -26
- package/dist/agent/tools/apply_patch.d.ts +0 -10
- package/dist/agent/tools/apply_patch.js +0 -52
- package/dist/agent/tools/copy_file.d.ts +0 -2
- package/dist/agent/tools/copy_file.js +0 -30
- package/dist/agent/tools/delete_file.d.ts +0 -2
- package/dist/agent/tools/delete_file.js +0 -24
- package/dist/agent/tools/grep.d.ts +0 -2
- package/dist/agent/tools/grep.js +0 -23
- package/dist/agent/tools/index.d.ts +0 -2
- package/dist/agent/tools/index.js +0 -32
- package/dist/agent/tools/list_files.d.ts +0 -2
- package/dist/agent/tools/list_files.js +0 -17
- package/dist/agent/tools/make_dir.d.ts +0 -2
- package/dist/agent/tools/make_dir.js +0 -24
- package/dist/agent/tools/move_path.d.ts +0 -2
- package/dist/agent/tools/move_path.js +0 -47
- package/dist/agent/tools/paths.d.ts +0 -7
- package/dist/agent/tools/paths.js +0 -84
- package/dist/agent/tools/pwd.d.ts +0 -2
- package/dist/agent/tools/pwd.js +0 -10
- package/dist/agent/tools/read_file.d.ts +0 -2
- package/dist/agent/tools/read_file.js +0 -21
- package/dist/agent/tools/read_many.d.ts +0 -2
- package/dist/agent/tools/read_many.js +0 -25
- package/dist/agent/tools/readers.d.ts +0 -6
- package/dist/agent/tools/readers.js +0 -216
- package/dist/agent/tools/replace_in_file.d.ts +0 -2
- package/dist/agent/tools/replace_in_file.js +0 -30
- package/dist/agent/tools/shell.d.ts +0 -2
- package/dist/agent/tools/shell.js +0 -48
- package/dist/agent/tools/stat_path.d.ts +0 -2
- package/dist/agent/tools/stat_path.js +0 -31
- package/dist/agent/tools/types.d.ts +0 -39
- package/dist/agent/tools/types.js +0 -1
- package/dist/agent/tools/validate.d.ts +0 -6
- package/dist/agent/tools/validate.js +0 -29
- package/dist/agent/tools/write_file.d.ts +0 -2
- package/dist/agent/tools/write_file.js +0 -26
- package/dist/commands/attach.d.ts +0 -9
- package/dist/commands/attach.js +0 -15
- package/dist/commands/bg.d.ts +0 -7
- package/dist/commands/bg.js +0 -9
- package/dist/commands/cancel.d.ts +0 -10
- package/dist/commands/cancel.js +0 -10
- package/dist/commands/compact.d.ts +0 -10
- package/dist/commands/compact.js +0 -22
- package/dist/commands/context.d.ts +0 -7
- package/dist/commands/context.js +0 -24
- package/dist/commands/edit.d.ts +0 -10
- package/dist/commands/edit.js +0 -36
- package/dist/commands/effort.d.ts +0 -25
- package/dist/commands/effort.js +0 -48
- package/dist/commands/expand.d.ts +0 -10
- package/dist/commands/expand.js +0 -8
- package/dist/commands/jobs.d.ts +0 -7
- package/dist/commands/jobs.js +0 -16
- package/dist/commands/kill.d.ts +0 -7
- package/dist/commands/kill.js +0 -11
- package/dist/commands/steer.d.ts +0 -11
- package/dist/commands/steer.js +0 -13
- package/dist/lib/model-meta.d.ts +0 -19
- package/dist/lib/model-meta.js +0 -113
- package/dist/lib/native-tools.d.ts +0 -12
- package/dist/lib/native-tools.js +0 -21
- package/dist/lib/net.d.ts +0 -33
- package/dist/lib/net.js +0 -168
- package/dist/patch/apply.d.ts +0 -15
- package/dist/patch/apply.js +0 -172
- package/dist/patch/parse.d.ts +0 -29
- package/dist/patch/parse.js +0 -112
- package/dist/patch/plan.d.ts +0 -49
- package/dist/patch/plan.js +0 -273
- package/dist/session/projection.d.ts +0 -43
- package/dist/session/projection.js +0 -257
- package/dist/ui/Picker.d.ts +0 -8
- package/dist/ui/Picker.js +0 -24
- package/src/agent/approval.ts +0 -47
- package/src/agent/compaction.ts +0 -276
- package/src/agent/context.ts +0 -97
- package/src/agent/ignore.ts +0 -147
- package/src/agent/process-tree.ts +0 -32
- package/src/agent/protocol-mode.ts +0 -59
- package/src/agent/registry.ts +0 -98
- package/src/agent/runner.ts +0 -443
- package/src/agent/shell-session.ts +0 -449
- package/src/agent/stream.ts +0 -143
- package/src/agent/tool-schemas.ts +0 -67
- package/src/agent/tools/append_file.ts +0 -28
- package/src/agent/tools/apply_patch.ts +0 -54
- package/src/agent/tools/copy_file.ts +0 -32
- package/src/agent/tools/delete_file.ts +0 -26
- package/src/agent/tools/grep.ts +0 -25
- package/src/agent/tools/index.ts +0 -34
- package/src/agent/tools/list_files.ts +0 -19
- package/src/agent/tools/make_dir.ts +0 -26
- package/src/agent/tools/move_path.ts +0 -50
- package/src/agent/tools/paths.ts +0 -92
- package/src/agent/tools/pwd.ts +0 -12
- package/src/agent/tools/read_file.ts +0 -23
- package/src/agent/tools/read_many.ts +0 -27
- package/src/agent/tools/readers.ts +0 -228
- package/src/agent/tools/replace_in_file.ts +0 -32
- package/src/agent/tools/shell.ts +0 -53
- package/src/agent/tools/stat_path.ts +0 -33
- package/src/agent/tools/types.ts +0 -42
- package/src/agent/tools/validate.ts +0 -35
- package/src/agent/tools/write_file.ts +0 -28
- package/src/commands/attach.ts +0 -16
- package/src/commands/bg.ts +0 -9
- package/src/commands/cancel.ts +0 -10
- package/src/commands/compact.ts +0 -23
- package/src/commands/context.ts +0 -25
- package/src/commands/edit.ts +0 -37
- package/src/commands/effort.ts +0 -49
- package/src/commands/expand.ts +0 -8
- package/src/commands/jobs.ts +0 -17
- package/src/commands/kill.ts +0 -12
- package/src/commands/steer.ts +0 -13
- package/src/lib/model-meta.ts +0 -138
- package/src/lib/native-tools.ts +0 -32
- package/src/lib/net.ts +0 -204
- package/src/patch/apply.ts +0 -194
- package/src/patch/parse.ts +0 -131
- package/src/patch/plan.ts +0 -317
- package/src/session/projection.ts +0 -308
- package/src/ui/Picker.ts +0 -24
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { resolvePath } from "./paths.js";
|
|
3
|
-
import type { Tool } from "./types.js";
|
|
4
|
-
import { invalid, preparePath, requiredString } from "./validate.js";
|
|
5
|
-
|
|
6
|
-
export const replaceInFileTool: Tool = {
|
|
7
|
-
name: "replace_in_file",
|
|
8
|
-
requiresTrust: true,
|
|
9
|
-
stateScope: "turn",
|
|
10
|
-
revalidate: ["trust", "sandboxRoots"],
|
|
11
|
-
prepare(call, ctx) {
|
|
12
|
-
try {
|
|
13
|
-
requiredString(call, "path");
|
|
14
|
-
requiredString(call, "find");
|
|
15
|
-
requiredString(call, "replace");
|
|
16
|
-
}
|
|
17
|
-
catch (err: any) {
|
|
18
|
-
return invalid(err.message);
|
|
19
|
-
}
|
|
20
|
-
return preparePath(ctx.cwd, requiredString(call, "path"));
|
|
21
|
-
},
|
|
22
|
-
async execute(call, ctx) {
|
|
23
|
-
const file = resolvePath(ctx.cwd, call);
|
|
24
|
-
const find = requiredString(call, "find");
|
|
25
|
-
const replacement = requiredString(call, "replace");
|
|
26
|
-
const source = await readFile(file, "utf8");
|
|
27
|
-
if (!source.includes(find))
|
|
28
|
-
return { ok: false, output: `text not found in ${file}` };
|
|
29
|
-
await writeFile(file, source.split(find).join(replacement), "utf8");
|
|
30
|
-
return { ok: true, output: `replaced text in ${file}`, sideEffects: { touched: [file] } };
|
|
31
|
-
},
|
|
32
|
-
};
|
package/src/agent/tools/shell.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { ShellExecResult } from "../shell-session.js";
|
|
2
|
-
import { executeShellCommand, pollShellSession } from "../shell-session.js";
|
|
3
|
-
import type { Tool } from "./types.js";
|
|
4
|
-
import { invalid, numberOption } from "./validate.js";
|
|
5
|
-
|
|
6
|
-
export const shellTool: Tool = {
|
|
7
|
-
name: "shell",
|
|
8
|
-
requiresTrust: true,
|
|
9
|
-
stateScope: "turn",
|
|
10
|
-
revalidate: ["trust", "sandboxRoots"],
|
|
11
|
-
approvalHints: { mayRequireApproval: true },
|
|
12
|
-
prepare(call) {
|
|
13
|
-
if (typeof call.session_id === "string" && call.session_id.trim())
|
|
14
|
-
return { ok: true };
|
|
15
|
-
if (typeof call.command !== "string" || call.command.trim() === "")
|
|
16
|
-
return invalid("command must be a non-empty string");
|
|
17
|
-
return { ok: true };
|
|
18
|
-
},
|
|
19
|
-
async execute(call, ctx) {
|
|
20
|
-
if (typeof call.session_id === "string" && call.session_id.trim()) {
|
|
21
|
-
const polled = await pollShellSession(call.session_id, numberOption(call.waitMs, 0));
|
|
22
|
-
if (!polled)
|
|
23
|
-
return { ok: false, output: `unknown shell session: ${call.session_id}` };
|
|
24
|
-
return formatPoll(call.session_id, polled);
|
|
25
|
-
}
|
|
26
|
-
const result = await executeShellCommand(call.command, ctx.cwd, {
|
|
27
|
-
signal: ctx.signal,
|
|
28
|
-
turn: ctx.turn,
|
|
29
|
-
timeoutMs: numberOption(call.timeoutMs, 120000),
|
|
30
|
-
});
|
|
31
|
-
return formatExec(result);
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
function formatExec(result: ShellExecResult): { ok: boolean; output: string } {
|
|
36
|
-
if (result.status !== "running")
|
|
37
|
-
return { ok: result.ok, output: result.output || `[command ${result.status}]` };
|
|
38
|
-
const header = `[session ${result.sessionId}] running`;
|
|
39
|
-
const body = result.output ? "\n" + result.output : "";
|
|
40
|
-
return {
|
|
41
|
-
ok: true,
|
|
42
|
-
output: `${header}${body}\n\nPoll with: {"tool":"shell","session_id":"${result.sessionId}"}`,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function formatPoll(id: string, result: ShellExecResult): { ok: boolean; output: string } {
|
|
47
|
-
const status = result.status === "running"
|
|
48
|
-
? `running (next poll ~${Math.round((result.nextPollMs ?? 1000) / 1000)}s)`
|
|
49
|
-
: `${result.status}${result.exitCode !== undefined && result.exitCode !== null ? ` (exit ${result.exitCode})` : ""}`;
|
|
50
|
-
const header = `[session ${id}] ${status}`;
|
|
51
|
-
const body = result.output ? "\n" + result.output : result.status === "running" ? "\n(no new output)" : "";
|
|
52
|
-
return { ok: result.ok, output: header + body };
|
|
53
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { stat } from "node:fs/promises";
|
|
2
|
-
import { resolvePath } from "./paths.js";
|
|
3
|
-
import type { Tool } from "./types.js";
|
|
4
|
-
import { invalid, preparePath, requiredString } from "./validate.js";
|
|
5
|
-
|
|
6
|
-
export const statPathTool: Tool = {
|
|
7
|
-
name: "stat_path",
|
|
8
|
-
stateScope: "call",
|
|
9
|
-
revalidate: ["sandboxRoots"],
|
|
10
|
-
prepare(call, ctx) {
|
|
11
|
-
let path: string;
|
|
12
|
-
try {
|
|
13
|
-
path = requiredString(call, "path");
|
|
14
|
-
}
|
|
15
|
-
catch (err: any) {
|
|
16
|
-
return invalid(err.message);
|
|
17
|
-
}
|
|
18
|
-
return preparePath(ctx.cwd, path);
|
|
19
|
-
},
|
|
20
|
-
async execute(call, ctx) {
|
|
21
|
-
const file = resolvePath(ctx.cwd, call);
|
|
22
|
-
const info = await stat(file);
|
|
23
|
-
return {
|
|
24
|
-
ok: true,
|
|
25
|
-
output: JSON.stringify({
|
|
26
|
-
path: file,
|
|
27
|
-
type: info.isDirectory() ? "dir" : info.isFile() ? "file" : "other",
|
|
28
|
-
size: info.size,
|
|
29
|
-
modified: info.mtime.toISOString(),
|
|
30
|
-
}, null, 2),
|
|
31
|
-
};
|
|
32
|
-
},
|
|
33
|
-
};
|
package/src/agent/tools/types.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export type StateScope = "call" | "turn" | "session";
|
|
2
|
-
|
|
3
|
-
export type RevalidateKey = "trust" | "sandboxRoots" | "schema" | "modelCaps";
|
|
4
|
-
|
|
5
|
-
export interface SideEffects {
|
|
6
|
-
touched?: string[];
|
|
7
|
-
created?: string[];
|
|
8
|
-
removed?: string[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ToolCall {
|
|
12
|
-
tool: string;
|
|
13
|
-
[key: string]: any;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ToolResult {
|
|
17
|
-
ok: boolean;
|
|
18
|
-
output: string;
|
|
19
|
-
sideEffects?: SideEffects;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface ToolCtx {
|
|
23
|
-
cwd: string;
|
|
24
|
-
signal?: AbortSignal;
|
|
25
|
-
turn?: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type Prepared = { ok: true } | { ok: false; output: string };
|
|
29
|
-
|
|
30
|
-
export interface ApprovalHints {
|
|
31
|
-
mayRequireApproval: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface Tool {
|
|
35
|
-
name: string;
|
|
36
|
-
requiresTrust?: boolean;
|
|
37
|
-
stateScope: StateScope;
|
|
38
|
-
revalidate?: RevalidateKey[];
|
|
39
|
-
approvalHints?: ApprovalHints;
|
|
40
|
-
prepare(call: ToolCall, ctx: ToolCtx): Prepared;
|
|
41
|
-
execute(call: ToolCall, ctx: ToolCtx): Promise<ToolResult>;
|
|
42
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { sandboxPath } from "./paths.js";
|
|
2
|
-
import type { Prepared, ToolCall } from "./types.js";
|
|
3
|
-
|
|
4
|
-
export function invalid(output: string): Prepared {
|
|
5
|
-
return { ok: false, output };
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function requiredString(call: ToolCall, key: string): string {
|
|
9
|
-
const value = call[key];
|
|
10
|
-
if (typeof value !== "string")
|
|
11
|
-
throw new Error(`${key} must be a string`);
|
|
12
|
-
return value;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function stringArray(call: ToolCall, key: string): string[] {
|
|
16
|
-
const value = call[key];
|
|
17
|
-
if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) {
|
|
18
|
-
throw new Error(`${key} must be an array of strings`);
|
|
19
|
-
}
|
|
20
|
-
return value;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function numberOption(value: any, fallback: number): number {
|
|
24
|
-
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function preparePath(cwd: string, raw: string): Prepared {
|
|
28
|
-
try {
|
|
29
|
-
sandboxPath(cwd, raw);
|
|
30
|
-
return { ok: true };
|
|
31
|
-
}
|
|
32
|
-
catch (err: any) {
|
|
33
|
-
return invalid(err?.message ?? String(err));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import { dirname } from "node:path";
|
|
3
|
-
import { resolvePath } from "./paths.js";
|
|
4
|
-
import type { Tool } from "./types.js";
|
|
5
|
-
import { invalid, preparePath, requiredString } from "./validate.js";
|
|
6
|
-
|
|
7
|
-
export const writeFileTool: Tool = {
|
|
8
|
-
name: "write_file",
|
|
9
|
-
requiresTrust: true,
|
|
10
|
-
stateScope: "turn",
|
|
11
|
-
revalidate: ["trust", "sandboxRoots"],
|
|
12
|
-
prepare(call, ctx) {
|
|
13
|
-
try {
|
|
14
|
-
requiredString(call, "path");
|
|
15
|
-
requiredString(call, "content");
|
|
16
|
-
}
|
|
17
|
-
catch (err: any) {
|
|
18
|
-
return invalid(err.message);
|
|
19
|
-
}
|
|
20
|
-
return preparePath(ctx.cwd, requiredString(call, "path"));
|
|
21
|
-
},
|
|
22
|
-
async execute(call, ctx) {
|
|
23
|
-
const file = resolvePath(ctx.cwd, call);
|
|
24
|
-
await mkdir(dirname(file), { recursive: true });
|
|
25
|
-
await writeFile(file, requiredString(call, "content"), "utf8");
|
|
26
|
-
return { ok: true, output: `wrote ${file}`, sideEffects: { touched: [file] } };
|
|
27
|
-
},
|
|
28
|
-
};
|
package/src/commands/attach.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { pollShellSession } from "../agent/shell-session.js";
|
|
2
|
-
|
|
3
|
-
export const attachCommand = {
|
|
4
|
-
name: "attach",
|
|
5
|
-
description: "Show new output from a background shell session (/attach <id>)",
|
|
6
|
-
async run({ args }) {
|
|
7
|
-
const id = args[0];
|
|
8
|
-
if (!id)
|
|
9
|
-
return { message: "Usage: /attach <session-id> (see /jobs)" };
|
|
10
|
-
const result = await pollShellSession(id, 0);
|
|
11
|
-
if (!result)
|
|
12
|
-
return { message: `Unknown session: ${id}` };
|
|
13
|
-
const status = result.status === "running" ? "running" : `${result.status} (exit ${result.exitCode ?? "?"})`;
|
|
14
|
-
return { message: `[session ${id}] ${status}\n${result.output || "(no new output)"}` };
|
|
15
|
-
},
|
|
16
|
-
};
|
package/src/commands/bg.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const bgCommand = {
|
|
2
|
-
name: "bg",
|
|
3
|
-
description: "Explain backgrounding (long shell commands auto-background after ~2s)",
|
|
4
|
-
run() {
|
|
5
|
-
return {
|
|
6
|
-
message: "Long shell commands already return a session id after ~2s; use /jobs to list them, /attach <id> for new output, /kill <id> to stop.",
|
|
7
|
-
};
|
|
8
|
-
},
|
|
9
|
-
};
|
package/src/commands/cancel.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const cancelCommand = {
|
|
2
|
-
name: "cancel",
|
|
3
|
-
description: "Cancel the active agent run (soft keyboard alternative to Esc)",
|
|
4
|
-
run({ state, actions }) {
|
|
5
|
-
if (!state.busy)
|
|
6
|
-
return { message: "Nothing is running." };
|
|
7
|
-
actions.cancelRun();
|
|
8
|
-
return { message: "Cancelling the active run…" };
|
|
9
|
-
},
|
|
10
|
-
};
|
package/src/commands/compact.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { compactMessages, DEFAULT_COMPACTION_CONFIG } from "../agent/compaction.js";
|
|
2
|
-
import { getModelMeta } from "../lib/model-meta.js";
|
|
3
|
-
|
|
4
|
-
export const compactCommand = {
|
|
5
|
-
name: "compact",
|
|
6
|
-
description: "Force local context compaction now",
|
|
7
|
-
run({ state, actions }) {
|
|
8
|
-
const meta = getModelMeta(state.providerId, state.model);
|
|
9
|
-
const result = compactMessages(state.history, { ...DEFAULT_COMPACTION_CONFIG, localThresholdRatio: 0 }, {
|
|
10
|
-
contextWindow: meta.contextWindow,
|
|
11
|
-
providerId: state.providerId,
|
|
12
|
-
model: state.model,
|
|
13
|
-
force: true,
|
|
14
|
-
});
|
|
15
|
-
if (!result.compacted)
|
|
16
|
-
return { message: "Nothing to compact (history is already small)." };
|
|
17
|
-
actions.replaceHistory(result.messages);
|
|
18
|
-
return {
|
|
19
|
-
message: `[context compacted] ${result.beforeTokens} → ${result.afterTokens} tokens (${result.droppedMessages} messages summarized).` +
|
|
20
|
-
(result.summaryFile ? `\nSummary: ${result.summaryFile}` : ""),
|
|
21
|
-
};
|
|
22
|
-
},
|
|
23
|
-
};
|
package/src/commands/context.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_COMPACTION_CONFIG, heapExceeded, localThresholdTokens } from "../agent/compaction.js";
|
|
2
|
-
import { estMessagesTokens, getModelMeta } from "../lib/model-meta.js";
|
|
3
|
-
|
|
4
|
-
export const contextCommand = {
|
|
5
|
-
name: "context",
|
|
6
|
-
description: "Show estimated context tokens, compaction threshold, and heap usage",
|
|
7
|
-
run(ctx) {
|
|
8
|
-
const meta = getModelMeta(ctx.state.providerId, ctx.state.model);
|
|
9
|
-
const tokens = estMessagesTokens(ctx.state.history, {
|
|
10
|
-
providerId: ctx.state.providerId,
|
|
11
|
-
model: ctx.state.model,
|
|
12
|
-
});
|
|
13
|
-
const threshold = localThresholdTokens(DEFAULT_COMPACTION_CONFIG, meta.contextWindow);
|
|
14
|
-
const percent = meta.contextWindow > 0 ? (tokens / meta.contextWindow) * 100 : 0;
|
|
15
|
-
const heapMb = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
16
|
-
return {
|
|
17
|
-
message: [
|
|
18
|
-
`Context: ~${tokens.toLocaleString()} / ${meta.contextWindow.toLocaleString()} tokens (${percent.toFixed(1)}%)`,
|
|
19
|
-
`Compaction threshold: ${threshold.toLocaleString()} tokens (${Math.round(DEFAULT_COMPACTION_CONFIG.localThresholdRatio * 100)}%)`,
|
|
20
|
-
`Heap: ${heapMb.toFixed(1)} MB / ${DEFAULT_COMPACTION_CONFIG.heapLimitMb} MB${heapExceeded(DEFAULT_COMPACTION_CONFIG) ? " [forced compaction]" : ""}`,
|
|
21
|
-
`Messages: ${ctx.state.history.length} · chars/token: ~${meta.charsPerToken}`,
|
|
22
|
-
].join("\n"),
|
|
23
|
-
};
|
|
24
|
-
},
|
|
25
|
-
};
|
package/src/commands/edit.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
|
|
6
|
-
export const editCommand = {
|
|
7
|
-
name: "edit",
|
|
8
|
-
description: "Edit the prompt in $EDITOR (works around Ink IME issues on Termux)",
|
|
9
|
-
run({ state, actions }) {
|
|
10
|
-
const file = join(tmpdir(), `fastcode-edit-${Date.now()}.md`);
|
|
11
|
-
writeFileSync(file, state.draft ?? "", "utf8");
|
|
12
|
-
const editor = process.env["EDITOR"] || process.env["VISUAL"] || "nano";
|
|
13
|
-
const wasRaw = Boolean(process.stdin.isTTY && process.stdin.isRaw);
|
|
14
|
-
try {
|
|
15
|
-
if (wasRaw)
|
|
16
|
-
process.stdin.setRawMode(false);
|
|
17
|
-
const result = spawnSync(editor, [file], { stdio: "inherit" });
|
|
18
|
-
if (result.error)
|
|
19
|
-
return { message: `Could not launch ${editor}: ${result.error.message}` };
|
|
20
|
-
const text = readFileSync(file, "utf8").trim();
|
|
21
|
-
if (!text)
|
|
22
|
-
return { message: "Editor closed with no text." };
|
|
23
|
-
actions.setInput(text);
|
|
24
|
-
return { message: "Draft loaded into the prompt; press Enter to send." };
|
|
25
|
-
}
|
|
26
|
-
finally {
|
|
27
|
-
if (wasRaw)
|
|
28
|
-
process.stdin.setRawMode(true);
|
|
29
|
-
try {
|
|
30
|
-
unlinkSync(file);
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
// temp file may already be gone
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
};
|
package/src/commands/effort.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { getProvider } from "../providers/index.js";
|
|
2
|
-
import type { ReasoningEffort } from "../types.js";
|
|
3
|
-
const EFFORTS: ReasoningEffort[] = ["auto", "low", "medium", "high", "max"];
|
|
4
|
-
const HINTS: Record<ReasoningEffort, string> = {
|
|
5
|
-
auto: "provider default (send nothing)",
|
|
6
|
-
low: "fast, minimal thinking",
|
|
7
|
-
medium: "balanced",
|
|
8
|
-
high: "deeper reasoning, slower",
|
|
9
|
-
max: "maximum budget where supported",
|
|
10
|
-
};
|
|
11
|
-
export const effortCommand = {
|
|
12
|
-
name: "effort",
|
|
13
|
-
description: "Set thinking effort (auto/low/medium/high/max). Usage: /effort [level]",
|
|
14
|
-
run({ args, state, actions }) {
|
|
15
|
-
const provider = getProvider(state.providerId);
|
|
16
|
-
const supported = provider?.supportsReasoning?.(state.model) ?? false;
|
|
17
|
-
const current = (state.reasoningEffort ?? "auto");
|
|
18
|
-
const apply = (value: ReasoningEffort) => {
|
|
19
|
-
actions.setReasoningEffort(value);
|
|
20
|
-
return describe(value, provider, supported);
|
|
21
|
-
};
|
|
22
|
-
if (args.length > 0) {
|
|
23
|
-
const value = args[0].toLowerCase();
|
|
24
|
-
if (!EFFORTS.includes(value as ReasoningEffort)) {
|
|
25
|
-
return { message: `Unknown effort "${args[0]}". Choose: ${EFFORTS.join(", ")}.` };
|
|
26
|
-
}
|
|
27
|
-
return { message: apply(value as ReasoningEffort) };
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
message: `Thinking effort: ${current}${supported ? "" : " (this provider has no thinking parameter)"}`,
|
|
31
|
-
picker: {
|
|
32
|
-
title: `Thinking effort · ${provider?.label ?? state.providerId}`,
|
|
33
|
-
current,
|
|
34
|
-
items: EFFORTS.map((value) => ({ value, label: value, hint: HINTS[value] })),
|
|
35
|
-
onSelect: (value) => actions.pushSystemMessage(apply(value as ReasoningEffort)),
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
function describe(value, provider, supported) {
|
|
41
|
-
if (value === "auto") {
|
|
42
|
-
return "Thinking effort: auto — the provider's default is used (no thinking parameter is sent).";
|
|
43
|
-
}
|
|
44
|
-
if (!supported) {
|
|
45
|
-
return `Thinking effort saved as ${value}, but ${provider?.label ?? "this provider"} does not expose a thinking parameter; ` +
|
|
46
|
-
"requests will omit it. Switch to a reasoning-capable model/provider to use it.";
|
|
47
|
-
}
|
|
48
|
-
return `Thinking effort: ${value}. The next request will carry the provider-specific thinking parameter.`;
|
|
49
|
-
}
|
package/src/commands/expand.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export const expandCommand = {
|
|
2
|
-
name: "expand",
|
|
3
|
-
description: "Toggle full tool output in the transcript (stable UI defaults to collapsed)",
|
|
4
|
-
run({ state, actions }) {
|
|
5
|
-
actions.setExpanded(!state.expanded);
|
|
6
|
-
return { message: state.expanded ? "Tool output: collapsed." : "Tool output: expanded (new output only)." };
|
|
7
|
-
},
|
|
8
|
-
};
|
package/src/commands/jobs.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { listShellSessions } from "../agent/shell-session.js";
|
|
2
|
-
|
|
3
|
-
export const jobsCommand = {
|
|
4
|
-
name: "jobs",
|
|
5
|
-
description: "List background shell sessions",
|
|
6
|
-
run() {
|
|
7
|
-
const jobs = listShellSessions();
|
|
8
|
-
if (jobs.length === 0)
|
|
9
|
-
return { message: "No shell sessions. Long commands return a session id automatically." };
|
|
10
|
-
const lines = jobs.map((job) => {
|
|
11
|
-
const exit = job.exitCode === undefined || job.exitCode === null ? "" : ` exit=${job.exitCode}`;
|
|
12
|
-
const command = job.command.length > 80 ? job.command.slice(0, 77) + "…" : job.command;
|
|
13
|
-
return `${job.id} ${job.status}${exit} ${(job.bytes / 1024).toFixed(1)}KB ${command}`;
|
|
14
|
-
});
|
|
15
|
-
return { message: ["Shell sessions:", ...lines, "", "Kill one with: /kill <id>"].join("\n") };
|
|
16
|
-
},
|
|
17
|
-
};
|
package/src/commands/kill.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { killShellSession } from "../agent/shell-session.js";
|
|
2
|
-
|
|
3
|
-
export const killCommand = {
|
|
4
|
-
name: "kill",
|
|
5
|
-
description: "Kill a background shell session (/kill <id>)",
|
|
6
|
-
run(ctx) {
|
|
7
|
-
const id = ctx.args[0];
|
|
8
|
-
if (!id)
|
|
9
|
-
return { message: "Usage: /kill <session-id> (see /jobs)" };
|
|
10
|
-
return { message: killShellSession(id) ? `Killed ${id} (process tree).` : `No running session named ${id}.` };
|
|
11
|
-
},
|
|
12
|
-
};
|
package/src/commands/steer.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const steerCommand = {
|
|
2
|
-
name: "steer",
|
|
3
|
-
description: "Add guidance to the next request of an active run (/steer <text>)",
|
|
4
|
-
run({ args, state, actions }) {
|
|
5
|
-
const text = args.join(" ").trim();
|
|
6
|
-
if (!text)
|
|
7
|
-
return { message: "Usage: /steer <guidance>" };
|
|
8
|
-
if (!state.busy)
|
|
9
|
-
return { message: "No active run. Just send the guidance as the next message." };
|
|
10
|
-
actions.steer(text);
|
|
11
|
-
return { message: "Steering queued for the next request." };
|
|
12
|
-
},
|
|
13
|
-
};
|
package/src/lib/model-meta.ts
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
export interface ModelMeta {
|
|
6
|
-
contextWindow: number;
|
|
7
|
-
supportsTools: boolean;
|
|
8
|
-
charsPerToken: number;
|
|
9
|
-
maxOutputTokens?: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface EstTokenOptions {
|
|
13
|
-
providerId?: string;
|
|
14
|
-
model?: string;
|
|
15
|
-
charsPerToken?: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const UNKNOWN_MODEL_META: ModelMeta = {
|
|
19
|
-
contextWindow: 32_768,
|
|
20
|
-
supportsTools: false,
|
|
21
|
-
charsPerToken: 2.5,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const PROVIDER_META: Record<string, ModelMeta> = {
|
|
25
|
-
anthropic: { contextWindow: 1_000_000, supportsTools: true, charsPerToken: 3.8, maxOutputTokens: 64_000 },
|
|
26
|
-
openai: { contextWindow: 400_000, supportsTools: true, charsPerToken: 3.8, maxOutputTokens: 32_000 },
|
|
27
|
-
google: { contextWindow: 1_048_576, supportsTools: true, charsPerToken: 3.6, maxOutputTokens: 65_536 },
|
|
28
|
-
deepseek: { contextWindow: 128_000, supportsTools: true, charsPerToken: 1.7, maxOutputTokens: 8_192 },
|
|
29
|
-
openrouter: { contextWindow: 128_000, supportsTools: true, charsPerToken: 2.5, maxOutputTokens: 16_384 },
|
|
30
|
-
groq: { contextWindow: 128_000, supportsTools: true, charsPerToken: 3.8, maxOutputTokens: 8_192 },
|
|
31
|
-
mistral: { contextWindow: 128_000, supportsTools: true, charsPerToken: 3.8, maxOutputTokens: 8_192 },
|
|
32
|
-
xai: { contextWindow: 256_000, supportsTools: true, charsPerToken: 3.8, maxOutputTokens: 16_384 },
|
|
33
|
-
moonshot: { contextWindow: 256_000, supportsTools: true, charsPerToken: 2.0, maxOutputTokens: 16_384 },
|
|
34
|
-
zhipu: { contextWindow: 128_000, supportsTools: true, charsPerToken: 1.7, maxOutputTokens: 8_192 },
|
|
35
|
-
qwen: { contextWindow: 128_000, supportsTools: true, charsPerToken: 1.7, maxOutputTokens: 8_192 },
|
|
36
|
-
ollama: { contextWindow: 32_768, supportsTools: true, charsPerToken: 2.5, maxOutputTokens: 4_096 },
|
|
37
|
-
custom: { contextWindow: 32_768, supportsTools: false, charsPerToken: 2.5 },
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const MODEL_OVERRIDES: Record<string, Partial<ModelMeta>> = {
|
|
41
|
-
"claude-haiku-5.5": { contextWindow: 200_000 },
|
|
42
|
-
"claude-haiku-4.5": { contextWindow: 200_000 },
|
|
43
|
-
"claude-sonnet-5": { contextWindow: 1_000_000 },
|
|
44
|
-
"claude-opus-5": { contextWindow: 1_000_000 },
|
|
45
|
-
"claude-sonnet-4.6": { contextWindow: 1_000_000 },
|
|
46
|
-
"claude-opus-4.6": { contextWindow: 1_000_000 },
|
|
47
|
-
"gpt-4o": { contextWindow: 128_000 },
|
|
48
|
-
"gpt-4o-mini": { contextWindow: 128_000 },
|
|
49
|
-
"gpt-4.1": { contextWindow: 1_000_000 },
|
|
50
|
-
o3: { contextWindow: 200_000 },
|
|
51
|
-
"o4-mini": { contextWindow: 200_000 },
|
|
52
|
-
"gemini-3.5-flash-lite": { contextWindow: 1_048_576 },
|
|
53
|
-
"gemini-3.1-flash-lite": { contextWindow: 1_048_576 },
|
|
54
|
-
"deepseek-v4-pro": { contextWindow: 128_000, charsPerToken: 1.7 },
|
|
55
|
-
"deepseek-flash": { contextWindow: 128_000, charsPerToken: 1.7 },
|
|
56
|
-
"glm-5.3": { contextWindow: 128_000, charsPerToken: 1.7 },
|
|
57
|
-
"glm-5.2": { contextWindow: 128_000, charsPerToken: 1.7 },
|
|
58
|
-
"qwen3.8-max": { contextWindow: 128_000, charsPerToken: 1.7 },
|
|
59
|
-
"qwen3.8-flash": { contextWindow: 128_000, charsPerToken: 1.7 },
|
|
60
|
-
"kimi-k3": { contextWindow: 256_000, charsPerToken: 2.0 },
|
|
61
|
-
"grok-4.7": { contextWindow: 256_000, charsPerToken: 3.8 },
|
|
62
|
-
"mistral-large-latest": { contextWindow: 128_000, charsPerToken: 3.8 },
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
let overrideCache: Record<string, Partial<ModelMeta>> | undefined;
|
|
66
|
-
|
|
67
|
-
export function modelMetaOverridePath(): string {
|
|
68
|
-
const root = process.env["FASTCODE_HOME"] ?? join(homedir(), ".fastcode");
|
|
69
|
-
return join(root, "model-meta.json");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function clearModelMetaCache(): void {
|
|
73
|
-
overrideCache = undefined;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function loadOverrides(): Record<string, Partial<ModelMeta>> {
|
|
77
|
-
if (overrideCache)
|
|
78
|
-
return overrideCache;
|
|
79
|
-
const file = modelMetaOverridePath();
|
|
80
|
-
if (!existsSync(file)) {
|
|
81
|
-
overrideCache = {};
|
|
82
|
-
return overrideCache;
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
86
|
-
overrideCache = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
overrideCache = {};
|
|
90
|
-
}
|
|
91
|
-
return overrideCache;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function usable(meta: Partial<ModelMeta> | undefined): meta is Partial<ModelMeta> {
|
|
95
|
-
return Boolean(meta) && typeof meta === "object";
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function apply(base: ModelMeta, ...layers: Array<Partial<ModelMeta> | undefined>): ModelMeta {
|
|
99
|
-
const next = { ...base };
|
|
100
|
-
for (const layer of layers) {
|
|
101
|
-
if (!usable(layer))
|
|
102
|
-
continue;
|
|
103
|
-
if (typeof layer.contextWindow === "number" && layer.contextWindow > 0)
|
|
104
|
-
next.contextWindow = Math.floor(layer.contextWindow);
|
|
105
|
-
if (typeof layer.charsPerToken === "number" && layer.charsPerToken > 0)
|
|
106
|
-
next.charsPerToken = layer.charsPerToken;
|
|
107
|
-
if (typeof layer.supportsTools === "boolean")
|
|
108
|
-
next.supportsTools = layer.supportsTools;
|
|
109
|
-
if (typeof layer.maxOutputTokens === "number" && layer.maxOutputTokens > 0)
|
|
110
|
-
next.maxOutputTokens = Math.floor(layer.maxOutputTokens);
|
|
111
|
-
}
|
|
112
|
-
return next;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function getModelMeta(providerId?: string, model?: string): ModelMeta {
|
|
116
|
-
const provider = providerId && PROVIDER_META[providerId] ? PROVIDER_META[providerId] : UNKNOWN_MODEL_META;
|
|
117
|
-
const overrides = loadOverrides();
|
|
118
|
-
const keys = [
|
|
119
|
-
providerId && model ? `${providerId}/${model}` : undefined,
|
|
120
|
-
providerId && model ? `${providerId}::${model}` : undefined,
|
|
121
|
-
model,
|
|
122
|
-
].filter((key): key is string => Boolean(key));
|
|
123
|
-
const layers = keys.map((key) => overrides[key]);
|
|
124
|
-
return apply(provider, model ? MODEL_OVERRIDES[model] : undefined, ...layers);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function estTokens(text: string, options: number | EstTokenOptions = {}): number {
|
|
128
|
-
if (!text)
|
|
129
|
-
return 0;
|
|
130
|
-
const ratio = typeof options === "number"
|
|
131
|
-
? options
|
|
132
|
-
: options.charsPerToken ?? getModelMeta(options.providerId, options.model).charsPerToken;
|
|
133
|
-
return Math.ceil(text.length / Math.max(0.1, ratio));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function estMessagesTokens(messages: Array<{ content: string }>, options: EstTokenOptions = {}): number {
|
|
137
|
-
return messages.reduce((sum, message) => sum + estTokens(message.content ?? "", options), 0);
|
|
138
|
-
}
|
package/src/lib/native-tools.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { NativeToolCall } from "../types.js";
|
|
2
|
-
|
|
3
|
-
export type ToolCallAccumulator = Map<number, NativeToolCall>;
|
|
4
|
-
|
|
5
|
-
export interface ToolCallDelta {
|
|
6
|
-
index?: number;
|
|
7
|
-
id?: string;
|
|
8
|
-
function?: { name?: string; arguments?: string };
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function mergeToolCallDelta(accumulator: ToolCallAccumulator, delta: ToolCallDelta): void {
|
|
12
|
-
const index = typeof delta.index === "number" && Number.isFinite(delta.index) ? delta.index : accumulator.size;
|
|
13
|
-
const entry = accumulator.get(index) ?? { id: "", name: "", arguments: "" };
|
|
14
|
-
if (typeof delta.id === "string" && delta.id)
|
|
15
|
-
entry.id = delta.id;
|
|
16
|
-
if (typeof delta.function?.name === "string" && delta.function.name)
|
|
17
|
-
entry.name = delta.function.name;
|
|
18
|
-
if (typeof delta.function?.arguments === "string")
|
|
19
|
-
entry.arguments += delta.function.arguments;
|
|
20
|
-
accumulator.set(index, entry);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function finalizeToolCalls(accumulator: ToolCallAccumulator): NativeToolCall[] {
|
|
24
|
-
return Array.from(accumulator.entries())
|
|
25
|
-
.sort((a, b) => a[0] - b[0])
|
|
26
|
-
.filter(([, call]) => Boolean(call.name))
|
|
27
|
-
.map(([index, call]) => ({
|
|
28
|
-
id: call.id || `call_${index}`,
|
|
29
|
-
name: call.name,
|
|
30
|
-
arguments: call.arguments || "{}",
|
|
31
|
-
}));
|
|
32
|
-
}
|