@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
package/dist/types.d.ts
CHANGED
|
@@ -5,26 +5,10 @@
|
|
|
5
5
|
* what the chat loop needs (streaming completions, model list, auth).
|
|
6
6
|
* Providers can layer richer behavior on top in their own modules.
|
|
7
7
|
*/
|
|
8
|
-
export type Role = "system" | "user" | "assistant"
|
|
9
|
-
export type ReasoningEffort = "auto" | "low" | "medium" | "high" | "max";
|
|
10
|
-
export interface NativeToolCall {
|
|
11
|
-
id: string;
|
|
12
|
-
name: string;
|
|
13
|
-
arguments: string;
|
|
14
|
-
}
|
|
15
|
-
export interface ToolSchema {
|
|
16
|
-
type: "function";
|
|
17
|
-
function: {
|
|
18
|
-
name: string;
|
|
19
|
-
description: string;
|
|
20
|
-
parameters: Record<string, any>;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
8
|
+
export type Role = "system" | "user" | "assistant";
|
|
23
9
|
export interface ChatMessage {
|
|
24
10
|
role: Role;
|
|
25
11
|
content: string;
|
|
26
|
-
toolCalls?: NativeToolCall[];
|
|
27
|
-
toolCallId?: string;
|
|
28
12
|
}
|
|
29
13
|
export interface ChatRequest {
|
|
30
14
|
model: string;
|
|
@@ -35,26 +19,14 @@ export interface ChatRequest {
|
|
|
35
19
|
temperature?: number;
|
|
36
20
|
/** Soft cap for output tokens. */
|
|
37
21
|
maxOutputTokens?: number;
|
|
38
|
-
/**
|
|
39
|
-
* Requested thinking depth. Providers that support it map this to their
|
|
40
|
-
* native parameter (`reasoning_effort`, `thinking.budget_tokens`, …);
|
|
41
|
-
* providers that don't should ignore it.
|
|
42
|
-
*/
|
|
43
|
-
reasoningEffort?: ReasoningEffort;
|
|
44
22
|
/** AbortSignal for cancellation (Esc / Ctrl+C). */
|
|
45
23
|
signal?: AbortSignal;
|
|
46
|
-
/** Stable idempotency key reused across retries of the same logical request. */
|
|
47
|
-
clientRequestId?: string;
|
|
48
|
-
/** Native function-calling schemas (auto mode only). */
|
|
49
|
-
tools?: ToolSchema[];
|
|
50
24
|
}
|
|
51
25
|
export interface ChatChunk {
|
|
52
26
|
/** Token text appended to the response. */
|
|
53
27
|
delta: string;
|
|
54
28
|
/** True on the final chunk. */
|
|
55
29
|
done: boolean;
|
|
56
|
-
/** Complete native tool calls (OpenAI-style) on the final chunk. */
|
|
57
|
-
toolCalls?: NativeToolCall[];
|
|
58
30
|
/** Provider-specific usage info on the final chunk. */
|
|
59
31
|
usage?: {
|
|
60
32
|
inputTokens?: number;
|
|
@@ -91,25 +63,6 @@ export interface Provider {
|
|
|
91
63
|
listModels(apiKey: string | undefined): Promise<ProviderModel[]>;
|
|
92
64
|
/** Stream a chat completion. */
|
|
93
65
|
stream(req: ChatRequest, apiKey: string | undefined): ChatStream;
|
|
94
|
-
/** Whether this provider/model honors ChatRequest.reasoningEffort. */
|
|
95
|
-
supportsReasoning?(model: string): boolean;
|
|
96
|
-
}
|
|
97
|
-
export interface PickerItem {
|
|
98
|
-
value: string;
|
|
99
|
-
label: string;
|
|
100
|
-
hint?: string;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* An interactive list a command can hand back to the app. The app renders it
|
|
104
|
-
* with arrow keys, number shortcuts, and Enter (Esc cancels).
|
|
105
|
-
*/
|
|
106
|
-
export interface PickerRequest {
|
|
107
|
-
title: string;
|
|
108
|
-
items: PickerItem[];
|
|
109
|
-
/** Currently selected value, highlighted on open. */
|
|
110
|
-
current?: string;
|
|
111
|
-
onSelect(value: string, item: PickerItem): void;
|
|
112
|
-
onCancel?(): void;
|
|
113
66
|
}
|
|
114
67
|
export interface SlashCommand {
|
|
115
68
|
name: string;
|
|
@@ -128,8 +81,6 @@ export interface CommandResult {
|
|
|
128
81
|
silent?: boolean;
|
|
129
82
|
/** Quit the app after this command. */
|
|
130
83
|
quit?: boolean;
|
|
131
|
-
/** Open an interactive picker after the command runs. */
|
|
132
|
-
picker?: PickerRequest;
|
|
133
84
|
}
|
|
134
85
|
export interface CommandContext {
|
|
135
86
|
args: string[];
|
|
@@ -150,10 +101,6 @@ export interface AppStateSnapshot {
|
|
|
150
101
|
enabledSkills: string[];
|
|
151
102
|
enabledPlugins: string[];
|
|
152
103
|
skillsRegistry: string;
|
|
153
|
-
reasoningEffort: ReasoningEffort;
|
|
154
|
-
expanded: boolean;
|
|
155
|
-
busy: boolean;
|
|
156
|
-
draft: string;
|
|
157
104
|
}
|
|
158
105
|
export interface AppActions {
|
|
159
106
|
setProvider(id: string): void;
|
|
@@ -162,17 +109,11 @@ export interface AppActions {
|
|
|
162
109
|
setAgentMode(enabled: boolean): void;
|
|
163
110
|
setSystemPrompt(prompt: string): void;
|
|
164
111
|
setSkillsRegistry(url: string): void;
|
|
165
|
-
setReasoningEffort(effort: ReasoningEffort): void;
|
|
166
112
|
enableSkill(name: string): void;
|
|
167
113
|
disableSkill(name: string): void;
|
|
168
114
|
enablePlugin(name: string): void;
|
|
169
115
|
disablePlugin(name: string): void;
|
|
170
116
|
clearHistory(): void;
|
|
171
|
-
replaceHistory(messages: ChatMessage[]): void;
|
|
172
|
-
cancelRun(): void;
|
|
173
|
-
steer(text: string): void;
|
|
174
|
-
setExpanded(value: boolean): void;
|
|
175
|
-
setInput(text: string): void;
|
|
176
117
|
pushSystemMessage(text: string): void;
|
|
177
118
|
/** Begin the guided API-key flow (choose provider → model → key). */
|
|
178
119
|
startLogin(options: {
|
package/dist/ui/Message.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
export declare const MessageBubble: ({ theme, role, content, streaming, markdown }:
|
|
1
|
+
export declare const MessageBubble: ({ theme, role, content, streaming, markdown, }: {
|
|
2
|
+
theme: any;
|
|
3
|
+
role: any;
|
|
4
|
+
content: any;
|
|
5
|
+
streaming: any;
|
|
6
|
+
markdown: any;
|
|
7
|
+
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
package/dist/ui/Message.js
CHANGED
|
@@ -6,19 +6,8 @@ const SIGIL = {
|
|
|
6
6
|
assistant: "▍ FastCode",
|
|
7
7
|
system: "✦ system",
|
|
8
8
|
};
|
|
9
|
-
const
|
|
10
|
-
function cachedMarkdown(md) {
|
|
11
|
-
const hit = markdownCache.get(md);
|
|
12
|
-
if (hit !== undefined)
|
|
13
|
-
return hit;
|
|
14
|
-
const rendered = renderMarkdown(md);
|
|
15
|
-
if (markdownCache.size > 200)
|
|
16
|
-
markdownCache.clear();
|
|
17
|
-
markdownCache.set(md, rendered);
|
|
18
|
-
return rendered;
|
|
19
|
-
}
|
|
20
|
-
export const MessageBubble = ({ theme, role, content, streaming, markdown }) => {
|
|
9
|
+
export const MessageBubble = ({ theme, role, content, streaming, markdown, }) => {
|
|
21
10
|
const color = role === "user" ? theme.user : role === "assistant" ? theme.assistant : theme.system;
|
|
22
|
-
const display = markdown ?
|
|
11
|
+
const display = markdown ? renderMarkdown(content) : content;
|
|
23
12
|
return (_jsxs(Box, { flexDirection: "column", marginY: 0, children: [_jsxs(Text, { color: color, bold: true, children: [SIGIL[role], streaming ? _jsx(Text, { color: theme.muted, children: " (streaming)" }) : null] }), _jsx(Box, { marginLeft: 2, flexDirection: "column", children: _jsx(Text, { color: color, children: display || (streaming ? "…" : "") }) })] }));
|
|
24
13
|
};
|
package/dist/ui/Prompt.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export declare const Prompt: ({ theme, value, onChange, onSubmit, disabled, placeholder, mask, }: {
|
|
1
|
+
export declare const Prompt: ({ theme, value, onChange, onSubmit, disabled, placeholder, stable, mask, }: {
|
|
2
2
|
theme: any;
|
|
3
3
|
value: any;
|
|
4
4
|
onChange: any;
|
|
5
5
|
onSubmit: any;
|
|
6
6
|
disabled: any;
|
|
7
7
|
placeholder: any;
|
|
8
|
+
stable?: boolean;
|
|
8
9
|
mask: any;
|
|
9
10
|
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
package/dist/ui/Prompt.js
CHANGED
|
@@ -15,9 +15,9 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
|
15
15
|
import { Box, Text } from "ink";
|
|
16
16
|
import TextInput from "ink-text-input";
|
|
17
17
|
import { COMMANDS } from "../commands/index.js";
|
|
18
|
-
export const Prompt = ({ theme, value, onChange, onSubmit, disabled, placeholder, mask, }) => {
|
|
18
|
+
export const Prompt = ({ theme, value, onChange, onSubmit, disabled, placeholder, stable = false, mask, }) => {
|
|
19
19
|
const suggestion = autocomplete(value);
|
|
20
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: disabled ? theme.muted : theme.accent, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: theme.accent, bold: true, children: "\u276F " }), disabled ? (_jsx(Text, { color: theme.muted, children: placeholder ?? "Working… (Esc to cancel)" })) : (_jsx(TextInput, { value: value, onChange: onChange, onSubmit: onSubmit, placeholder: placeholder ?? "Type a message or /help …", showCursor:
|
|
20
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: disabled ? theme.muted : theme.accent, paddingX: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: theme.accent, bold: true, children: "\u276F " }), disabled ? (_jsx(Text, { color: theme.muted, children: placeholder ?? "Working… (Esc to cancel)" })) : (_jsx(TextInput, { value: value, onChange: onChange, onSubmit: onSubmit, placeholder: placeholder ?? "Type a message or /help …", showCursor: !stable, mask: mask }))] }), !disabled && suggestion ? (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: theme.muted, children: ["\u21AA ", suggestion] }) })) : null] }));
|
|
21
21
|
};
|
|
22
22
|
function autocomplete(value) {
|
|
23
23
|
if (!value.startsWith("/") || value.includes(" "))
|
package/dist/ui/Spinner.js
CHANGED
|
@@ -21,19 +21,13 @@ const VERBS = [
|
|
|
21
21
|
];
|
|
22
22
|
export const Spinner = ({ theme, label, stable = false }) => {
|
|
23
23
|
const [tick, setTick] = useState(0);
|
|
24
|
-
// stable UI only lowers the redraw rate; it must still animate. A frozen
|
|
25
|
-
// frame made long waits look like a hang.
|
|
26
|
-
const configured = Number(process.env["FASTCODE_SPINNER_MS"]);
|
|
27
|
-
const interval = Number.isFinite(configured) && configured >= 60
|
|
28
|
-
? configured
|
|
29
|
-
: stable
|
|
30
|
-
? 120
|
|
31
|
-
: 80;
|
|
32
24
|
useEffect(() => {
|
|
33
|
-
|
|
25
|
+
if (stable)
|
|
26
|
+
return;
|
|
27
|
+
const id = setInterval(() => setTick((t) => t + 1), 80);
|
|
34
28
|
return () => clearInterval(id);
|
|
35
|
-
}, [
|
|
36
|
-
const frame = FRAMES[tick % FRAMES.length];
|
|
29
|
+
}, [stable]);
|
|
30
|
+
const frame = stable ? "⠋" : FRAMES[tick % FRAMES.length];
|
|
37
31
|
const verb = label ?? VERBS[Math.floor(tick / 24) % VERBS.length];
|
|
38
32
|
return (_jsxs(Text, { color: theme.accent, children: [frame, " ", _jsxs(Text, { color: theme.muted, children: [verb, "\u2026"] })] }));
|
|
39
33
|
};
|
package/dist/ui/StatusBar.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const StatusBar: ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount,
|
|
1
|
+
export declare const StatusBar: ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount, hint, }: {
|
|
2
2
|
theme: any;
|
|
3
3
|
providerId: any;
|
|
4
4
|
model: any;
|
|
@@ -6,6 +6,5 @@ export declare const StatusBar: ({ theme, providerId, model, inputTokens, output
|
|
|
6
6
|
outputTokens: any;
|
|
7
7
|
costUsd: any;
|
|
8
8
|
enabledSkillCount: any;
|
|
9
|
-
reasoningEffort: any;
|
|
10
9
|
hint: any;
|
|
11
10
|
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
package/dist/ui/StatusBar.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text, useStdout } from "ink";
|
|
3
3
|
import { platformLabel } from "../lib/platform.js";
|
|
4
|
-
export const StatusBar = ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount,
|
|
4
|
+
export const StatusBar = ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount, hint, }) => {
|
|
5
5
|
const { stdout } = useStdout();
|
|
6
6
|
const columns = stdout?.columns ?? process.stdout.columns ?? 80;
|
|
7
7
|
const compact = columns < 88;
|
|
8
8
|
const cost = costUsd > 0 ? `$${costUsd.toFixed(4)}` : "$0.0000";
|
|
9
9
|
const providerModel = `${providerId}/${model}`;
|
|
10
10
|
const label = compact ? truncate(providerModel, Math.max(18, columns - 28)) : providerModel;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
: hint ?? "/help \u00B7 esc cancel \u00B7 ctrl+c quit" })] }));
|
|
11
|
+
return (_jsxs(Box, { flexDirection: compact ? "column" : "row", justifyContent: "space-between", borderStyle: "round", borderColor: theme.border, paddingX: 1, children: [_jsxs(Text, { color: theme.muted, children: [_jsx(Text, { color: theme.accent, children: "\u25CF" }), " ", label, _jsx(Text, { color: theme.muted, children: " \u00B7 " }), inputTokens, "\u2191 ", outputTokens, "\u2193 ", cost, !compact ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.muted, children: " \u00B7 " }), "skills: ", enabledSkillCount, _jsx(Text, { color: theme.muted, children: " \u00B7 " }), platformLabel()] })) : null] }), _jsx(Text, { color: theme.muted, children: compact
|
|
12
|
+
? `${platformLabel()} · skills:${enabledSkillCount} · ${hint ?? "/help · esc · ctrl+c"}`
|
|
13
|
+
: hint ?? "/help · esc cancel · ctrl+c quit" })] }));
|
|
15
14
|
};
|
|
16
15
|
function truncate(value, max) {
|
|
17
16
|
if (value.length <= max)
|
|
18
17
|
return value;
|
|
19
|
-
return `${value.slice(0, Math.max(1, max - 1))}
|
|
18
|
+
return `${value.slice(0, Math.max(1, max - 1))}…`;
|
|
20
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datename/fastcode-termux",
|
|
3
|
-
"version": "0.1.6
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "FastCode — a blazing-fast TUI coding assistant. Multi-LLM, skills.sh skills, slash commands. Works on Termux, Linux, Windows, and macOS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/agent/guards.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { normalize, resolve } from "node:path";
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Dangerous-command guard.
|
|
5
3
|
*
|
|
@@ -74,197 +72,3 @@ export function evaluateShellCommand(command) {
|
|
|
74
72
|
}
|
|
75
73
|
return { allow: true, output: undefined };
|
|
76
74
|
}
|
|
77
|
-
export const READ_ONLY_TOOLS = new Set([
|
|
78
|
-
"pwd", "read_file", "read_many", "list_files", "grep", "stat_path",
|
|
79
|
-
]);
|
|
80
|
-
const READ_ONLY_COMMANDS = new Set([
|
|
81
|
-
"pwd", "ls", "dir", "cat", "head", "tail", "wc", "stat", "file", "du", "df",
|
|
82
|
-
"grep", "rg", "egrep", "fgrep", "which", "whereis", "where", "whoami", "id",
|
|
83
|
-
"groups", "uname", "date", "uptime", "printenv", "echo", "printf",
|
|
84
|
-
"true", "false", "basename", "dirname", "realpath", "readlink", "tree",
|
|
85
|
-
"more", "less", "jq", "cut", "tr",
|
|
86
|
-
]);
|
|
87
|
-
const READ_ONLY_PREFIXES = new Set([
|
|
88
|
-
"git status", "git diff", "git log", "git show", "git rev-parse",
|
|
89
|
-
"git ls-files", "git blame", "git grep", "git describe", "git merge-base",
|
|
90
|
-
"git cat-file", "git rev-list", "git shortlog", "git whatchanged",
|
|
91
|
-
"npm ls", "npm list", "npm view", "npm outdated", "npm explain", "npm why",
|
|
92
|
-
"pnpm list", "pnpm ls", "yarn list", "yarn info",
|
|
93
|
-
"cargo tree", "go list", "pip list", "pip show",
|
|
94
|
-
"docker ps", "docker images", "docker logs",
|
|
95
|
-
]);
|
|
96
|
-
const NON_READ_ONLY_LEADERS = new Set([
|
|
97
|
-
"cd", "sudo", "doas", "env", "xargs", "time", "command", "eval", "exec",
|
|
98
|
-
"source", ".", "sh", "bash", "zsh", "fish", "powershell", "cmd",
|
|
99
|
-
]);
|
|
100
|
-
function scanCommand(command, onChar) {
|
|
101
|
-
let quote = "";
|
|
102
|
-
let escaped = false;
|
|
103
|
-
for (let i = 0; i < command.length; i += 1) {
|
|
104
|
-
const char = command[i];
|
|
105
|
-
if (escaped) {
|
|
106
|
-
escaped = false;
|
|
107
|
-
onChar(char, i, quote);
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
if (char === "\\") {
|
|
111
|
-
escaped = true;
|
|
112
|
-
onChar(char, i, quote);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (quote) {
|
|
116
|
-
if (char === quote)
|
|
117
|
-
quote = "";
|
|
118
|
-
onChar(char, i, quote);
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (char === '"' || char === "'") {
|
|
122
|
-
quote = char;
|
|
123
|
-
onChar(char, i, quote);
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
onChar(char, i, quote);
|
|
127
|
-
}
|
|
128
|
-
return quote === "";
|
|
129
|
-
}
|
|
130
|
-
function hasWriteRedirection(command) {
|
|
131
|
-
let found = false;
|
|
132
|
-
const balanced = scanCommand(command, (char, index, quote) => {
|
|
133
|
-
if (quote || char !== ">")
|
|
134
|
-
return;
|
|
135
|
-
const previous = command[index - 1];
|
|
136
|
-
if (previous === "=")
|
|
137
|
-
return;
|
|
138
|
-
found = true;
|
|
139
|
-
});
|
|
140
|
-
return !balanced || found;
|
|
141
|
-
}
|
|
142
|
-
function hasCommandSubstitution(command) {
|
|
143
|
-
let found = false;
|
|
144
|
-
const balanced = scanCommand(command, (char, index, quote) => {
|
|
145
|
-
if (quote)
|
|
146
|
-
return;
|
|
147
|
-
if (char === "`" || (char === "$" && command[index + 1] === "("))
|
|
148
|
-
found = true;
|
|
149
|
-
});
|
|
150
|
-
return !balanced || found;
|
|
151
|
-
}
|
|
152
|
-
export function splitCommandSegments(command) {
|
|
153
|
-
const parts = [];
|
|
154
|
-
let current = "";
|
|
155
|
-
let quote = "";
|
|
156
|
-
let escaped = false;
|
|
157
|
-
for (let i = 0; i < command.length; i += 1) {
|
|
158
|
-
const char = command[i];
|
|
159
|
-
if (escaped) {
|
|
160
|
-
current += char;
|
|
161
|
-
escaped = false;
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
if (char === "\\") {
|
|
165
|
-
current += char;
|
|
166
|
-
escaped = true;
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
if (quote) {
|
|
170
|
-
current += char;
|
|
171
|
-
if (char === quote)
|
|
172
|
-
quote = "";
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
if (char === '"' || char === "'") {
|
|
176
|
-
quote = char;
|
|
177
|
-
current += char;
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
const next = command[i + 1];
|
|
181
|
-
if ((char === "&" && next === "&") || (char === "|" && next === "|")) {
|
|
182
|
-
parts.push(current);
|
|
183
|
-
current = "";
|
|
184
|
-
i += 1;
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
if (char === ";" || char === "|" || char === "&" || char === "\n") {
|
|
188
|
-
parts.push(current);
|
|
189
|
-
current = "";
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
current += char;
|
|
193
|
-
}
|
|
194
|
-
parts.push(current);
|
|
195
|
-
return parts.map((part) => part.trim()).filter(Boolean);
|
|
196
|
-
}
|
|
197
|
-
function isReadOnlySegment(segment) {
|
|
198
|
-
const tokens = segment.split(/\s+/).filter(Boolean);
|
|
199
|
-
if (tokens.length === 0)
|
|
200
|
-
return true;
|
|
201
|
-
const first = tokens[0].toLowerCase();
|
|
202
|
-
const second = (tokens[1] ?? "").toLowerCase();
|
|
203
|
-
if (NON_READ_ONLY_LEADERS.has(first))
|
|
204
|
-
return false;
|
|
205
|
-
if (READ_ONLY_PREFIXES.has(first + " " + second))
|
|
206
|
-
return true;
|
|
207
|
-
if (READ_ONLY_COMMANDS.has(first))
|
|
208
|
-
return true;
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
export function isReadOnlyCommand(command) {
|
|
212
|
-
const cmd = String(command ?? "").trim();
|
|
213
|
-
if (!cmd)
|
|
214
|
-
return false;
|
|
215
|
-
if (hasWriteRedirection(cmd) || hasCommandSubstitution(cmd))
|
|
216
|
-
return false;
|
|
217
|
-
const segments = splitCommandSegments(cmd);
|
|
218
|
-
if (segments.length === 0)
|
|
219
|
-
return false;
|
|
220
|
-
return segments.every(isReadOnlySegment);
|
|
221
|
-
}
|
|
222
|
-
export function isReadOnlyToolCall(call) {
|
|
223
|
-
const tool = typeof call?.tool === "string" ? call.tool : "";
|
|
224
|
-
if (tool === "shell")
|
|
225
|
-
return isReadOnlyCommand(call.command);
|
|
226
|
-
return READ_ONLY_TOOLS.has(tool);
|
|
227
|
-
}
|
|
228
|
-
export function loopExemptTools() {
|
|
229
|
-
const raw = process.env["FASTCODE_LOOP_EXEMPT"] ?? "";
|
|
230
|
-
return new Set(raw.split(",").map((entry) => entry.trim()).filter(Boolean));
|
|
231
|
-
}
|
|
232
|
-
export function isLoopExempt(tool) {
|
|
233
|
-
return loopExemptTools().has(String(tool ?? ""));
|
|
234
|
-
}
|
|
235
|
-
function stableValue(value) {
|
|
236
|
-
if (value === undefined)
|
|
237
|
-
return "null";
|
|
238
|
-
if (value === null || typeof value !== "object")
|
|
239
|
-
return JSON.stringify(value);
|
|
240
|
-
if (Array.isArray(value))
|
|
241
|
-
return "[" + value.map((entry) => stableValue(entry)).join(",") + "]";
|
|
242
|
-
const keys = Object.keys(value).sort().filter((key) => value[key] !== undefined);
|
|
243
|
-
return "{" + keys.map((key) => JSON.stringify(key) + ":" + stableValue(value[key])).join(",") + "}";
|
|
244
|
-
}
|
|
245
|
-
export function stableStringify(value) {
|
|
246
|
-
return stableValue(value);
|
|
247
|
-
}
|
|
248
|
-
function normalizeFingerprintPath(value, cwd) {
|
|
249
|
-
let normalized = normalize(resolve(cwd, value));
|
|
250
|
-
if (normalized.length > 1)
|
|
251
|
-
normalized = normalized.replace(/[\\/]+$/, "");
|
|
252
|
-
return normalized;
|
|
253
|
-
}
|
|
254
|
-
function fingerprintValue(key, value, cwd) {
|
|
255
|
-
if (typeof value === "string" && (key === "path" || key === "from" || key === "to" || key === "cwd"))
|
|
256
|
-
return normalizeFingerprintPath(value, cwd);
|
|
257
|
-
if (key === "paths" && Array.isArray(value))
|
|
258
|
-
return value.map((entry) => typeof entry === "string" ? normalizeFingerprintPath(entry, cwd) : entry);
|
|
259
|
-
return value;
|
|
260
|
-
}
|
|
261
|
-
export function toolCallFingerprint(call, cwd = process.cwd()) {
|
|
262
|
-
const tool = typeof call?.tool === "string" ? call.tool : "unknown";
|
|
263
|
-
const args = {};
|
|
264
|
-
for (const key of Object.keys(call ?? {}).sort()) {
|
|
265
|
-
if (key === "tool" || key === "timeoutMs")
|
|
266
|
-
continue;
|
|
267
|
-
args[key] = fingerprintValue(key, call[key], cwd);
|
|
268
|
-
}
|
|
269
|
-
return tool + ":" + stableStringify(args);
|
|
270
|
-
}
|
package/src/agent/protocol.ts
CHANGED
|
@@ -97,16 +97,13 @@ You can inspect and change the user's machine by emitting exactly one or more to
|
|
|
97
97
|
Available tools:
|
|
98
98
|
- shell: {"tool":"shell","command":"command to run"}
|
|
99
99
|
- shell with timeout: {"tool":"shell","command":"npm test","timeoutMs":120000}
|
|
100
|
-
- shell poll (long commands return a session id): {"tool":"shell","session_id":"sh_..."}
|
|
101
|
-
Polling returns only new output; use waitMs to wait briefly for more.
|
|
102
100
|
- pwd: {"tool":"pwd"}
|
|
103
101
|
- read_file: {"tool":"read_file","path":"path/to/file"}
|
|
104
102
|
- read_many: {"tool":"read_many","paths":["file1","file2"]}
|
|
105
103
|
- write_file: {"tool":"write_file","path":"path/to/file","content":"full file contents"}
|
|
106
104
|
- append_file: {"tool":"append_file","path":"path/to/file","content":"text to append"}
|
|
107
105
|
- apply_patch: {"tool":"apply_patch","patch":"*** Begin Patch\\n*** Update File: path\\n@@\\n-old\\n+new\\n*** End Patch\\n"}
|
|
108
|
-
- list_files: {"tool":"list_files","path":"optional/path","maxDepth":2
|
|
109
|
-
- read_file is capped (default 200KB); grep skips files over 1MB. .fastcodeignore is honored.
|
|
106
|
+
- list_files: {"tool":"list_files","path":"optional/path","maxDepth":2}
|
|
110
107
|
- grep: {"tool":"grep","pattern":"text or regex","path":"optional/path"}
|
|
111
108
|
- replace_in_file: {"tool":"replace_in_file","path":"path/to/file","find":"exact text","replace":"replacement"}
|
|
112
109
|
- stat_path: {"tool":"stat_path","path":"path/to/file"}
|