@datename/fastcode-termux 0.0.0-stage → 0.1.6-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +418 -2
- package/bin/fastcode.mjs +59 -0
- package/dist/agent/approval.d.ts +50 -0
- package/dist/agent/approval.js +7 -0
- package/dist/agent/compaction.d.ts +39 -0
- package/dist/agent/compaction.js +227 -0
- package/dist/agent/context.d.ts +29 -0
- package/dist/agent/context.js +62 -0
- package/dist/agent/guards.d.ts +43 -0
- package/dist/agent/guards.js +269 -0
- package/dist/agent/ignore.d.ts +11 -0
- package/dist/agent/ignore.js +129 -0
- package/dist/agent/limits.d.ts +24 -0
- package/dist/agent/limits.js +71 -0
- package/dist/agent/process-tree.d.ts +2 -0
- package/dist/agent/process-tree.js +31 -0
- package/dist/agent/protocol-mode.d.ts +6 -0
- package/dist/agent/protocol-mode.js +51 -0
- package/dist/agent/protocol.d.ts +4 -0
- package/dist/agent/protocol.js +129 -0
- package/dist/agent/registry.d.ts +17 -0
- package/dist/agent/registry.js +90 -0
- package/dist/agent/runner.d.ts +106 -0
- package/dist/agent/runner.js +352 -0
- package/dist/agent/shell-session.d.ts +37 -0
- package/dist/agent/shell-session.js +400 -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 +63 -0
- package/dist/agent/tools/append_file.d.ts +2 -0
- package/dist/agent/tools/append_file.js +26 -0
- package/dist/agent/tools/apply_patch.d.ts +10 -0
- package/dist/agent/tools/apply_patch.js +52 -0
- package/dist/agent/tools/copy_file.d.ts +2 -0
- package/dist/agent/tools/copy_file.js +30 -0
- package/dist/agent/tools/delete_file.d.ts +2 -0
- package/dist/agent/tools/delete_file.js +24 -0
- package/dist/agent/tools/grep.d.ts +2 -0
- package/dist/agent/tools/grep.js +23 -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 +24 -0
- package/dist/agent/tools/move_path.d.ts +2 -0
- package/dist/agent/tools/move_path.js +47 -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 +21 -0
- package/dist/agent/tools/read_many.d.ts +2 -0
- package/dist/agent/tools/read_many.js +25 -0
- package/dist/agent/tools/readers.d.ts +6 -0
- package/dist/agent/tools/readers.js +216 -0
- package/dist/agent/tools/replace_in_file.d.ts +2 -0
- package/dist/agent/tools/replace_in_file.js +30 -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 +39 -0
- package/dist/agent/tools/types.js +1 -0
- package/dist/agent/tools/validate.d.ts +6 -0
- package/dist/agent/tools/validate.js +29 -0
- package/dist/agent/tools/write_file.d.ts +2 -0
- package/dist/agent/tools/write_file.js +26 -0
- package/dist/agent/tools.d.ts +3 -0
- package/dist/agent/tools.js +2 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +708 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +569 -0
- package/dist/commands/about.d.ts +8 -0
- package/dist/commands/about.js +16 -0
- package/dist/commands/agent.d.ts +11 -0
- package/dist/commands/agent.js +18 -0
- 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 +11 -0
- package/dist/commands/clear.js +9 -0
- package/dist/commands/compact.d.ts +10 -0
- package/dist/commands/compact.js +22 -0
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.js +24 -0
- package/dist/commands/context.d.ts +7 -0
- package/dist/commands/context.js +24 -0
- package/dist/commands/cost.d.ts +9 -0
- package/dist/commands/cost.js +13 -0
- package/dist/commands/cwd.d.ts +7 -0
- package/dist/commands/cwd.js +7 -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/exit.d.ts +9 -0
- package/dist/commands/exit.js +8 -0
- package/dist/commands/expand.d.ts +10 -0
- package/dist/commands/expand.js +8 -0
- package/dist/commands/help.d.ts +6 -0
- package/dist/commands/help.js +18 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.js +80 -0
- package/dist/commands/jobs.d.ts +7 -0
- package/dist/commands/jobs.js +16 -0
- package/dist/commands/kill.d.ts +7 -0
- package/dist/commands/kill.js +11 -0
- package/dist/commands/login.d.ts +18 -0
- package/dist/commands/login.js +63 -0
- package/dist/commands/logout.d.ts +9 -0
- package/dist/commands/logout.js +45 -0
- package/dist/commands/model.d.ts +24 -0
- package/dist/commands/model.js +50 -0
- package/dist/commands/plugin.d.ts +11 -0
- package/dist/commands/plugin.js +74 -0
- package/dist/commands/provider.d.ts +24 -0
- package/dist/commands/provider.js +39 -0
- package/dist/commands/reset.d.ts +9 -0
- package/dist/commands/reset.js +13 -0
- package/dist/commands/skills.d.ts +11 -0
- package/dist/commands/skills.js +106 -0
- package/dist/commands/steer.d.ts +11 -0
- package/dist/commands/steer.js +13 -0
- package/dist/commands/system.d.ts +11 -0
- package/dist/commands/system.js +20 -0
- package/dist/commands/theme.d.ts +11 -0
- package/dist/commands/theme.js +22 -0
- package/dist/commands/tools.d.ts +7 -0
- package/dist/commands/tools.js +29 -0
- package/dist/commands/whoami.d.ts +9 -0
- package/dist/commands/whoami.js +52 -0
- package/dist/config/paths.d.ts +4 -0
- package/dist/config/paths.js +59 -0
- package/dist/config/store.d.ts +89 -0
- package/dist/config/store.js +260 -0
- package/dist/config/themes.d.ts +73 -0
- package/dist/config/themes.js +77 -0
- package/dist/config/trust.d.ts +22 -0
- package/dist/config/trust.js +153 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +31 -0
- package/dist/lib/diagnostics.d.ts +66 -0
- package/dist/lib/diagnostics.js +195 -0
- package/dist/lib/http.d.ts +23 -0
- package/dist/lib/http.js +128 -0
- package/dist/lib/markdown.d.ts +1 -0
- package/dist/lib/markdown.js +32 -0
- 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/lib/pkg.d.ts +5 -0
- package/dist/lib/pkg.js +27 -0
- package/dist/lib/platform.d.ts +7 -0
- package/dist/lib/platform.js +57 -0
- package/dist/lib/startup.d.ts +6 -0
- package/dist/lib/startup.js +25 -0
- package/dist/lib/uiMode.d.ts +2 -0
- package/dist/lib/uiMode.js +7 -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/plugins/manager.d.ts +23 -0
- package/dist/plugins/manager.js +101 -0
- package/dist/providers/anthropic.d.ts +22 -0
- package/dist/providers/anthropic.js +119 -0
- package/dist/providers/custom.d.ts +33 -0
- package/dist/providers/custom.js +25 -0
- package/dist/providers/deepseek.d.ts +34 -0
- package/dist/providers/deepseek.js +16 -0
- package/dist/providers/google.d.ts +33 -0
- package/dist/providers/google.js +19 -0
- package/dist/providers/groq.d.ts +34 -0
- package/dist/providers/groq.js +21 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.js +67 -0
- package/dist/providers/mistral.d.ts +34 -0
- package/dist/providers/mistral.js +20 -0
- package/dist/providers/moonshot.d.ts +34 -0
- package/dist/providers/moonshot.js +23 -0
- package/dist/providers/ollama.d.ts +33 -0
- package/dist/providers/ollama.js +22 -0
- package/dist/providers/openai.d.ts +34 -0
- package/dist/providers/openai.js +26 -0
- package/dist/providers/openaiCompatible.d.ts +26 -0
- package/dist/providers/openaiCompatible.js +158 -0
- package/dist/providers/openrouter.d.ts +34 -0
- package/dist/providers/openrouter.js +27 -0
- package/dist/providers/qwen.d.ts +34 -0
- package/dist/providers/qwen.js +24 -0
- package/dist/providers/xai.d.ts +34 -0
- package/dist/providers/xai.js +19 -0
- package/dist/providers/zhipu.d.ts +34 -0
- package/dist/providers/zhipu.js +24 -0
- package/dist/session/log.d.ts +52 -0
- package/dist/session/log.js +331 -0
- package/dist/session/projection.d.ts +43 -0
- package/dist/session/projection.js +257 -0
- package/dist/skills/manager.d.ts +18 -0
- package/dist/skills/manager.js +201 -0
- package/dist/skills/parser.d.ts +18 -0
- package/dist/skills/parser.js +65 -0
- package/dist/types.d.ts +205 -0
- package/dist/types.js +1 -0
- package/dist/ui/Banner.d.ts +5 -0
- package/dist/ui/Banner.js +65 -0
- package/dist/ui/Message.d.ts +1 -0
- package/dist/ui/Message.js +24 -0
- package/dist/ui/Picker.d.ts +8 -0
- package/dist/ui/Picker.js +24 -0
- package/dist/ui/Prompt.d.ts +9 -0
- package/dist/ui/Prompt.js +38 -0
- package/dist/ui/Spinner.d.ts +5 -0
- package/dist/ui/Spinner.js +39 -0
- package/dist/ui/StatusBar.d.ts +11 -0
- package/dist/ui/StatusBar.js +20 -0
- package/dist/ui/TrustGate.d.ts +5 -0
- package/dist/ui/TrustGate.js +26 -0
- package/package.json +96 -4
- package/src/agent/approval.ts +47 -0
- package/src/agent/compaction.ts +276 -0
- package/src/agent/context.ts +97 -0
- package/src/agent/guards.ts +270 -0
- package/src/agent/ignore.ts +147 -0
- package/src/agent/limits.ts +71 -0
- package/src/agent/process-tree.ts +32 -0
- package/src/agent/protocol-mode.ts +59 -0
- package/src/agent/protocol.ts +129 -0
- package/src/agent/registry.ts +98 -0
- package/src/agent/runner.ts +443 -0
- package/src/agent/shell-session.ts +449 -0
- package/src/agent/stream.ts +143 -0
- package/src/agent/tool-schemas.ts +67 -0
- package/src/agent/tools/append_file.ts +28 -0
- package/src/agent/tools/apply_patch.ts +54 -0
- package/src/agent/tools/copy_file.ts +32 -0
- package/src/agent/tools/delete_file.ts +26 -0
- package/src/agent/tools/grep.ts +25 -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 +26 -0
- package/src/agent/tools/move_path.ts +50 -0
- package/src/agent/tools/paths.ts +92 -0
- package/src/agent/tools/pwd.ts +12 -0
- package/src/agent/tools/read_file.ts +23 -0
- package/src/agent/tools/read_many.ts +27 -0
- package/src/agent/tools/readers.ts +228 -0
- package/src/agent/tools/replace_in_file.ts +32 -0
- package/src/agent/tools/shell.ts +53 -0
- package/src/agent/tools/stat_path.ts +33 -0
- package/src/agent/tools/types.ts +42 -0
- package/src/agent/tools/validate.ts +35 -0
- package/src/agent/tools/write_file.ts +28 -0
- package/src/agent/tools.ts +3 -0
- package/src/app.ts +708 -0
- package/src/cli.ts +335 -0
- package/src/commands/about.ts +16 -0
- package/src/commands/agent.ts +18 -0
- 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 +9 -0
- package/src/commands/compact.ts +23 -0
- package/src/commands/config.ts +24 -0
- package/src/commands/context.ts +25 -0
- package/src/commands/cost.ts +13 -0
- package/src/commands/cwd.ts +7 -0
- package/src/commands/edit.ts +37 -0
- package/src/commands/effort.ts +49 -0
- package/src/commands/exit.ts +8 -0
- package/src/commands/expand.ts +8 -0
- package/src/commands/help.ts +18 -0
- package/src/commands/index.ts +80 -0
- package/src/commands/jobs.ts +17 -0
- package/src/commands/kill.ts +12 -0
- package/src/commands/login.ts +63 -0
- package/src/commands/logout.ts +45 -0
- package/src/commands/model.ts +50 -0
- package/src/commands/plugin.ts +74 -0
- package/src/commands/provider.ts +39 -0
- package/src/commands/reset.ts +13 -0
- package/src/commands/skills.ts +106 -0
- package/src/commands/steer.ts +13 -0
- package/src/commands/system.ts +20 -0
- package/src/commands/theme.ts +22 -0
- package/src/commands/tools.ts +29 -0
- package/src/commands/whoami.ts +52 -0
- package/src/config/paths.ts +59 -0
- package/src/config/store.ts +293 -0
- package/src/config/themes.ts +77 -0
- package/src/config/trust.ts +183 -0
- package/src/index.ts +31 -0
- package/src/lib/diagnostics.ts +195 -0
- package/src/lib/http.ts +132 -0
- package/src/lib/markdown.ts +32 -0
- 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/lib/pkg.ts +35 -0
- package/src/lib/platform.ts +57 -0
- package/src/lib/startup.ts +25 -0
- package/src/lib/uiMode.ts +7 -0
- package/src/patch/apply.ts +194 -0
- package/src/patch/parse.ts +131 -0
- package/src/patch/plan.ts +317 -0
- package/src/plugins/manager.ts +101 -0
- package/src/providers/anthropic.ts +119 -0
- package/src/providers/custom.ts +25 -0
- package/src/providers/deepseek.ts +16 -0
- package/src/providers/google.ts +19 -0
- package/src/providers/groq.ts +21 -0
- package/src/providers/index.ts +68 -0
- package/src/providers/mistral.ts +20 -0
- package/src/providers/moonshot.ts +23 -0
- package/src/providers/ollama.ts +22 -0
- package/src/providers/openai.ts +26 -0
- package/src/providers/openaiCompatible.ts +158 -0
- package/src/providers/openrouter.ts +27 -0
- package/src/providers/qwen.ts +24 -0
- package/src/providers/xai.ts +19 -0
- package/src/providers/zhipu.ts +24 -0
- package/src/session/log.ts +374 -0
- package/src/session/projection.ts +308 -0
- package/src/skills/manager.ts +201 -0
- package/src/skills/parser.ts +65 -0
- package/src/types.ts +205 -0
- package/src/ui/Banner.ts +68 -0
- package/src/ui/Message.ts +24 -0
- package/src/ui/Picker.ts +24 -0
- package/src/ui/Prompt.ts +38 -0
- package/src/ui/Spinner.ts +39 -0
- package/src/ui/StatusBar.ts +20 -0
- package/src/ui/TrustGate.ts +26 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getProvider, PROVIDERS } from "../providers/index.js";
|
|
2
|
+
import { maskKey, setCredential } from "../config/store.js";
|
|
3
|
+
import { getPaths } from "../config/paths.js";
|
|
4
|
+
/**
|
|
5
|
+
* Save a provider-wide key and describe it for the terminal. `model` is kept
|
|
6
|
+
* for the `/login provider model key` one-liner and only recorded as the
|
|
7
|
+
* credential's origin — the key itself is reused by every model of that
|
|
8
|
+
* provider. Shared by the `/login` command and the guided flow in the app.
|
|
9
|
+
*/
|
|
10
|
+
export function saveScopedKey(providerId, providerLabel, model, key) {
|
|
11
|
+
const trimmed = key.trim();
|
|
12
|
+
setCredential(providerId, model, trimmed);
|
|
13
|
+
const paths = getPaths();
|
|
14
|
+
return [
|
|
15
|
+
"Saved API key",
|
|
16
|
+
` provider ${providerLabel} (${providerId})`,
|
|
17
|
+
` scope all ${providerId} models (saved from ${model || "unknown"})`,
|
|
18
|
+
` key ${maskKey(trimmed)}`,
|
|
19
|
+
` stored ${paths.auth} (mode 0600)`,
|
|
20
|
+
"",
|
|
21
|
+
`Remove with /logout ${providerId}`,
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
|
24
|
+
export const loginCommand = {
|
|
25
|
+
name: "login",
|
|
26
|
+
description: "Bind a provider-wide API key. Usage: /login [provider] [model] [key]",
|
|
27
|
+
run({ args, state, actions }) {
|
|
28
|
+
if (args.length === 0) {
|
|
29
|
+
actions.startLogin({});
|
|
30
|
+
return { message: introText(state) };
|
|
31
|
+
}
|
|
32
|
+
const provider = getProvider(args[0]);
|
|
33
|
+
if (!provider) {
|
|
34
|
+
return { message: `Unknown provider "${args[0]}". Available: ${PROVIDERS.map((p) => p.id).join(", ")}` };
|
|
35
|
+
}
|
|
36
|
+
if (provider.authEnv.length === 0) {
|
|
37
|
+
return { message: `${provider.label} doesn't require an API key. Nothing to save.` };
|
|
38
|
+
}
|
|
39
|
+
if (args.length === 1) {
|
|
40
|
+
actions.startLogin({ provider: provider.id });
|
|
41
|
+
return { message: `Provider: ${provider.label} (${provider.id}).\nThe key will apply to every model of this provider.` };
|
|
42
|
+
}
|
|
43
|
+
const model = args[1];
|
|
44
|
+
if (args.length === 2) {
|
|
45
|
+
actions.startLogin({ provider: provider.id, model });
|
|
46
|
+
return { message: `Provider: ${provider.id} · saved from model: ${model}.\nNow paste the API key (input is masked).` };
|
|
47
|
+
}
|
|
48
|
+
const key = args.slice(2).join(" ");
|
|
49
|
+
return { message: saveScopedKey(provider.id, provider.label, model, key) };
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
function introText(state) {
|
|
53
|
+
const env = getProvider(state.providerId)?.authEnv?.[0] ?? "PROVIDER_API_KEY";
|
|
54
|
+
return [
|
|
55
|
+
"Bind a provider-wide API key (reused by every model of that provider).",
|
|
56
|
+
"",
|
|
57
|
+
` current provider: ${state.providerId}`,
|
|
58
|
+
"",
|
|
59
|
+
"FastCode will ask for the provider, then optionally a model name, then the key.",
|
|
60
|
+
" one-liner: /login <provider> <model> <key>",
|
|
61
|
+
` or set: export ${env}=<key> (provider-wide, any model)`,
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getProvider } from "../providers/index.js";
|
|
2
|
+
import { listCredentials, maskKey, removeCredential, removeCredentialsForProvider } from "../config/store.js";
|
|
3
|
+
export const logoutCommand = {
|
|
4
|
+
name: "logout",
|
|
5
|
+
description: "Remove a stored API key. Usage: /logout <provider> [model] | /logout <provider> --all",
|
|
6
|
+
run({ args }) {
|
|
7
|
+
if (args.length === 0) {
|
|
8
|
+
const credentials = listCredentials();
|
|
9
|
+
if (credentials.length === 0)
|
|
10
|
+
return { message: "No stored keys. Use /login to add one." };
|
|
11
|
+
const lines = ["Stored keys (provider-wide):"];
|
|
12
|
+
for (const c of credentials)
|
|
13
|
+
lines.push(` ${c.provider} ${maskKey(c.key)}`);
|
|
14
|
+
lines.push("");
|
|
15
|
+
lines.push("Remove: /logout <provider>");
|
|
16
|
+
lines.push(" /logout <provider> --all");
|
|
17
|
+
return { message: lines.join("\n") };
|
|
18
|
+
}
|
|
19
|
+
const id = args[0];
|
|
20
|
+
const provider = getProvider(id);
|
|
21
|
+
if (!provider)
|
|
22
|
+
return { message: `Unknown provider "${id}".` };
|
|
23
|
+
if (args.includes("--all")) {
|
|
24
|
+
const removed = removeCredentialsForProvider(provider.id);
|
|
25
|
+
return {
|
|
26
|
+
message: removed > 0
|
|
27
|
+
? `Removed ${removed} stored key(s) for ${provider.label}.`
|
|
28
|
+
: `No stored key for ${provider.label}.`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (args.length >= 2) {
|
|
32
|
+
const ok = removeCredential(provider.id);
|
|
33
|
+
return {
|
|
34
|
+
message: ok
|
|
35
|
+
? `Removed the stored key for ${provider.id} (applies to all its models).`
|
|
36
|
+
: `No stored key for ${provider.id}.`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const forProvider = listCredentials().filter((c) => c.provider === provider.id);
|
|
40
|
+
if (forProvider.length === 0)
|
|
41
|
+
return { message: `No stored key for ${provider.label}.` };
|
|
42
|
+
removeCredential(provider.id);
|
|
43
|
+
return { message: `Removed the stored key for ${provider.label} (all models).` };
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const modelCommand: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
run({ args, state, actions }: {
|
|
5
|
+
args: any;
|
|
6
|
+
state: any;
|
|
7
|
+
actions: any;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
message: string;
|
|
10
|
+
picker?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
message: string;
|
|
13
|
+
picker: {
|
|
14
|
+
title: string;
|
|
15
|
+
current: any;
|
|
16
|
+
items: {
|
|
17
|
+
value: any;
|
|
18
|
+
label: any;
|
|
19
|
+
hint: string;
|
|
20
|
+
}[];
|
|
21
|
+
onSelect: (id: any) => void;
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getProviderOrThrow, probeProvider } from "../providers/index.js";
|
|
2
|
+
import { resolveProviderKey } from "../config/store.js";
|
|
3
|
+
export const modelCommand = {
|
|
4
|
+
name: "model",
|
|
5
|
+
description: "Pick a model interactively, or switch with /model <id>",
|
|
6
|
+
async run({ args, state, actions }) {
|
|
7
|
+
const provider = getProviderOrThrow(state.providerId);
|
|
8
|
+
if (args.length > 0) {
|
|
9
|
+
const id = args.join(" ");
|
|
10
|
+
actions.setModel(id);
|
|
11
|
+
return { message: `Model set to ${id}.` };
|
|
12
|
+
}
|
|
13
|
+
const { key } = resolveProviderKey(provider.id, provider.authEnv);
|
|
14
|
+
const fetched = await provider.listModels(key).catch(() => []);
|
|
15
|
+
const models = dedupe(fetched);
|
|
16
|
+
if (models.length === 0) {
|
|
17
|
+
return { message: `No models available from ${provider.label}.` };
|
|
18
|
+
}
|
|
19
|
+
const online = await probeProvider(provider, key);
|
|
20
|
+
const list = models.slice(0, 50);
|
|
21
|
+
return {
|
|
22
|
+
message: `Models for ${provider.label}: ${list.length}${online ? "" : " (offline — showing the built-in list)"}.\n` +
|
|
23
|
+
"Use ↑/↓, a number, or Enter to select.",
|
|
24
|
+
picker: {
|
|
25
|
+
title: `Select model · ${provider.label}${online ? "" : " (offline)"}`,
|
|
26
|
+
current: state.model,
|
|
27
|
+
items: list.map((m) => ({
|
|
28
|
+
value: m.id,
|
|
29
|
+
label: m.id,
|
|
30
|
+
hint: m.label ? `— ${m.label}` : undefined,
|
|
31
|
+
})),
|
|
32
|
+
onSelect: (id) => {
|
|
33
|
+
actions.setModel(id);
|
|
34
|
+
actions.pushSystemMessage(`Model set to ${id}.`);
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
function dedupe(models) {
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
const out = [];
|
|
43
|
+
for (const model of models) {
|
|
44
|
+
if (!model?.id || seen.has(model.id))
|
|
45
|
+
continue;
|
|
46
|
+
seen.add(model.id);
|
|
47
|
+
out.push(model);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { getPlugin, importPlugin, listInstalledPlugins, removePlugin, } from "../plugins/manager.js";
|
|
2
|
+
export const pluginCommand = {
|
|
3
|
+
name: "plugin",
|
|
4
|
+
description: "Manage always-active plugin packs. Usage: /plugin [list|import|enable|disable|remove|info]",
|
|
5
|
+
run({ args, state, actions }) {
|
|
6
|
+
const sub = (args[0] ?? "list").toLowerCase();
|
|
7
|
+
if (sub === "list") {
|
|
8
|
+
const plugins = listInstalledPlugins();
|
|
9
|
+
if (plugins.length === 0)
|
|
10
|
+
return { message: "No plugins installed. Import one with /plugin import <path> [name]." };
|
|
11
|
+
return {
|
|
12
|
+
message: [
|
|
13
|
+
"Installed plugins:",
|
|
14
|
+
"",
|
|
15
|
+
...plugins.map((p) => {
|
|
16
|
+
const enabled = state.enabledPlugins.includes(p.name) ? "●" : " ";
|
|
17
|
+
return `${enabled} ${p.name} — ${p.description}`;
|
|
18
|
+
}),
|
|
19
|
+
].join("\n"),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (sub === "import") {
|
|
23
|
+
const source = args[1];
|
|
24
|
+
if (!source)
|
|
25
|
+
return { message: "Usage: /plugin import <folder-path> [name]" };
|
|
26
|
+
const plugin = importPlugin(source, args[2]);
|
|
27
|
+
actions.enablePlugin(plugin.name);
|
|
28
|
+
return { message: `Imported and enabled plugin ${plugin.name}.` };
|
|
29
|
+
}
|
|
30
|
+
if (sub === "enable") {
|
|
31
|
+
const name = args[1];
|
|
32
|
+
if (!name)
|
|
33
|
+
return { message: "Usage: /plugin enable <name>" };
|
|
34
|
+
const plugin = getPlugin(name);
|
|
35
|
+
if (!plugin)
|
|
36
|
+
return { message: `Plugin not found: ${name}` };
|
|
37
|
+
actions.enablePlugin(plugin.name);
|
|
38
|
+
return { message: `Enabled plugin ${plugin.name}.` };
|
|
39
|
+
}
|
|
40
|
+
if (sub === "disable") {
|
|
41
|
+
const name = args[1];
|
|
42
|
+
if (!name)
|
|
43
|
+
return { message: "Usage: /plugin disable <name>" };
|
|
44
|
+
actions.disablePlugin(name);
|
|
45
|
+
return { message: `Disabled plugin ${name}.` };
|
|
46
|
+
}
|
|
47
|
+
if (sub === "remove") {
|
|
48
|
+
const name = args[1];
|
|
49
|
+
if (!name)
|
|
50
|
+
return { message: "Usage: /plugin remove <name>" };
|
|
51
|
+
actions.disablePlugin(name);
|
|
52
|
+
return { message: removePlugin(name) ? `Removed plugin ${name}.` : `Plugin not found: ${name}` };
|
|
53
|
+
}
|
|
54
|
+
if (sub === "info") {
|
|
55
|
+
const name = args[1];
|
|
56
|
+
if (!name)
|
|
57
|
+
return { message: "Usage: /plugin info <name>" };
|
|
58
|
+
const plugin = getPlugin(name);
|
|
59
|
+
if (!plugin)
|
|
60
|
+
return { message: `Plugin not found: ${name}` };
|
|
61
|
+
return {
|
|
62
|
+
message: [
|
|
63
|
+
`Plugin: ${plugin.name}`,
|
|
64
|
+
`Path: ${plugin.path}`,
|
|
65
|
+
`Description: ${plugin.description}`,
|
|
66
|
+
`Skills: ${plugin.skills.map((s) => s.name).join(", ") || "none"}`,
|
|
67
|
+
"",
|
|
68
|
+
plugin.body.slice(0, 4000),
|
|
69
|
+
].join("\n"),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return { message: "Usage: /plugin [list|import|enable|disable|remove|info]" };
|
|
73
|
+
},
|
|
74
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const providerCommand: {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
run({ args, actions, state }: {
|
|
5
|
+
args: any;
|
|
6
|
+
actions: any;
|
|
7
|
+
state: any;
|
|
8
|
+
}): {
|
|
9
|
+
message: string;
|
|
10
|
+
picker: {
|
|
11
|
+
title: string;
|
|
12
|
+
current: any;
|
|
13
|
+
items: {
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
hint: string;
|
|
17
|
+
}[];
|
|
18
|
+
onSelect: (id: any) => void;
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
message: string;
|
|
22
|
+
picker?: undefined;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PROVIDERS, getProvider } from "../providers/index.js";
|
|
2
|
+
export const providerCommand = {
|
|
3
|
+
name: "provider",
|
|
4
|
+
description: "List or switch the active LLM provider. Usage: /provider [id]",
|
|
5
|
+
run({ args, actions, state }) {
|
|
6
|
+
if (args.length === 0) {
|
|
7
|
+
return {
|
|
8
|
+
message: "Select a provider (↑/↓ or a number, Enter to confirm).",
|
|
9
|
+
picker: {
|
|
10
|
+
title: "Select provider",
|
|
11
|
+
current: state.providerId,
|
|
12
|
+
items: PROVIDERS.map((p) => ({
|
|
13
|
+
value: p.id,
|
|
14
|
+
label: `${p.id.padEnd(12)} ${p.label}`,
|
|
15
|
+
hint: p.authEnv.length === 0 ? "(no key needed)" : `[${p.authEnv.join(", ")}]`,
|
|
16
|
+
})),
|
|
17
|
+
onSelect: (id) => {
|
|
18
|
+
const next = getProvider(id);
|
|
19
|
+
if (!next)
|
|
20
|
+
return;
|
|
21
|
+
actions.setProvider(next.id);
|
|
22
|
+
actions.setModel(next.defaultModel);
|
|
23
|
+
actions.pushSystemMessage(`Provider set to ${next.label}. Default model: ${next.defaultModel}.`);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const target = args[0];
|
|
29
|
+
const next = getProvider(target);
|
|
30
|
+
if (!next) {
|
|
31
|
+
return { message: `Unknown provider "${target}". Try /provider with no args.` };
|
|
32
|
+
}
|
|
33
|
+
actions.setProvider(next.id);
|
|
34
|
+
actions.setModel(next.defaultModel);
|
|
35
|
+
return {
|
|
36
|
+
message: `Provider set to ${next.label}. Default model: ${next.defaultModel}. Use /model to change.`,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DEFAULT_CONFIG, saveConfig } from "../config/store.js";
|
|
2
|
+
export const resetCommand = {
|
|
3
|
+
name: "reset",
|
|
4
|
+
description: "Reset config to defaults (does not touch API keys).",
|
|
5
|
+
run({ actions }) {
|
|
6
|
+
saveConfig({ ...DEFAULT_CONFIG });
|
|
7
|
+
actions.setProvider(DEFAULT_CONFIG.providerId);
|
|
8
|
+
actions.setModel(DEFAULT_CONFIG.model);
|
|
9
|
+
actions.setTheme(DEFAULT_CONFIG.theme);
|
|
10
|
+
actions.setSystemPrompt(DEFAULT_CONFIG.systemPrompt);
|
|
11
|
+
return { message: "Config reset to defaults." };
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { installSkill, uninstallSkill, listInstalledSkills, searchRegistry, getSkill, } from "../skills/manager.js";
|
|
2
|
+
export const skillsCommand = {
|
|
3
|
+
name: "skills",
|
|
4
|
+
description: "Manage Agent Skills (download from skills.sh and toggle).",
|
|
5
|
+
async run({ args, state, actions }) {
|
|
6
|
+
const sub = (args[0] ?? "list").toLowerCase();
|
|
7
|
+
const rest = args.slice(1);
|
|
8
|
+
if (sub === "list" || sub === "ls") {
|
|
9
|
+
const installed = listInstalledSkills();
|
|
10
|
+
if (installed.length === 0) {
|
|
11
|
+
return {
|
|
12
|
+
message: "No skills installed. Try `/skills search <query>` or `/skills install <name>`.",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const lines = ["Installed skills:"];
|
|
16
|
+
for (const s of installed) {
|
|
17
|
+
const enabled = state.enabledSkills.includes(s.name) ? "● " : " ";
|
|
18
|
+
lines.push(`${enabled}${s.name} — ${truncate(s.description, 80)}`);
|
|
19
|
+
lines.push(` source: ${s.source}`);
|
|
20
|
+
}
|
|
21
|
+
lines.push("");
|
|
22
|
+
lines.push("Toggle with `/skills enable <name>` or `/skills disable <name>`.");
|
|
23
|
+
return { message: lines.join("\n") };
|
|
24
|
+
}
|
|
25
|
+
if (sub === "search") {
|
|
26
|
+
if (rest.length === 0)
|
|
27
|
+
return { message: "Usage: /skills search <query>" };
|
|
28
|
+
const hits = await searchRegistry(rest.join(" "), state.skillsRegistry);
|
|
29
|
+
if (hits.length === 0) {
|
|
30
|
+
return { message: `No skills found for "${rest.join(" ")}".` };
|
|
31
|
+
}
|
|
32
|
+
const lines = [`Skills matching "${rest.join(" ")}":`];
|
|
33
|
+
for (const h of hits.slice(0, 20)) {
|
|
34
|
+
lines.push(` • ${h.slug} — ${truncate(h.description ?? "", 80)}`);
|
|
35
|
+
}
|
|
36
|
+
lines.push("");
|
|
37
|
+
lines.push("Install with `/skills install <slug>`.");
|
|
38
|
+
return { message: lines.join("\n") };
|
|
39
|
+
}
|
|
40
|
+
if (sub === "install" || sub === "add") {
|
|
41
|
+
if (rest.length === 0)
|
|
42
|
+
return { message: "Usage: /skills install <name|owner/repo|url>" };
|
|
43
|
+
const force = rest.includes("--force");
|
|
44
|
+
const spec = rest.filter((r) => r !== "--force").join(" ");
|
|
45
|
+
try {
|
|
46
|
+
const skill = await installSkill(spec, { registry: state.skillsRegistry, force });
|
|
47
|
+
return {
|
|
48
|
+
message: `Installed skill "${skill.name}" → ${skill.path}\n${truncate(skill.description, 200)}\n\nEnable with /skills enable ${skill.name}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
return { message: `Install failed: ${err.message}` };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (sub === "uninstall" || sub === "remove" || sub === "rm") {
|
|
56
|
+
if (rest.length === 0)
|
|
57
|
+
return { message: "Usage: /skills uninstall <name>" };
|
|
58
|
+
const ok = uninstallSkill(rest[0]);
|
|
59
|
+
if (ok)
|
|
60
|
+
actions.disableSkill(rest[0]);
|
|
61
|
+
return { message: ok ? `Uninstalled "${rest[0]}".` : `No skill named "${rest[0]}".` };
|
|
62
|
+
}
|
|
63
|
+
if (sub === "enable" || sub === "use") {
|
|
64
|
+
if (rest.length === 0)
|
|
65
|
+
return { message: "Usage: /skills enable <name>" };
|
|
66
|
+
const skill = getSkill(rest[0]);
|
|
67
|
+
if (!skill)
|
|
68
|
+
return { message: `Skill "${rest[0]}" is not installed.` };
|
|
69
|
+
actions.enableSkill(skill.name);
|
|
70
|
+
return { message: `Enabled skill "${skill.name}".` };
|
|
71
|
+
}
|
|
72
|
+
if (sub === "disable" || sub === "off") {
|
|
73
|
+
if (rest.length === 0)
|
|
74
|
+
return { message: "Usage: /skills disable <name>" };
|
|
75
|
+
actions.disableSkill(rest[0]);
|
|
76
|
+
return { message: `Disabled skill "${rest[0]}".` };
|
|
77
|
+
}
|
|
78
|
+
if (sub === "info" || sub === "show") {
|
|
79
|
+
if (rest.length === 0)
|
|
80
|
+
return { message: "Usage: /skills info <name>" };
|
|
81
|
+
const skill = getSkill(rest[0]);
|
|
82
|
+
if (!skill)
|
|
83
|
+
return { message: `Skill "${rest[0]}" is not installed.` };
|
|
84
|
+
const head = `# ${skill.name}\n_${skill.description}_\n\nSource: ${skill.source}\n\n---\n\n`;
|
|
85
|
+
return { message: head + skill.body };
|
|
86
|
+
}
|
|
87
|
+
if (sub === "registry") {
|
|
88
|
+
if (rest.length === 0) {
|
|
89
|
+
return { message: `Skills registry: ${state.skillsRegistry}` };
|
|
90
|
+
}
|
|
91
|
+
// Mutate via AppActions so the in-memory React state stays in sync —
|
|
92
|
+
// direct saveConfig() would be silently overwritten by the next state
|
|
93
|
+
// change because app.tsx persists in-memory config on every update.
|
|
94
|
+
actions.setSkillsRegistry(rest[0]);
|
|
95
|
+
return { message: `Skills registry set to ${rest[0]}.` };
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
message: "Unknown subcommand. Try: list, search, install, uninstall, enable, disable, info, registry.",
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
function truncate(s, n) {
|
|
103
|
+
if (s.length <= n)
|
|
104
|
+
return s;
|
|
105
|
+
return s.slice(0, n - 1) + "…";
|
|
106
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const systemCommand = {
|
|
2
|
+
name: "system",
|
|
3
|
+
description: "Show or set the system prompt. Usage: /system [new prompt]",
|
|
4
|
+
run({ raw, state, actions }) {
|
|
5
|
+
// Strip the leading "/system" verb keeping the rest verbatim, including
|
|
6
|
+
// whitespace, so multi-paragraph prompts survive.
|
|
7
|
+
const stripped = raw.replace(/^\/system\s*/i, "");
|
|
8
|
+
if (!stripped.trim()) {
|
|
9
|
+
return {
|
|
10
|
+
message: [
|
|
11
|
+
"Current system prompt:",
|
|
12
|
+
"",
|
|
13
|
+
state.systemPrompt,
|
|
14
|
+
].join("\n"),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
actions.setSystemPrompt(stripped);
|
|
18
|
+
return { message: "System prompt updated." };
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { THEMES } from "../config/themes.js";
|
|
2
|
+
export const themeCommand = {
|
|
3
|
+
name: "theme",
|
|
4
|
+
description: "List or switch the color theme. Usage: /theme [id]",
|
|
5
|
+
run({ args, state, actions }) {
|
|
6
|
+
if (args.length === 0) {
|
|
7
|
+
const lines = ["Themes:"];
|
|
8
|
+
for (const id of Object.keys(THEMES)) {
|
|
9
|
+
const marker = id === state.theme ? "● " : " ";
|
|
10
|
+
lines.push(`${marker}${id} — ${THEMES[id].label}`);
|
|
11
|
+
}
|
|
12
|
+
lines.push("");
|
|
13
|
+
lines.push("Switch with `/theme <id>`.");
|
|
14
|
+
return { message: lines.join("\n") };
|
|
15
|
+
}
|
|
16
|
+
const id = args[0];
|
|
17
|
+
if (!THEMES[id])
|
|
18
|
+
return { message: `Unknown theme "${id}".` };
|
|
19
|
+
actions.setTheme(id);
|
|
20
|
+
return { message: `Theme set to ${id}.` };
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const toolsCommand = {
|
|
2
|
+
name: "tools",
|
|
3
|
+
description: "Show local coding-agent tools.",
|
|
4
|
+
run() {
|
|
5
|
+
return {
|
|
6
|
+
message: [
|
|
7
|
+
"FastCode agent tools:",
|
|
8
|
+
"",
|
|
9
|
+
" shell Run terminal commands in the sandbox root",
|
|
10
|
+
" pwd Print sandbox root",
|
|
11
|
+
" read_file Read one file",
|
|
12
|
+
" read_many Read multiple files",
|
|
13
|
+
" write_file Replace/create a file",
|
|
14
|
+
" append_file Append to a file",
|
|
15
|
+
" apply_patch Apply focused patch hunks",
|
|
16
|
+
" replace_in_file Replace exact text in a file",
|
|
17
|
+
" list_files List files recursively",
|
|
18
|
+
" grep Search files",
|
|
19
|
+
" stat_path Inspect file metadata",
|
|
20
|
+
" make_dir Create directories",
|
|
21
|
+
" copy_file Copy a file",
|
|
22
|
+
" move_path Move/rename a path",
|
|
23
|
+
" delete_file Delete a path",
|
|
24
|
+
"",
|
|
25
|
+
"Sandbox: file tools are rooted at the current working directory.",
|
|
26
|
+
].join("\n"),
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
};
|