@datename/fastcode-termux 0.1.6 → 0.1.8-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +4 -0
- package/README.md +67 -16
- package/dist/agent/approval-json.d.ts +43 -0
- package/dist/agent/approval-json.js +69 -0
- package/dist/agent/approval-native.d.ts +3 -0
- package/dist/agent/approval-native.js +165 -0
- package/dist/agent/approval-store.d.ts +16 -0
- package/dist/agent/approval-store.js +21 -0
- package/dist/agent/approval.d.ts +83 -0
- package/dist/agent/approval.js +42 -0
- package/dist/agent/compaction.d.ts +41 -0
- package/dist/agent/compaction.js +270 -0
- package/dist/agent/context.d.ts +29 -0
- package/dist/agent/context.js +62 -0
- package/dist/agent/guards.d.ts +24 -16
- package/dist/agent/guards.js +1167 -18
- package/dist/agent/ignore.d.ts +11 -0
- package/dist/agent/ignore.js +129 -0
- package/dist/agent/policy/defaults.d.ts +16 -0
- package/dist/agent/policy/defaults.js +17 -0
- package/dist/agent/policy/egress.d.ts +32 -0
- package/dist/agent/policy/egress.js +280 -0
- package/dist/agent/process-tree.d.ts +22 -0
- package/dist/agent/process-tree.js +102 -0
- package/dist/agent/protocol-mode.d.ts +6 -0
- package/dist/agent/protocol-mode.js +51 -0
- package/dist/agent/protocol.d.ts +20 -1
- package/dist/agent/protocol.js +169 -39
- package/dist/agent/registry.d.ts +19 -0
- package/dist/agent/registry.js +247 -0
- package/dist/agent/runner.d.ts +127 -0
- package/dist/agent/runner.js +391 -0
- package/dist/agent/shell-ast.d.ts +11 -0
- package/dist/agent/shell-ast.js +204 -0
- package/dist/agent/shell-session.d.ts +51 -0
- package/dist/agent/shell-session.js +611 -0
- package/dist/agent/stream.d.ts +29 -0
- package/dist/agent/stream.js +103 -0
- package/dist/agent/tool-schemas.d.ts +2 -0
- package/dist/agent/tool-schemas.js +82 -0
- package/dist/agent/tools/append_file.d.ts +2 -0
- package/dist/agent/tools/append_file.js +28 -0
- package/dist/agent/tools/apply_patch.d.ts +10 -0
- package/dist/agent/tools/apply_patch.js +92 -0
- package/dist/agent/tools/copy_file.d.ts +2 -0
- package/dist/agent/tools/copy_file.js +53 -0
- package/dist/agent/tools/delete_file.d.ts +2 -0
- package/dist/agent/tools/delete_file.js +43 -0
- package/dist/agent/tools/grep.d.ts +2 -0
- package/dist/agent/tools/grep.js +54 -0
- package/dist/agent/tools/index.d.ts +2 -0
- package/dist/agent/tools/index.js +32 -0
- package/dist/agent/tools/list_files.d.ts +2 -0
- package/dist/agent/tools/list_files.js +17 -0
- package/dist/agent/tools/make_dir.d.ts +2 -0
- package/dist/agent/tools/make_dir.js +26 -0
- package/dist/agent/tools/move_path.d.ts +9 -0
- package/dist/agent/tools/move_path.js +73 -0
- package/dist/agent/tools/paths.d.ts +7 -0
- package/dist/agent/tools/paths.js +84 -0
- package/dist/agent/tools/pwd.d.ts +2 -0
- package/dist/agent/tools/pwd.js +10 -0
- package/dist/agent/tools/read_file.d.ts +2 -0
- package/dist/agent/tools/read_file.js +81 -0
- package/dist/agent/tools/read_many.d.ts +2 -0
- package/dist/agent/tools/read_many.js +43 -0
- package/dist/agent/tools/readers.d.ts +58 -0
- package/dist/agent/tools/readers.js +426 -0
- package/dist/agent/tools/replace_in_file.d.ts +2 -0
- package/dist/agent/tools/replace_in_file.js +63 -0
- package/dist/agent/tools/shell.d.ts +2 -0
- package/dist/agent/tools/shell.js +48 -0
- package/dist/agent/tools/stat_path.d.ts +2 -0
- package/dist/agent/tools/stat_path.js +31 -0
- package/dist/agent/tools/types.d.ts +65 -0
- package/dist/agent/tools/types.js +1 -0
- package/dist/agent/tools/validate.d.ts +19 -0
- package/dist/agent/tools/validate.js +92 -0
- package/dist/agent/tools/write_file.d.ts +2 -0
- package/dist/agent/tools/write_file.js +28 -0
- package/dist/agent/tools.d.ts +3 -1
- package/dist/agent/tools.js +2 -377
- package/dist/app.d.ts +2 -1
- package/dist/app.js +846 -173
- package/dist/cli-main.js +363 -0
- package/dist/cli.js +444 -333
- package/dist/commands/about.js +1 -1
- package/dist/commands/attach.d.ts +9 -0
- package/dist/commands/attach.js +15 -0
- package/dist/commands/bg.d.ts +7 -0
- package/dist/commands/bg.js +9 -0
- package/dist/commands/cancel.d.ts +10 -0
- package/dist/commands/cancel.js +10 -0
- package/dist/commands/clear.d.ts +1 -0
- package/dist/commands/clear.js +1 -1
- package/dist/commands/compact.d.ts +22 -0
- package/dist/commands/compact.js +34 -0
- package/dist/commands/context.d.ts +7 -0
- package/dist/commands/context.js +25 -0
- package/dist/commands/edit.d.ts +10 -0
- package/dist/commands/edit.js +36 -0
- package/dist/commands/effort.d.ts +25 -0
- package/dist/commands/effort.js +48 -0
- package/dist/commands/expand.d.ts +10 -0
- package/dist/commands/expand.js +8 -0
- package/dist/commands/index.js +24 -0
- package/dist/commands/jobs.d.ts +7 -0
- package/dist/commands/jobs.js +17 -0
- package/dist/commands/kill.d.ts +7 -0
- package/dist/commands/kill.js +13 -0
- package/dist/commands/login.d.ts +6 -4
- package/dist/commands/login.js +24 -22
- package/dist/commands/logout.js +8 -16
- package/dist/commands/model.d.ts +1 -0
- package/dist/commands/model.js +10 -22
- package/dist/commands/provider.d.ts +1 -2
- package/dist/commands/provider.js +4 -11
- package/dist/commands/skills.js +34 -4
- package/dist/commands/steer.d.ts +11 -0
- package/dist/commands/steer.js +13 -0
- package/dist/commands/threads.d.ts +9 -0
- package/dist/commands/threads.js +26 -0
- package/dist/commands/whoami.js +6 -5
- package/dist/config/store.d.ts +53 -12
- package/dist/config/store.js +163 -73
- package/dist/config/trust.d.ts +30 -8
- package/dist/config/trust.js +139 -14
- package/dist/headless.d.ts +7 -0
- package/dist/headless.js +213 -0
- package/dist/index.js +19 -3
- package/dist/lib/debug.d.ts +2 -0
- package/dist/lib/debug.js +22 -0
- package/dist/lib/diagnostics.d.ts +48 -4
- package/dist/lib/diagnostics.js +90 -8
- package/dist/lib/highlight-subset.d.ts +21 -0
- package/dist/lib/highlight-subset.js +88 -0
- package/dist/lib/http.d.ts +11 -1
- package/dist/lib/http.js +62 -4
- package/dist/lib/lifecycle.d.ts +5 -0
- package/dist/lib/lifecycle.js +62 -0
- package/dist/lib/markdown.js +22 -4
- package/dist/lib/model-meta.d.ts +19 -0
- package/dist/lib/model-meta.js +113 -0
- package/dist/lib/native-tools.d.ts +12 -0
- package/dist/lib/native-tools.js +21 -0
- package/dist/lib/net.d.ts +33 -0
- package/dist/lib/net.js +168 -0
- package/dist/patch/apply.d.ts +15 -0
- package/dist/patch/apply.js +172 -0
- package/dist/patch/parse.d.ts +29 -0
- package/dist/patch/parse.js +112 -0
- package/dist/patch/plan.d.ts +49 -0
- package/dist/patch/plan.js +273 -0
- package/dist/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.js +12 -0
- package/dist/providers/custom.d.ts +9 -0
- package/dist/providers/deepseek.d.ts +10 -0
- package/dist/providers/deepseek.js +3 -2
- package/dist/providers/google.d.ts +9 -0
- package/dist/providers/groq.d.ts +10 -0
- package/dist/providers/groq.js +2 -1
- package/dist/providers/index.d.ts +10 -201
- package/dist/providers/index.js +30 -0
- package/dist/providers/mistral.d.ts +10 -0
- package/dist/providers/mistral.js +2 -1
- package/dist/providers/moonshot.d.ts +10 -0
- package/dist/providers/moonshot.js +2 -1
- package/dist/providers/ollama.d.ts +9 -0
- package/dist/providers/openai.d.ts +10 -0
- package/dist/providers/openai.js +2 -1
- package/dist/providers/openaiCompatible.d.ts +33 -2
- package/dist/providers/openaiCompatible.js +78 -16
- package/dist/providers/openrouter.d.ts +10 -0
- package/dist/providers/openrouter.js +2 -1
- package/dist/providers/qwen.d.ts +10 -0
- package/dist/providers/qwen.js +2 -1
- package/dist/providers/spec.d.ts +12 -0
- package/dist/providers/spec.js +29 -0
- package/dist/providers/xai.d.ts +10 -0
- package/dist/providers/xai.js +2 -1
- package/dist/providers/zhipu.d.ts +10 -0
- package/dist/providers/zhipu.js +2 -1
- package/dist/session/log.d.ts +49 -14
- package/dist/session/log.js +236 -11
- package/dist/session/projection.d.ts +76 -0
- package/dist/session/projection.js +526 -0
- package/dist/skills/manager.d.ts +15 -0
- package/dist/skills/manager.js +135 -18
- package/dist/types.d.ts +75 -1
- package/dist/ui/Message.d.ts +1 -7
- package/dist/ui/Message.js +13 -2
- package/dist/ui/Picker.d.ts +8 -0
- package/dist/ui/Picker.js +24 -0
- package/dist/ui/Prompt.d.ts +1 -2
- package/dist/ui/Prompt.js +2 -2
- package/dist/ui/Spinner.js +11 -5
- package/dist/ui/StatusBar.d.ts +2 -1
- package/dist/ui/StatusBar.js +6 -5
- package/package.json +3 -2
- package/src/agent/approval-json.ts +103 -0
- package/src/agent/approval-native.ts +168 -0
- package/src/agent/approval-store.ts +38 -0
- package/src/agent/approval.ts +94 -0
- package/src/agent/compaction.ts +321 -0
- package/src/agent/context.ts +97 -0
- package/src/agent/guards.ts +1239 -19
- package/src/agent/ignore.ts +147 -0
- package/src/agent/policy/defaults.ts +34 -0
- package/src/agent/policy/egress.ts +335 -0
- package/src/agent/process-tree.ts +114 -0
- package/src/agent/protocol-mode.ts +59 -0
- package/src/agent/protocol.ts +191 -40
- package/src/agent/registry.ts +270 -0
- package/src/agent/runner.ts +486 -0
- package/src/agent/shell-ast.ts +227 -0
- package/src/agent/shell-session.ts +673 -0
- package/src/agent/stream.ts +143 -0
- package/src/agent/tool-schemas.ts +86 -0
- package/src/agent/tools/append_file.ts +30 -0
- package/src/agent/tools/apply_patch.ts +95 -0
- package/src/agent/tools/copy_file.ts +56 -0
- package/src/agent/tools/delete_file.ts +45 -0
- package/src/agent/tools/grep.ts +57 -0
- package/src/agent/tools/index.ts +34 -0
- package/src/agent/tools/list_files.ts +19 -0
- package/src/agent/tools/make_dir.ts +28 -0
- package/src/agent/tools/move_path.ts +83 -0
- package/src/agent/tools/paths.ts +92 -0
- package/src/agent/tools/pwd.ts +12 -0
- package/src/agent/tools/read_file.ts +84 -0
- package/src/agent/tools/read_many.ts +45 -0
- package/src/agent/tools/readers.ts +491 -0
- package/src/agent/tools/replace_in_file.ts +66 -0
- package/src/agent/tools/shell.ts +53 -0
- package/src/agent/tools/stat_path.ts +33 -0
- package/src/agent/tools/types.ts +84 -0
- package/src/agent/tools/validate.ts +104 -0
- package/src/agent/tools/write_file.ts +30 -0
- package/src/agent/tools.ts +3 -377
- package/src/app.ts +853 -170
- package/src/{cli.ts → cli-main.ts} +64 -9
- package/src/commands/about.ts +1 -1
- package/src/commands/attach.ts +16 -0
- package/src/commands/bg.ts +9 -0
- package/src/commands/cancel.ts +10 -0
- package/src/commands/clear.ts +1 -1
- package/src/commands/compact.ts +35 -0
- package/src/commands/context.ts +26 -0
- package/src/commands/edit.ts +37 -0
- package/src/commands/effort.ts +49 -0
- package/src/commands/expand.ts +8 -0
- package/src/commands/index.ts +24 -0
- package/src/commands/jobs.ts +18 -0
- package/src/commands/kill.ts +14 -0
- package/src/commands/login.ts +24 -22
- package/src/commands/logout.ts +8 -16
- package/src/commands/model.ts +10 -22
- package/src/commands/provider.ts +4 -11
- package/src/commands/skills.ts +34 -4
- package/src/commands/steer.ts +13 -0
- package/src/commands/threads.ts +28 -0
- package/src/commands/whoami.ts +6 -5
- package/src/config/store.ts +168 -77
- package/src/config/trust.ts +181 -22
- package/src/headless.ts +225 -0
- package/src/index.ts +19 -3
- package/src/lib/debug.ts +24 -0
- package/src/lib/diagnostics.ts +90 -8
- package/src/lib/highlight-subset.ts +93 -0
- package/src/lib/http.ts +66 -4
- package/src/lib/lifecycle.ts +69 -0
- package/src/lib/markdown.ts +22 -4
- package/src/lib/model-meta.ts +138 -0
- package/src/lib/native-tools.ts +32 -0
- package/src/lib/net.ts +204 -0
- package/src/patch/apply.ts +194 -0
- package/src/patch/parse.ts +131 -0
- package/src/patch/plan.ts +317 -0
- package/src/providers/anthropic.ts +13 -1
- package/src/providers/deepseek.ts +3 -2
- package/src/providers/groq.ts +2 -1
- package/src/providers/index.ts +32 -1
- package/src/providers/mistral.ts +2 -1
- package/src/providers/moonshot.ts +2 -1
- package/src/providers/openai.ts +2 -1
- package/src/providers/openaiCompatible.ts +104 -19
- package/src/providers/openrouter.ts +2 -1
- package/src/providers/qwen.ts +2 -1
- package/src/providers/spec.ts +42 -0
- package/src/providers/xai.ts +2 -1
- package/src/providers/zhipu.ts +2 -1
- package/src/session/log.ts +311 -29
- package/src/session/projection.ts +621 -0
- package/src/skills/manager.ts +140 -18
- package/src/types/highlight-shims.d.ts +14 -0
- package/src/types.ts +79 -2
- package/src/ui/Message.ts +13 -2
- package/src/ui/Picker.ts +24 -0
- package/src/ui/Prompt.ts +2 -2
- package/src/ui/Spinner.ts +11 -5
- package/src/ui/StatusBar.ts +6 -5
- package/tsconfig.json +1 -0
- /package/dist/{cli.d.ts → cli-main.d.ts} +0 -0
package/dist/skills/manager.js
CHANGED
|
@@ -5,21 +5,122 @@
|
|
|
5
5
|
* a SKILL.md file plus optional resource files. FastCode supports three
|
|
6
6
|
* install sources:
|
|
7
7
|
*
|
|
8
|
-
* 1.
|
|
9
|
-
* `/skills install pdf` → resolves via the registry
|
|
10
|
-
* `/skills install owner/repo/skill` → fetches raw SKILL.md
|
|
11
|
-
* 2. Direct https URLs ending in SKILL.md.
|
|
8
|
+
* 1. A registry configured via FASTCODE_SKILLS_REGISTRY or skillsRegistry
|
|
9
|
+
* `/skills install pdf` → resolves via the configured registry
|
|
10
|
+
* `/skills install owner/repo/skill` → fetches raw SKILL.md from the registry
|
|
11
|
+
* 2. Direct https URLs ending in SKILL.md (no registry required).
|
|
12
12
|
* 3. Local paths (just symlinks into ~/.fastcode/skills/).
|
|
13
13
|
*
|
|
14
14
|
* Installed skills can be enabled per-session and are then stitched into
|
|
15
15
|
* the system prompt at chat time, exactly like Claude does internally.
|
|
16
16
|
*/
|
|
17
|
+
import { createHash } from "node:crypto";
|
|
17
18
|
import { readFileSync, writeFileSync, existsSync, readdirSync, rmSync, mkdirSync, } from "node:fs";
|
|
18
19
|
import { join } from "node:path";
|
|
19
20
|
import { getPaths } from "../config/paths.js";
|
|
21
|
+
import { invalidateConfigCache } from "../config/store.js";
|
|
20
22
|
import { fetchJson } from "../lib/http.js";
|
|
21
23
|
import { parseSkill } from "./parser.js";
|
|
22
|
-
const
|
|
24
|
+
const SOURCE_FILE = ".fastcode-source";
|
|
25
|
+
const INTEGRITY_VERSION = 1;
|
|
26
|
+
const REGISTRY_REQUIRED = "No skills registry configured. Set one with `/skills registry <url>` or FASTCODE_SKILLS_REGISTRY.";
|
|
27
|
+
/**
|
|
28
|
+
* Pick the skills registry without treating an empty environment variable as
|
|
29
|
+
* "configured". `??` would keep `""` and make env overrides silently break;
|
|
30
|
+
* explicit null/empty checks keep `""` and `" "` on the config path. There is
|
|
31
|
+
* intentionally no built-in default registry.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveRegistry(envValue, configValue) {
|
|
34
|
+
const env = typeof envValue === "string" && envValue.trim() ? envValue.trim() : "";
|
|
35
|
+
const configured = typeof configValue === "string" && configValue.trim() ? configValue.trim() : "";
|
|
36
|
+
return (env || configured).replace(/\/+$/, "");
|
|
37
|
+
}
|
|
38
|
+
function requireRegistry(registry) {
|
|
39
|
+
if (!registry)
|
|
40
|
+
throw new Error(REGISTRY_REQUIRED);
|
|
41
|
+
return registry;
|
|
42
|
+
}
|
|
43
|
+
export function hashSkillDirectory(folder) {
|
|
44
|
+
const entries = skillFiles(folder).sort();
|
|
45
|
+
return createHash("sha256").update(entries.join("\n")).digest("hex");
|
|
46
|
+
}
|
|
47
|
+
function skillFiles(folder, prefix = "") {
|
|
48
|
+
const out = [];
|
|
49
|
+
let items;
|
|
50
|
+
try {
|
|
51
|
+
items = readdirSync(folder, { withFileTypes: true });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
for (const item of items) {
|
|
57
|
+
if (item.name === SOURCE_FILE)
|
|
58
|
+
continue;
|
|
59
|
+
const full = join(folder, item.name);
|
|
60
|
+
const rel = prefix ? prefix + "/" + item.name : item.name;
|
|
61
|
+
if (item.isDirectory()) {
|
|
62
|
+
out.push(...skillFiles(full, rel));
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (!item.isFile())
|
|
66
|
+
continue;
|
|
67
|
+
const digest = createHash("sha256").update(readFileSync(full)).digest("hex");
|
|
68
|
+
out.push(rel + "\0" + digest);
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
function readSourceMeta(folder) {
|
|
73
|
+
const sourcePath = join(folder, SOURCE_FILE);
|
|
74
|
+
if (!existsSync(sourcePath))
|
|
75
|
+
return { source: "local", legacy: true };
|
|
76
|
+
const raw = readFileSync(sourcePath, "utf8").trim();
|
|
77
|
+
if (raw.startsWith("{")) {
|
|
78
|
+
try {
|
|
79
|
+
const parsed = JSON.parse(raw);
|
|
80
|
+
return {
|
|
81
|
+
source: typeof parsed.source === "string" ? parsed.source : "local",
|
|
82
|
+
sha256: typeof parsed.sha256 === "string" ? parsed.sha256 : undefined,
|
|
83
|
+
legacy: typeof parsed.sha256 !== "string",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Fall through and treat the file as a legacy plain-text source.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { source: raw || "local", legacy: true };
|
|
91
|
+
}
|
|
92
|
+
function writeSourceMeta(folder, source) {
|
|
93
|
+
const sha256 = hashSkillDirectory(folder);
|
|
94
|
+
const payload = {
|
|
95
|
+
version: INTEGRITY_VERSION,
|
|
96
|
+
algorithm: "sha256",
|
|
97
|
+
source,
|
|
98
|
+
sha256,
|
|
99
|
+
};
|
|
100
|
+
writeFileSync(join(folder, SOURCE_FILE), JSON.stringify(payload, null, 2));
|
|
101
|
+
return sha256;
|
|
102
|
+
}
|
|
103
|
+
export function rebaselineSkills(names) {
|
|
104
|
+
const installed = listInstalledSkills();
|
|
105
|
+
const wanted = names && names.length > 0 ? new Set(names) : undefined;
|
|
106
|
+
const results = [];
|
|
107
|
+
let changed = false;
|
|
108
|
+
for (const skill of installed) {
|
|
109
|
+
if (wanted && !wanted.has(skill.name) && !wanted.has(basename(skill.path)))
|
|
110
|
+
continue;
|
|
111
|
+
try {
|
|
112
|
+
writeSourceMeta(skill.path, skill.source === "local" ? "local" : skill.source);
|
|
113
|
+
results.push({ name: skill.name, ok: true });
|
|
114
|
+
changed = true;
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
results.push({ name: skill.name, ok: false, warning: err?.message ?? String(err) });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (changed)
|
|
121
|
+
invalidateConfigCache();
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
23
124
|
/** List skills currently installed under ~/.fastcode/skills. */
|
|
24
125
|
export function listInstalledSkills() {
|
|
25
126
|
const { skills } = getPaths();
|
|
@@ -35,16 +136,20 @@ export function listInstalledSkills() {
|
|
|
35
136
|
continue;
|
|
36
137
|
const raw = readFileSync(md, "utf8");
|
|
37
138
|
const parsed = parseSkill(raw, dir.name);
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
139
|
+
const meta = readSourceMeta(folder);
|
|
140
|
+
const actualHash = hashSkillDirectory(folder);
|
|
141
|
+
const integrity = !meta.sha256
|
|
142
|
+
? "unverified"
|
|
143
|
+
: actualHash === meta.sha256 ? "ok" : "drift";
|
|
42
144
|
out.push({
|
|
43
145
|
name: parsed.name || dir.name,
|
|
44
146
|
description: parsed.description,
|
|
45
|
-
source,
|
|
147
|
+
source: meta.source,
|
|
46
148
|
path: folder,
|
|
47
149
|
body: parsed.body,
|
|
150
|
+
integrity,
|
|
151
|
+
sha256: actualHash,
|
|
152
|
+
lockedHash: meta.sha256,
|
|
48
153
|
});
|
|
49
154
|
}
|
|
50
155
|
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -56,7 +161,7 @@ export function getSkill(name) {
|
|
|
56
161
|
/** Install a skill. Returns the parsed manifest on success. */
|
|
57
162
|
export async function installSkill(spec, opts = {}) {
|
|
58
163
|
const { skills } = getPaths();
|
|
59
|
-
const registry = (opts.registry
|
|
164
|
+
const registry = resolveRegistry(process.env["FASTCODE_SKILLS_REGISTRY"], opts.registry);
|
|
60
165
|
let parsed;
|
|
61
166
|
let source;
|
|
62
167
|
let folderName;
|
|
@@ -68,7 +173,8 @@ export async function installSkill(spec, opts = {}) {
|
|
|
68
173
|
}
|
|
69
174
|
else if (looksLikeRepoPath(spec)) {
|
|
70
175
|
// owner/repo or owner/repo/skill — fetch via registry's raw endpoint.
|
|
71
|
-
const
|
|
176
|
+
const base = requireRegistry(registry);
|
|
177
|
+
const url = `${base}/${spec}?format=md`;
|
|
72
178
|
const body = await fetchText(url);
|
|
73
179
|
parsed = parseSkill(body, parts(spec).pop() ?? spec);
|
|
74
180
|
source = url;
|
|
@@ -76,11 +182,12 @@ export async function installSkill(spec, opts = {}) {
|
|
|
76
182
|
}
|
|
77
183
|
else {
|
|
78
184
|
// Single-token name → search the registry.
|
|
79
|
-
const
|
|
185
|
+
const base = requireRegistry(registry);
|
|
186
|
+
const hits = await searchRegistry(spec, base);
|
|
80
187
|
const hit = hits[0];
|
|
81
188
|
if (!hit)
|
|
82
|
-
throw new Error(`No skill found for "${spec}" in ${
|
|
83
|
-
const url = hit.fetchUrl ?? `${
|
|
189
|
+
throw new Error(`No skill found for "${spec}" in ${base}`);
|
|
190
|
+
const url = hit.fetchUrl ?? `${base}/${hit.slug}?format=md`;
|
|
84
191
|
const body = await fetchText(url);
|
|
85
192
|
parsed = parseSkill(body, hit.name);
|
|
86
193
|
source = url;
|
|
@@ -94,13 +201,14 @@ export async function installSkill(spec, opts = {}) {
|
|
|
94
201
|
rmSync(targetDir, { recursive: true, force: true });
|
|
95
202
|
mkdirSync(targetDir, { recursive: true });
|
|
96
203
|
writeFileSync(join(targetDir, "SKILL.md"), reassemble(parsed));
|
|
97
|
-
|
|
204
|
+
writeSourceMeta(targetDir, source);
|
|
98
205
|
return {
|
|
99
206
|
name: parsed.name || folderName,
|
|
100
207
|
description: parsed.description,
|
|
101
208
|
source,
|
|
102
209
|
path: targetDir,
|
|
103
210
|
body: parsed.body,
|
|
211
|
+
integrity: "ok",
|
|
104
212
|
};
|
|
105
213
|
}
|
|
106
214
|
/** Remove an installed skill by name or folder. */
|
|
@@ -125,8 +233,10 @@ export function uninstallSkill(name) {
|
|
|
125
233
|
return false;
|
|
126
234
|
}
|
|
127
235
|
/** Search the registry for skills matching a query. */
|
|
128
|
-
export async function searchRegistry(query, registry
|
|
129
|
-
const base =
|
|
236
|
+
export async function searchRegistry(query, registry) {
|
|
237
|
+
const base = resolveRegistry(process.env["FASTCODE_SKILLS_REGISTRY"], registry);
|
|
238
|
+
if (!base)
|
|
239
|
+
return [];
|
|
130
240
|
try {
|
|
131
241
|
const json = await fetchJson(`${base}/api/v1/skills/search?q=${encodeURIComponent(query)}`);
|
|
132
242
|
return json.data ?? [];
|
|
@@ -145,6 +255,13 @@ export function buildSkillsPrompt(enabled) {
|
|
|
145
255
|
const skill = installed.find((s) => s.name === name || basename(s.path) === name);
|
|
146
256
|
if (!skill)
|
|
147
257
|
continue;
|
|
258
|
+
if (skill.integrity !== "ok") {
|
|
259
|
+
const reason = skill.integrity === "drift"
|
|
260
|
+
? "content drift detected"
|
|
261
|
+
: "no integrity baseline (legacy install)";
|
|
262
|
+
process.stderr.write(`skill ${skill.name} ${reason}; disabled. Run /skills verify ${skill.name} --confirm to re-baseline.\n`);
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
148
265
|
chunks.push(`<skill name="${skill.name}">\n${skill.body.trim()}\n</skill>`);
|
|
149
266
|
}
|
|
150
267
|
if (chunks.length === 0)
|
package/dist/types.d.ts
CHANGED
|
@@ -5,10 +5,26 @@
|
|
|
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";
|
|
8
|
+
export type Role = "system" | "user" | "assistant" | "tool";
|
|
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
|
+
}
|
|
9
23
|
export interface ChatMessage {
|
|
10
24
|
role: Role;
|
|
11
25
|
content: string;
|
|
26
|
+
toolCalls?: NativeToolCall[];
|
|
27
|
+
toolCallId?: string;
|
|
12
28
|
}
|
|
13
29
|
export interface ChatRequest {
|
|
14
30
|
model: string;
|
|
@@ -19,14 +35,26 @@ export interface ChatRequest {
|
|
|
19
35
|
temperature?: number;
|
|
20
36
|
/** Soft cap for output tokens. */
|
|
21
37
|
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;
|
|
22
44
|
/** AbortSignal for cancellation (Esc / Ctrl+C). */
|
|
23
45
|
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[];
|
|
24
50
|
}
|
|
25
51
|
export interface ChatChunk {
|
|
26
52
|
/** Token text appended to the response. */
|
|
27
53
|
delta: string;
|
|
28
54
|
/** True on the final chunk. */
|
|
29
55
|
done: boolean;
|
|
56
|
+
/** Complete native tool calls (OpenAI-style) on the final chunk. */
|
|
57
|
+
toolCalls?: NativeToolCall[];
|
|
30
58
|
/** Provider-specific usage info on the final chunk. */
|
|
31
59
|
usage?: {
|
|
32
60
|
inputTokens?: number;
|
|
@@ -63,6 +91,25 @@ export interface Provider {
|
|
|
63
91
|
listModels(apiKey: string | undefined): Promise<ProviderModel[]>;
|
|
64
92
|
/** Stream a chat completion. */
|
|
65
93
|
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;
|
|
66
113
|
}
|
|
67
114
|
export interface SlashCommand {
|
|
68
115
|
name: string;
|
|
@@ -74,6 +121,15 @@ export interface SlashCommand {
|
|
|
74
121
|
/** Execute the command. Return text to render, or undefined for no output. */
|
|
75
122
|
run(ctx: CommandContext): Promise<CommandResult> | CommandResult;
|
|
76
123
|
}
|
|
124
|
+
export interface CommandCompaction {
|
|
125
|
+
summaryRef?: string;
|
|
126
|
+
source: "local" | "server" | "none";
|
|
127
|
+
beforeTokens: number;
|
|
128
|
+
afterTokens: number;
|
|
129
|
+
droppedMessages: number;
|
|
130
|
+
keepMessages: number;
|
|
131
|
+
reason?: "threshold" | "heap" | "manual";
|
|
132
|
+
}
|
|
77
133
|
export interface CommandResult {
|
|
78
134
|
/** Text rendered as a system message in the transcript. */
|
|
79
135
|
message?: string;
|
|
@@ -81,6 +137,12 @@ export interface CommandResult {
|
|
|
81
137
|
silent?: boolean;
|
|
82
138
|
/** Quit the app after this command. */
|
|
83
139
|
quit?: boolean;
|
|
140
|
+
/** Open an interactive picker after the command runs. */
|
|
141
|
+
picker?: PickerRequest;
|
|
142
|
+
/** Manual /compact result; the app appends the matching compacted fact. */
|
|
143
|
+
compacted?: CommandCompaction;
|
|
144
|
+
/** /clear result; the app appends a cleared fact so resume does not resurrect history. */
|
|
145
|
+
cleared?: boolean;
|
|
84
146
|
}
|
|
85
147
|
export interface CommandContext {
|
|
86
148
|
args: string[];
|
|
@@ -101,6 +163,10 @@ export interface AppStateSnapshot {
|
|
|
101
163
|
enabledSkills: string[];
|
|
102
164
|
enabledPlugins: string[];
|
|
103
165
|
skillsRegistry: string;
|
|
166
|
+
reasoningEffort: ReasoningEffort;
|
|
167
|
+
expanded: boolean;
|
|
168
|
+
busy: boolean;
|
|
169
|
+
draft: string;
|
|
104
170
|
}
|
|
105
171
|
export interface AppActions {
|
|
106
172
|
setProvider(id: string): void;
|
|
@@ -109,16 +175,24 @@ export interface AppActions {
|
|
|
109
175
|
setAgentMode(enabled: boolean): void;
|
|
110
176
|
setSystemPrompt(prompt: string): void;
|
|
111
177
|
setSkillsRegistry(url: string): void;
|
|
178
|
+
setReasoningEffort(effort: ReasoningEffort): void;
|
|
179
|
+
setShellPoolSize(size: number): void;
|
|
112
180
|
enableSkill(name: string): void;
|
|
113
181
|
disableSkill(name: string): void;
|
|
114
182
|
enablePlugin(name: string): void;
|
|
115
183
|
disablePlugin(name: string): void;
|
|
116
184
|
clearHistory(): void;
|
|
185
|
+
replaceHistory(messages: ChatMessage[]): void;
|
|
186
|
+
cancelRun(): void;
|
|
187
|
+
steer(text: string): void;
|
|
188
|
+
setExpanded(value: boolean): void;
|
|
189
|
+
setInput(text: string): void;
|
|
117
190
|
pushSystemMessage(text: string): void;
|
|
118
191
|
/** Begin the guided API-key flow (choose provider → model → key). */
|
|
119
192
|
startLogin(options: {
|
|
120
193
|
provider?: string;
|
|
121
194
|
model?: string;
|
|
195
|
+
flow?: "provider" | "model" | "login";
|
|
122
196
|
}): void;
|
|
123
197
|
}
|
|
124
198
|
export interface SkillManifest {
|
package/dist/ui/Message.d.ts
CHANGED
|
@@ -1,7 +1 @@
|
|
|
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>>;
|
|
1
|
+
export declare const MessageBubble: ({ theme, role, content, streaming, markdown }: any) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
package/dist/ui/Message.js
CHANGED
|
@@ -6,8 +6,19 @@ const SIGIL = {
|
|
|
6
6
|
assistant: "▍ FastCode",
|
|
7
7
|
system: "✦ system",
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
const markdownCache = new Map();
|
|
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 }) => {
|
|
10
21
|
const color = role === "user" ? theme.user : role === "assistant" ? theme.assistant : theme.system;
|
|
11
|
-
const display = markdown ?
|
|
22
|
+
const display = markdown ? cachedMarkdown(content) : content;
|
|
12
23
|
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 ? "…" : "") }) })] }));
|
|
13
24
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Presentational picker used by /model, /provider, and /effort.
|
|
4
|
+
*
|
|
5
|
+
* Keyboard handling lives in App so it can suspend the normal prompt input and
|
|
6
|
+
* so every picker behaves the same. This component only renders the window of
|
|
7
|
+
* items around the active index.
|
|
8
|
+
*/
|
|
9
|
+
import { Box, Text } from "ink";
|
|
10
|
+
const WINDOW = 10;
|
|
11
|
+
export const Picker = ({ theme, title, items, index, current, hint }) => {
|
|
12
|
+
const max = Math.max(0, items.length - 1);
|
|
13
|
+
const active = Math.max(0, Math.min(index, max));
|
|
14
|
+
const start = Math.max(0, Math.min(active - Math.floor(WINDOW / 2), Math.max(0, items.length - WINDOW)));
|
|
15
|
+
const visible = items.slice(start, start + WINDOW);
|
|
16
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.accent, paddingX: 1, children: [_jsx(Text, { color: theme.accent, bold: true, children: title }), ...visible.map((item, offset) => {
|
|
17
|
+
const itemIndex = start + offset;
|
|
18
|
+
const selected = itemIndex === active;
|
|
19
|
+
const marker = selected ? "\u276F" : " ";
|
|
20
|
+
const number = itemIndex < 9 ? String(itemIndex + 1) : " ";
|
|
21
|
+
const isCurrent = current !== undefined && item.value === current;
|
|
22
|
+
return (_jsxs(Text, { color: selected ? theme.accent : theme.muted, children: [marker, " ", number, ". ", isCurrent ? "\u25CF " : " ", item.label, item.hint ? _jsxs(Text, { color: theme.muted, children: [" ", item.hint] }) : null] }, item.value));
|
|
23
|
+
}), items.length > WINDOW ? (_jsx(Text, { color: theme.muted, children: ` … ${start + 1}-${start + visible.length} of ${items.length}` })) : null, _jsx(Text, { color: theme.muted, children: hint ?? " \u2191/\u2193 select \u00B7 1-9 jump \u00B7 Enter confirm \u00B7 Esc cancel" })] }));
|
|
24
|
+
};
|
package/dist/ui/Prompt.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
export declare const Prompt: ({ theme, value, onChange, onSubmit, disabled, placeholder,
|
|
1
|
+
export declare const Prompt: ({ theme, value, onChange, onSubmit, disabled, placeholder, 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;
|
|
9
8
|
mask: any;
|
|
10
9
|
}) => 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,
|
|
18
|
+
export const Prompt = ({ theme, value, onChange, onSubmit, disabled, placeholder, 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: true, 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,13 +21,19 @@ 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;
|
|
24
32
|
useEffect(() => {
|
|
25
|
-
|
|
26
|
-
return;
|
|
27
|
-
const id = setInterval(() => setTick((t) => t + 1), 80);
|
|
33
|
+
const id = setInterval(() => setTick((t) => t + 1), interval);
|
|
28
34
|
return () => clearInterval(id);
|
|
29
|
-
}, [
|
|
30
|
-
const frame =
|
|
35
|
+
}, [interval]);
|
|
36
|
+
const frame = FRAMES[tick % FRAMES.length];
|
|
31
37
|
const verb = label ?? VERBS[Math.floor(tick / 24) % VERBS.length];
|
|
32
38
|
return (_jsxs(Text, { color: theme.accent, children: [frame, " ", _jsxs(Text, { color: theme.muted, children: [verb, "\u2026"] })] }));
|
|
33
39
|
};
|
package/dist/ui/StatusBar.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const StatusBar: ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount, hint, }: {
|
|
1
|
+
export declare const StatusBar: ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount, reasoningEffort, hint, }: {
|
|
2
2
|
theme: any;
|
|
3
3
|
providerId: any;
|
|
4
4
|
model: any;
|
|
@@ -6,5 +6,6 @@ export declare const StatusBar: ({ theme, providerId, model, inputTokens, output
|
|
|
6
6
|
outputTokens: any;
|
|
7
7
|
costUsd: any;
|
|
8
8
|
enabledSkillCount: any;
|
|
9
|
+
reasoningEffort: any;
|
|
9
10
|
hint: any;
|
|
10
11
|
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
package/dist/ui/StatusBar.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
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, hint, }) => {
|
|
4
|
+
export const StatusBar = ({ theme, providerId, model, inputTokens, outputTokens, costUsd, enabledSkillCount, reasoningEffort, 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
|
-
: hint ?? "/help
|
|
11
|
+
const effort = reasoningEffort && reasoningEffort !== "auto" ? `effort:${reasoningEffort}` : "";
|
|
12
|
+
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 && effort ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.muted, children: " \u00B7 " }), effort] })) : null, !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
|
|
13
|
+
? `${effort ? effort + " \u00B7 " : ""}${platformLabel()} \u00B7 skills:${enabledSkillCount} \u00B7 ${hint ?? "/help \u00B7 esc \u00B7 ctrl+c"}`
|
|
14
|
+
: hint ?? "/help \u00B7 esc cancel \u00B7 ctrl+c quit" })] }));
|
|
14
15
|
};
|
|
15
16
|
function truncate(value, max) {
|
|
16
17
|
if (value.length <= max)
|
|
17
18
|
return value;
|
|
18
|
-
return `${value.slice(0, Math.max(1, max - 1))}
|
|
19
|
+
return `${value.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
19
20
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datename/fastcode-termux",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8-beta.0",
|
|
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": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"node": ">=18.17"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"build": "tsc -p tsconfig.json && node scripts/build.mjs",
|
|
24
|
+
"build": "tsc -p tsconfig.build.json && node scripts/build.mjs",
|
|
25
25
|
"build:bundle": "node scripts/build.mjs",
|
|
26
26
|
"dev": "tsx src/index.ts",
|
|
27
27
|
"start": "node bin/fastcode.mjs",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"url": "https://github.com/dateName/fastcode-termux/issues"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
+
"bash-parser": "^0.5.0",
|
|
68
69
|
"boxen": "^7.1.1",
|
|
69
70
|
"chalk": "^5.3.0",
|
|
70
71
|
"cli-highlight": "^2.1.11",
|