@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/config/store.js
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
* edit it from `nano ~/.fastcode/config.json` if needed. Atomic writes prevent
|
|
6
6
|
* partial files on Ctrl+C.
|
|
7
7
|
*
|
|
8
|
-
* API keys are
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* API keys are NOT a single global string: each one is scoped to a concrete
|
|
9
|
+
* "provider + model" pair. auth.json stores one credential per
|
|
10
|
+
* `<provider>::<model>` scope, and a stored key is only used when the current
|
|
11
|
+
* provider AND model match that scope. The old provider-only format is read as
|
|
12
|
+
* "legacy": it is shown back to the user but never used silently, because a
|
|
13
|
+
* provider-only key does not tell us which model it was meant for.
|
|
12
14
|
*/
|
|
13
|
-
import { readFileSync, writeFileSync, existsSync, renameSync
|
|
15
|
+
import { readFileSync, writeFileSync, existsSync, renameSync } from "node:fs";
|
|
14
16
|
import { join, dirname } from "node:path";
|
|
15
17
|
import { getPaths, lockdown, ensureDir } from "./paths.js";
|
|
16
18
|
import { DEFAULT_THEME } from "./themes.js";
|
|
@@ -27,26 +29,7 @@ export const DEFAULT_CONFIG = {
|
|
|
27
29
|
enabledPlugins: [],
|
|
28
30
|
skillsRegistry: "https://skillshub.wtf",
|
|
29
31
|
lifetimeCostUsd: 0,
|
|
30
|
-
/**
|
|
31
|
-
* Extra directories the file tools may read and write outside the project
|
|
32
|
-
* root. Relative entries are resolved against the project root; `~/` is
|
|
33
|
-
* expanded against the user's home directory.
|
|
34
|
-
*/
|
|
35
|
-
sharedDirs: [],
|
|
36
|
-
/** Maximum agent tool turns before the loop asks the user to continue. */
|
|
37
|
-
maxAgentTurns: 24,
|
|
38
|
-
/** Abort a stream that receives no data for this long (ms). */
|
|
39
|
-
requestIdleTimeoutMs: 60_000,
|
|
40
|
-
/** Approximate character budget before history compaction kicks in. */
|
|
41
|
-
contextBudgetChars: 400_000,
|
|
42
|
-
/** Thinking depth: auto = send nothing, provider default. */
|
|
43
|
-
reasoningEffort: "auto",
|
|
44
|
-
/** Cached per-provider/model capabilities (native vs pseudo tool calling). */
|
|
45
|
-
capabilities: {
|
|
46
|
-
toolCalling: {},
|
|
47
|
-
},
|
|
48
32
|
};
|
|
49
|
-
export const AUTH_VERSION = 3;
|
|
50
33
|
export function loadConfig() {
|
|
51
34
|
const { config } = getPaths();
|
|
52
35
|
if (!existsSync(config))
|
|
@@ -63,97 +46,58 @@ export function saveConfig(cfg) {
|
|
|
63
46
|
const { config } = getPaths();
|
|
64
47
|
atomicWrite(config, JSON.stringify(cfg, null, 2));
|
|
65
48
|
}
|
|
66
|
-
/** Composite id
|
|
49
|
+
/** Composite scope id for a provider + model credential. */
|
|
67
50
|
export function scopeId(providerId, model) {
|
|
68
51
|
return `${providerId}::${model}`;
|
|
69
52
|
}
|
|
70
|
-
/** Pick the most recently saved credential when several legacy scopes map to one provider. */
|
|
71
|
-
function keepNewest(keys, credential) {
|
|
72
|
-
const existing = keys[credential.provider];
|
|
73
|
-
if (!existing) {
|
|
74
|
-
keys[credential.provider] = credential;
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const previous = Date.parse(existing.addedAt || "") || 0;
|
|
78
|
-
const next = Date.parse(credential.addedAt || "") || 0;
|
|
79
|
-
if (next > previous)
|
|
80
|
-
keys[credential.provider] = credential;
|
|
81
|
-
}
|
|
82
|
-
let migrationChecked = false;
|
|
83
53
|
export function loadAuth() {
|
|
84
54
|
const { auth } = getPaths();
|
|
85
|
-
const empty = { version:
|
|
55
|
+
const empty = { version: 2, keys: {}, legacy: {} };
|
|
86
56
|
if (!existsSync(auth))
|
|
87
57
|
return empty;
|
|
88
|
-
let raw;
|
|
89
58
|
try {
|
|
90
|
-
raw = JSON.parse(readFileSync(auth, "utf8"));
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
provider,
|
|
110
|
-
model,
|
|
111
|
-
key: value.key,
|
|
112
|
-
addedAt: typeof value.addedAt === "string" ? value.addedAt : "",
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
else if (typeof value === "string" && value.trim()) {
|
|
116
|
-
// v1: keys were plain provider -> key strings.
|
|
117
|
-
keepNewest(keys, { provider: id, key: value, addedAt: "" });
|
|
118
|
-
migrated = true;
|
|
59
|
+
const raw = JSON.parse(readFileSync(auth, "utf8"));
|
|
60
|
+
const keys = {};
|
|
61
|
+
const legacy = {};
|
|
62
|
+
const source = raw && typeof raw === "object" ? (raw.keys ?? {}) : {};
|
|
63
|
+
for (const [id, value] of Object.entries(source)) {
|
|
64
|
+
if (value && typeof value === "object" && typeof value.key === "string") {
|
|
65
|
+
const [idProvider, idModel] = id.split("::");
|
|
66
|
+
const provider = value.provider || idProvider || id;
|
|
67
|
+
const model = value.model || idModel || "";
|
|
68
|
+
keys[scopeId(provider, model)] = {
|
|
69
|
+
provider,
|
|
70
|
+
model,
|
|
71
|
+
key: value.key,
|
|
72
|
+
addedAt: value.addedAt ?? "",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
else if (typeof value === "string" && value.trim()) {
|
|
76
|
+
legacy[id] = value;
|
|
77
|
+
}
|
|
119
78
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// Provider-only keys are exactly what v3 wants: migrate instead
|
|
125
|
-
// of leaving them unusable.
|
|
126
|
-
keepNewest(keys, { provider, key: value, addedAt: "" });
|
|
127
|
-
migrated = true;
|
|
79
|
+
if (raw && typeof raw === "object" && raw.legacy && typeof raw.legacy === "object") {
|
|
80
|
+
for (const [id, value] of Object.entries(raw.legacy)) {
|
|
81
|
+
if (typeof value === "string" && value.trim())
|
|
82
|
+
legacy[id] = value;
|
|
128
83
|
}
|
|
129
84
|
}
|
|
85
|
+
return { version: 2, keys, legacy };
|
|
130
86
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// Keep the pre-migration file so a user with several old model
|
|
134
|
-
// keys can recover a credential we had to collapse.
|
|
135
|
-
const backup = auth + ".v2.bak";
|
|
136
|
-
if (!existsSync(backup))
|
|
137
|
-
copyFileSync(auth, backup);
|
|
138
|
-
writeAuth({ version: AUTH_VERSION, keys, legacy });
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
// Read-only home (or locked file): keep the migrated view in memory.
|
|
142
|
-
}
|
|
87
|
+
catch {
|
|
88
|
+
return empty;
|
|
143
89
|
}
|
|
144
|
-
migrationChecked = true;
|
|
145
|
-
return { version: AUTH_VERSION, keys, legacy };
|
|
146
90
|
}
|
|
147
|
-
function
|
|
91
|
+
export function saveAuth(store) {
|
|
148
92
|
const { auth } = getPaths();
|
|
149
|
-
|
|
93
|
+
const payload = { version: 2, keys: store.keys };
|
|
94
|
+
if (Object.keys(store.legacy).length > 0)
|
|
95
|
+
payload.legacy = store.legacy;
|
|
96
|
+
atomicWrite(auth, JSON.stringify(payload, null, 2));
|
|
150
97
|
lockdown(auth);
|
|
151
98
|
}
|
|
152
|
-
export function
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
export function getCredential(providerId, _model) {
|
|
156
|
-
return loadAuth().keys[providerId];
|
|
99
|
+
export function getCredential(providerId, model) {
|
|
100
|
+
return loadAuth().keys[scopeId(providerId, model)];
|
|
157
101
|
}
|
|
158
102
|
export function listCredentials() {
|
|
159
103
|
return Object.values(loadAuth().keys);
|
|
@@ -164,7 +108,7 @@ export function listLegacy() {
|
|
|
164
108
|
export function getLegacy(providerId) {
|
|
165
109
|
return loadAuth().legacy[providerId];
|
|
166
110
|
}
|
|
167
|
-
/** Save/replace the provider
|
|
111
|
+
/** Save/replace the credential for one provider+model scope (drops the legacy key). */
|
|
168
112
|
export function setCredential(providerId, model, key) {
|
|
169
113
|
const store = loadAuth();
|
|
170
114
|
const credential = {
|
|
@@ -173,26 +117,29 @@ export function setCredential(providerId, model, key) {
|
|
|
173
117
|
key: key.trim(),
|
|
174
118
|
addedAt: new Date().toISOString(),
|
|
175
119
|
};
|
|
176
|
-
store.keys[providerId] = credential;
|
|
120
|
+
store.keys[scopeId(providerId, model)] = credential;
|
|
177
121
|
delete store.legacy[providerId];
|
|
178
122
|
saveAuth(store);
|
|
179
123
|
return credential;
|
|
180
124
|
}
|
|
181
|
-
export function removeCredential(providerId,
|
|
125
|
+
export function removeCredential(providerId, model) {
|
|
182
126
|
const store = loadAuth();
|
|
183
|
-
|
|
127
|
+
const id = scopeId(providerId, model);
|
|
128
|
+
if (!store.keys[id])
|
|
184
129
|
return false;
|
|
185
|
-
delete store.keys[
|
|
130
|
+
delete store.keys[id];
|
|
186
131
|
saveAuth(store);
|
|
187
132
|
return true;
|
|
188
133
|
}
|
|
189
|
-
/** Remove
|
|
134
|
+
/** Remove every credential for a provider (all models) plus its legacy key. */
|
|
190
135
|
export function removeCredentialsForProvider(providerId) {
|
|
191
136
|
const store = loadAuth();
|
|
192
137
|
let removed = 0;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
138
|
+
for (const id of Object.keys(store.keys)) {
|
|
139
|
+
if (store.keys[id].provider === providerId) {
|
|
140
|
+
delete store.keys[id];
|
|
141
|
+
removed += 1;
|
|
142
|
+
}
|
|
196
143
|
}
|
|
197
144
|
if (store.legacy[providerId]) {
|
|
198
145
|
delete store.legacy[providerId];
|
|
@@ -212,16 +159,16 @@ export function maskKey(key) {
|
|
|
212
159
|
return value.slice(0, 3) + "****" + value.slice(-4);
|
|
213
160
|
}
|
|
214
161
|
/**
|
|
215
|
-
* Resolve the key to use for a provider:
|
|
216
|
-
* 1. the
|
|
162
|
+
* Resolve the key to use for a specific provider+model:
|
|
163
|
+
* 1. the scoped credential in auth.json (exact provider+model match), then
|
|
217
164
|
* 2. the provider's environment variable (provider-scoped, any model), and
|
|
218
|
-
* 3.
|
|
165
|
+
* 3. report an "unbound" legacy key instead of using it silently.
|
|
219
166
|
*/
|
|
220
|
-
export function resolveApiKey(providerId,
|
|
167
|
+
export function resolveApiKey(providerId, model, envVars) {
|
|
221
168
|
const store = loadAuth();
|
|
222
|
-
const
|
|
223
|
-
if (
|
|
224
|
-
return { status: "ok", key:
|
|
169
|
+
const scoped = store.keys[scopeId(providerId, model)];
|
|
170
|
+
if (scoped && scoped.key)
|
|
171
|
+
return { status: "ok", key: scoped.key, source: "file" };
|
|
225
172
|
for (const envVar of envVars ?? []) {
|
|
226
173
|
const value = process.env[envVar];
|
|
227
174
|
if (value && value.trim())
|
|
@@ -234,9 +181,10 @@ export function resolveApiKey(providerId, _model, envVars) {
|
|
|
234
181
|
/** Best-effort key for a provider regardless of model (used to list models). */
|
|
235
182
|
export function resolveProviderKey(providerId, envVars) {
|
|
236
183
|
const store = loadAuth();
|
|
237
|
-
const credential
|
|
238
|
-
|
|
239
|
-
|
|
184
|
+
for (const credential of Object.values(store.keys)) {
|
|
185
|
+
if (credential.provider === providerId && credential.key)
|
|
186
|
+
return { key: credential.key, source: "file" };
|
|
187
|
+
}
|
|
240
188
|
for (const envVar of envVars ?? []) {
|
|
241
189
|
const value = process.env[envVar];
|
|
242
190
|
if (value && value.trim())
|
package/dist/config/trust.d.ts
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
export interface TrustToolEntry extends TrustPathEntry {
|
|
6
|
-
catalogHash: string;
|
|
7
|
-
}
|
|
8
|
-
export interface TrustStore {
|
|
9
|
-
version: 1;
|
|
10
|
-
tools: Record<string, TrustToolEntry>;
|
|
11
|
-
paths: Record<string, TrustPathEntry>;
|
|
12
|
-
}
|
|
13
|
-
export declare function normalizeProjectPath(dir: string): string;
|
|
14
|
-
export declare function loadTrust(): TrustStore;
|
|
1
|
+
export declare function normalizeProjectPath(dir: any): string;
|
|
2
|
+
export declare function loadTrust(): {
|
|
3
|
+
trusted: any;
|
|
4
|
+
};
|
|
15
5
|
export declare function trustAllEnabled(): boolean;
|
|
16
|
-
export declare function isTrusted(dir:
|
|
17
|
-
export declare function trustProject(dir:
|
|
18
|
-
export declare function untrustProject(dir:
|
|
19
|
-
export declare function listTrusted():
|
|
20
|
-
path: string;
|
|
21
|
-
addedAt: string;
|
|
22
|
-
}>;
|
|
6
|
+
export declare function isTrusted(dir: any): any;
|
|
7
|
+
export declare function trustProject(dir: any): string;
|
|
8
|
+
export declare function untrustProject(dir: any): boolean;
|
|
9
|
+
export declare function listTrusted(): any;
|
package/dist/config/trust.js
CHANGED
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
*
|
|
8
8
|
* FASTCODE_TRUST_ALL=1 marks every directory trusted (scripts, CI).
|
|
9
9
|
*/
|
|
10
|
-
import { existsSync, readFileSync, realpathSync,
|
|
10
|
+
import { existsSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { resolve } from "node:path";
|
|
12
12
|
import { ensureDir, getPaths } from "./paths.js";
|
|
13
13
|
const TRUTHY = ["1", "true", "yes", "on"];
|
|
14
|
-
let cache;
|
|
15
14
|
export function normalizeProjectPath(dir) {
|
|
16
15
|
const absolute = resolve(dir);
|
|
17
16
|
try {
|
|
@@ -21,104 +20,22 @@ export function normalizeProjectPath(dir) {
|
|
|
21
20
|
return absolute;
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
|
-
function emptyStore() {
|
|
25
|
-
return { version: 1, tools: {}, paths: {} };
|
|
26
|
-
}
|
|
27
|
-
function normalizePaths(raw) {
|
|
28
|
-
const paths = {};
|
|
29
|
-
if (!raw || typeof raw !== "object")
|
|
30
|
-
return paths;
|
|
31
|
-
for (const [key, value] of Object.entries(raw)) {
|
|
32
|
-
if (!key || !value || typeof value !== "object")
|
|
33
|
-
continue;
|
|
34
|
-
paths[key] = {
|
|
35
|
-
grantedAt: typeof value.grantedAt === "string" ? value.grantedAt : "",
|
|
36
|
-
lastUsed: typeof value.lastUsed === "string" ? value.lastUsed : "",
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
return paths;
|
|
40
|
-
}
|
|
41
|
-
function normalizeTools(raw) {
|
|
42
|
-
const tools = {};
|
|
43
|
-
if (!raw || typeof raw !== "object")
|
|
44
|
-
return tools;
|
|
45
|
-
for (const [key, value] of Object.entries(raw)) {
|
|
46
|
-
if (!key || !value || typeof value !== "object" || typeof value.catalogHash !== "string")
|
|
47
|
-
continue;
|
|
48
|
-
tools[key] = {
|
|
49
|
-
grantedAt: typeof value.grantedAt === "string" ? value.grantedAt : "",
|
|
50
|
-
lastUsed: typeof value.lastUsed === "string" ? value.lastUsed : "",
|
|
51
|
-
catalogHash: value.catalogHash,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return tools;
|
|
55
|
-
}
|
|
56
|
-
function migrateLegacy(raw) {
|
|
57
|
-
if (!raw || typeof raw !== "object" || !Array.isArray(raw.trusted))
|
|
58
|
-
return undefined;
|
|
59
|
-
const store = emptyStore();
|
|
60
|
-
for (const entry of raw.trusted) {
|
|
61
|
-
if (!entry || typeof entry.path !== "string" || !entry.path)
|
|
62
|
-
continue;
|
|
63
|
-
const at = typeof entry.addedAt === "string" ? entry.addedAt : new Date().toISOString();
|
|
64
|
-
store.paths[entry.path] = { grantedAt: at, lastUsed: at };
|
|
65
|
-
}
|
|
66
|
-
return store;
|
|
67
|
-
}
|
|
68
|
-
function readStore(file) {
|
|
69
|
-
if (!existsSync(file))
|
|
70
|
-
return emptyStore();
|
|
71
|
-
try {
|
|
72
|
-
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
73
|
-
if (raw && raw.version === 1) {
|
|
74
|
-
return {
|
|
75
|
-
version: 1,
|
|
76
|
-
tools: normalizeTools(raw.tools),
|
|
77
|
-
paths: normalizePaths(raw.paths),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
const migrated = migrateLegacy(raw);
|
|
81
|
-
if (!migrated)
|
|
82
|
-
return emptyStore();
|
|
83
|
-
try {
|
|
84
|
-
writeFileSync(file, JSON.stringify(migrated, null, 2), "utf8");
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
// A read-only home still gets the migrated view in memory.
|
|
88
|
-
}
|
|
89
|
-
return migrated;
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return emptyStore();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
23
|
export function loadTrust() {
|
|
96
24
|
const { trust } = getPaths();
|
|
97
|
-
|
|
25
|
+
if (!existsSync(trust))
|
|
26
|
+
return { trusted: [] };
|
|
98
27
|
try {
|
|
99
|
-
const
|
|
100
|
-
|
|
28
|
+
const raw = JSON.parse(readFileSync(trust, "utf8"));
|
|
29
|
+
return { trusted: Array.isArray(raw.trusted) ? raw.trusted.filter((entry) => entry && typeof entry.path === "string") : [] };
|
|
101
30
|
}
|
|
102
31
|
catch {
|
|
103
|
-
|
|
32
|
+
return { trusted: [] };
|
|
104
33
|
}
|
|
105
|
-
if (cache && cache.file === trust && cache.key === key)
|
|
106
|
-
return cache.state;
|
|
107
|
-
const state = readStore(trust);
|
|
108
|
-
cache = { file: trust, key, state };
|
|
109
|
-
return state;
|
|
110
34
|
}
|
|
111
35
|
function saveTrust(state) {
|
|
112
36
|
const paths = getPaths();
|
|
113
37
|
ensureDir(paths.root);
|
|
114
38
|
writeFileSync(paths.trust, JSON.stringify(state, null, 2), "utf8");
|
|
115
|
-
try {
|
|
116
|
-
const info = statSync(paths.trust);
|
|
117
|
-
cache = { file: paths.trust, key: `${info.mtimeMs}:${info.size}`, state };
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
cache = undefined;
|
|
121
|
-
}
|
|
122
39
|
}
|
|
123
40
|
export function trustAllEnabled() {
|
|
124
41
|
return TRUTHY.includes((process.env["FASTCODE_TRUST_ALL"] ?? "").trim().toLowerCase());
|
|
@@ -127,14 +44,13 @@ export function isTrusted(dir) {
|
|
|
127
44
|
if (trustAllEnabled())
|
|
128
45
|
return true;
|
|
129
46
|
const target = normalizeProjectPath(dir);
|
|
130
|
-
return
|
|
47
|
+
return loadTrust().trusted.some((entry) => entry.path === target);
|
|
131
48
|
}
|
|
132
49
|
export function trustProject(dir) {
|
|
133
50
|
const target = normalizeProjectPath(dir);
|
|
134
51
|
const state = loadTrust();
|
|
135
|
-
if (!state.
|
|
136
|
-
|
|
137
|
-
state.paths[target] = { grantedAt: at, lastUsed: at };
|
|
52
|
+
if (!state.trusted.some((entry) => entry.path === target)) {
|
|
53
|
+
state.trusted.push({ path: target, addedAt: new Date().toISOString() });
|
|
138
54
|
saveTrust(state);
|
|
139
55
|
}
|
|
140
56
|
return target;
|
|
@@ -142,12 +58,10 @@ export function trustProject(dir) {
|
|
|
142
58
|
export function untrustProject(dir) {
|
|
143
59
|
const target = normalizeProjectPath(dir);
|
|
144
60
|
const state = loadTrust();
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
saveTrust(state);
|
|
149
|
-
return true;
|
|
61
|
+
const next = state.trusted.filter((entry) => entry.path !== target);
|
|
62
|
+
saveTrust({ trusted: next });
|
|
63
|
+
return state.trusted.length !== next.length;
|
|
150
64
|
}
|
|
151
65
|
export function listTrusted() {
|
|
152
|
-
return
|
|
66
|
+
return loadTrust().trusted;
|
|
153
67
|
}
|
|
@@ -12,54 +12,29 @@ export declare function collectDiagnostics(): {
|
|
|
12
12
|
configRoot: any;
|
|
13
13
|
configFile: any;
|
|
14
14
|
authFile: any;
|
|
15
|
-
authMode: string;
|
|
16
|
-
tmpdir: string;
|
|
17
|
-
memTotalMb: number;
|
|
18
|
-
memFreeMb: number;
|
|
19
15
|
providerId: any;
|
|
20
16
|
model: any;
|
|
21
17
|
keyPresent: boolean;
|
|
22
|
-
keyStatus: "ok" | "
|
|
23
|
-
keyEnv:
|
|
18
|
+
keyStatus: "ok" | "unbound" | "missing";
|
|
19
|
+
keyEnv: any;
|
|
24
20
|
skillsInstalled: number;
|
|
25
21
|
pluginsInstalled: number;
|
|
26
22
|
enabledSkills: any;
|
|
27
23
|
enabledPlugins: any;
|
|
28
24
|
sessionLogEnabled: boolean;
|
|
29
25
|
sessionCacheMb: number;
|
|
30
|
-
sessionFsync: "auto" | "off" | "on";
|
|
31
|
-
unclosedSessions: number;
|
|
32
26
|
sessionsDir: any;
|
|
33
27
|
sessionsCount: number;
|
|
34
28
|
sessionsBytes: number;
|
|
35
29
|
trustFile: any;
|
|
36
|
-
trusted:
|
|
30
|
+
trusted: any;
|
|
37
31
|
shellDenyPatterns: number;
|
|
38
32
|
allowDangerous: boolean;
|
|
39
33
|
toolOutputLimit: number;
|
|
40
|
-
tokenBudget: number;
|
|
41
|
-
costBudgetUsd: number;
|
|
42
|
-
compactionEnabled: boolean;
|
|
43
|
-
compactionRatio: number;
|
|
44
|
-
compactionHeapMb: number;
|
|
45
|
-
compactionHeapUsedMb: number;
|
|
46
|
-
compactionForced: boolean;
|
|
47
|
-
serverCompactionAware: boolean;
|
|
48
|
-
shellActive: number;
|
|
49
|
-
shellPool: number;
|
|
50
|
-
shellSpawns: number;
|
|
51
|
-
shellMaxSpawn: number;
|
|
52
|
-
sseIdleMs: number;
|
|
53
|
-
toolProtocol: import("../agent/protocol-mode.js").ToolProtocol;
|
|
54
|
-
toolProtocolMode: string;
|
|
55
|
-
toolCapability: any;
|
|
56
|
-
loopExempt: string[];
|
|
57
|
-
modelMetaFile: string;
|
|
58
|
-
modelMeta: import("./model-meta.js").ModelMeta;
|
|
59
34
|
providers: {
|
|
60
35
|
id: string;
|
|
61
36
|
label: string;
|
|
62
|
-
env: string[];
|
|
37
|
+
env: any[] | string[];
|
|
63
38
|
keyPresent: boolean;
|
|
64
39
|
}[];
|
|
65
40
|
};
|
package/dist/lib/diagnostics.js
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* diagnosed without opening the TUI: Node version, Termux detection, whether
|
|
6
6
|
* stdout is a real terminal, the config root, and which provider keys exist.
|
|
7
7
|
*/
|
|
8
|
-
import { existsSync, statSync } from "node:fs";
|
|
9
|
-
import { totalmem, freemem, tmpdir as osTmpdir } from "node:os";
|
|
10
8
|
import { detectPlatform, platformLabel } from "./platform.js";
|
|
11
9
|
import { readPackageMeta } from "./pkg.js";
|
|
12
10
|
import { shouldUseStableTerminalUi } from "./uiMode.js";
|
|
@@ -15,14 +13,10 @@ import { loadConfig, resolveApiKey, resolveProviderKey } from "../config/store.j
|
|
|
15
13
|
import { PROVIDERS } from "../providers/index.js";
|
|
16
14
|
import { listInstalledSkills } from "../skills/manager.js";
|
|
17
15
|
import { listInstalledPlugins } from "../plugins/manager.js";
|
|
18
|
-
import {
|
|
16
|
+
import { loggingEnabled, listSessions, sessionCacheLimitBytes } from "../session/log.js";
|
|
19
17
|
import { isTrusted } from "../config/trust.js";
|
|
20
|
-
import { DEFAULT_DENY_PATTERNS
|
|
18
|
+
import { DEFAULT_DENY_PATTERNS } from "../agent/guards.js";
|
|
21
19
|
import { toolOutputLimit } from "../agent/limits.js";
|
|
22
|
-
import { compactionConfigFromEnv, heapExceeded } from "../agent/compaction.js";
|
|
23
|
-
import { shellPoolStats } from "../agent/shell-session.js";
|
|
24
|
-
import { resolveToolProtocol, toolCapabilityKey } from "../agent/protocol-mode.js";
|
|
25
|
-
import { getModelMeta, modelMetaOverridePath } from "./model-meta.js";
|
|
26
20
|
const NODE_REQUIRED = "18.17";
|
|
27
21
|
function readVersion() {
|
|
28
22
|
return readPackageMeta().version;
|
|
@@ -61,16 +55,6 @@ export function collectDiagnostics() {
|
|
|
61
55
|
// Same for plugins.
|
|
62
56
|
}
|
|
63
57
|
const platform = detectPlatform();
|
|
64
|
-
const compaction = compactionConfigFromEnv();
|
|
65
|
-
const shells = shellPoolStats();
|
|
66
|
-
let authMode = "missing";
|
|
67
|
-
try {
|
|
68
|
-
if (paths?.auth && existsSync(paths.auth))
|
|
69
|
-
authMode = (statSync(paths.auth).mode & 0o777).toString(8).padStart(4, "0");
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
authMode = "unreadable";
|
|
73
|
-
}
|
|
74
58
|
return {
|
|
75
59
|
version: readVersion(),
|
|
76
60
|
node: process.version,
|
|
@@ -85,10 +69,6 @@ export function collectDiagnostics() {
|
|
|
85
69
|
configRoot: paths?.root,
|
|
86
70
|
configFile: paths?.config,
|
|
87
71
|
authFile: paths?.auth,
|
|
88
|
-
authMode,
|
|
89
|
-
tmpdir: process.env["TMPDIR"] || osTmpdir(),
|
|
90
|
-
memTotalMb: totalmem() / 1024 / 1024,
|
|
91
|
-
memFreeMb: freemem() / 1024 / 1024,
|
|
92
72
|
providerId: config.providerId,
|
|
93
73
|
model: config.model,
|
|
94
74
|
keyPresent,
|
|
@@ -100,8 +80,6 @@ export function collectDiagnostics() {
|
|
|
100
80
|
enabledPlugins: (config.enabledPlugins ?? []).length,
|
|
101
81
|
sessionLogEnabled: loggingEnabled(),
|
|
102
82
|
sessionCacheMb: Math.round(sessionCacheLimitBytes() / (1024 * 1024)),
|
|
103
|
-
sessionFsync: fsyncMode(),
|
|
104
|
-
unclosedSessions: findUnclosedSessions().length,
|
|
105
83
|
sessionsDir: paths?.sessions,
|
|
106
84
|
sessionsCount: listSessions().length,
|
|
107
85
|
sessionsBytes: listSessions().reduce((sum, entry) => sum + entry.bytes, 0),
|
|
@@ -110,25 +88,6 @@ export function collectDiagnostics() {
|
|
|
110
88
|
shellDenyPatterns: DEFAULT_DENY_PATTERNS.length,
|
|
111
89
|
allowDangerous: ["1", "true", "yes", "on"].includes((process.env["FASTCODE_ALLOW_DANGEROUS"] ?? "").trim().toLowerCase()),
|
|
112
90
|
toolOutputLimit: toolOutputLimit(),
|
|
113
|
-
tokenBudget: positiveEnv("FASTCODE_TOKEN_BUDGET"),
|
|
114
|
-
costBudgetUsd: positiveEnv("FASTCODE_COST_BUDGET_USD"),
|
|
115
|
-
compactionEnabled: compaction.enabled,
|
|
116
|
-
compactionRatio: compaction.localThresholdRatio,
|
|
117
|
-
compactionHeapMb: compaction.heapLimitMb,
|
|
118
|
-
compactionHeapUsedMb: process.memoryUsage().heapUsed / 1024 / 1024,
|
|
119
|
-
compactionForced: heapExceeded(compaction),
|
|
120
|
-
serverCompactionAware: compaction.serverCompactionAware,
|
|
121
|
-
shellActive: shells.active,
|
|
122
|
-
shellPool: shells.pool,
|
|
123
|
-
shellSpawns: shells.spawns,
|
|
124
|
-
shellMaxSpawn: shells.maxSpawnPerTurn,
|
|
125
|
-
sseIdleMs: positiveEnv("FASTCODE_SSE_IDLE_MS") || 25_000,
|
|
126
|
-
toolProtocol: resolveToolProtocol(config, config.providerId, config.model),
|
|
127
|
-
toolProtocolMode: (process.env["FASTCODE_TOOL_PROTOCOL"] ?? "legacy").trim().toLowerCase(),
|
|
128
|
-
toolCapability: config.capabilities?.toolCalling?.[toolCapabilityKey(config.providerId, config.model)] ?? "unknown",
|
|
129
|
-
loopExempt: Array.from(loopExemptTools()),
|
|
130
|
-
modelMetaFile: modelMetaOverridePath(),
|
|
131
|
-
modelMeta: getModelMeta(config.providerId, config.model),
|
|
132
91
|
providers: PROVIDERS.map((p) => ({
|
|
133
92
|
id: p.id,
|
|
134
93
|
label: p.label,
|
|
@@ -137,10 +96,6 @@ export function collectDiagnostics() {
|
|
|
137
96
|
})),
|
|
138
97
|
};
|
|
139
98
|
}
|
|
140
|
-
function positiveEnv(name) {
|
|
141
|
-
const value = Number(process.env[name]);
|
|
142
|
-
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
143
|
-
}
|
|
144
99
|
export function formatDiagnostics(info) {
|
|
145
100
|
const lines = [];
|
|
146
101
|
lines.push(`FastCode ${info.version} — environment check`);
|
|
@@ -151,21 +106,12 @@ export function formatDiagnostics(info) {
|
|
|
151
106
|
lines.push(` stable UI ${info.stableUi ? "on (anti-flicker)" : "off"}`);
|
|
152
107
|
lines.push(" config root " + (info.configRoot ?? "(unavailable)"));
|
|
153
108
|
lines.push(" config file " + (info.configFile ?? "(unavailable)"));
|
|
154
|
-
lines.push(" keys file " + (info.authFile ?? "(unavailable)") + "
|
|
155
|
-
lines.push(" tmpdir " + info.tmpdir + (info.termux && !String(info.tmpdir).startsWith("/data/data/com.termux") ? " [WARN: use $PREFIX/tmp]" : ""));
|
|
156
|
-
lines.push(" memory " + info.memFreeMb.toFixed(0) + "MB free / " + info.memTotalMb.toFixed(0) + "MB total");
|
|
109
|
+
lines.push(" keys file " + (info.authFile ?? "(unavailable)") + " (separate, chmod 0600)");
|
|
157
110
|
lines.push(" trusted cwd " + (info.trusted ? "yes" : "NO - agent tools ask first or stay off") + " (" + (info.trustFile ?? "?") + ")");
|
|
158
111
|
lines.push(" session log " + (info.sessionLogEnabled ? "on" : "off") + " cache cap " + info.sessionCacheMb + "MB, " + info.sessionsCount + " file(s), " + (info.sessionsBytes / 1024 / 1024).toFixed(2) + "MB used");
|
|
159
|
-
lines.push(" session
|
|
112
|
+
lines.push(" session dir " + (info.sessionsDir ?? "(unavailable)"));
|
|
160
113
|
lines.push(" shell guard " + info.shellDenyPatterns + " deny patterns" + (info.allowDangerous ? " [FASTCODE_ALLOW_DANGEROUS is ON]" : ""));
|
|
161
114
|
lines.push(" tool output " + info.toolOutputLimit + " chars max (streaming cap)");
|
|
162
|
-
lines.push(` budgets ${info.tokenBudget > 0 ? "tokens ≤ " + info.tokenBudget : "token budget off"} · ${info.costBudgetUsd > 0 ? "$" + info.costBudgetUsd : "cost budget off"}`);
|
|
163
|
-
lines.push(` compaction ${info.compactionEnabled ? "on" : "off"} · ${Math.round(info.compactionRatio * 100)}% · heap ${info.compactionHeapUsedMb.toFixed(1)}/${info.compactionHeapMb}MB${info.compactionForced ? " [FORCED]" : ""}${info.serverCompactionAware ? " · server-aware" : ""}`);
|
|
164
|
-
lines.push(` shell pool ${info.shellActive} active · ${info.shellPool} resident · ${info.shellSpawns} spawns · cap ${info.shellMaxSpawn}/turn`);
|
|
165
|
-
lines.push(` loop exempt ${info.loopExempt.length > 0 ? info.loopExempt.join(", ") : "(none)"}`);
|
|
166
|
-
lines.push(` model meta ctx ${info.modelMeta.contextWindow} · ~${info.modelMeta.charsPerToken} chars/token · ${info.modelMeta.supportsTools ? "tools" : "no tools"} · ${info.modelMetaFile}`);
|
|
167
|
-
lines.push(` sse timeout ${info.sseIdleMs}ms idle`);
|
|
168
|
-
lines.push(` tool protocol ${info.toolProtocol} (${info.toolProtocolMode}) · cached ${info.toolCapability}`);
|
|
169
115
|
lines.push(` provider ${info.providerId} · model ${info.model}`);
|
|
170
116
|
let apiKeyStatus;
|
|
171
117
|
if (info.keyPresent)
|
|
@@ -188,8 +134,6 @@ export function formatDiagnostics(info) {
|
|
|
188
134
|
lines.push(" - pkg install nodejs git");
|
|
189
135
|
lines.push(" - keep the session alive with: termux-wake-lock");
|
|
190
136
|
lines.push(" - add an extra-keys row for Esc/Ctrl in ~/.termux/termux.properties");
|
|
191
|
-
lines.push(" - long tasks: export TMPDIR=$PREFIX/tmp and use termux-wake-lock");
|
|
192
|
-
lines.push(` - Android 12+ caps phantom processes (~32); background shells are pooled (${info.shellPool} resident, cap ${info.shellMaxSpawn}/turn)`);
|
|
193
137
|
}
|
|
194
138
|
return lines.join("\n");
|
|
195
139
|
}
|
package/dist/lib/http.d.ts
CHANGED
|
@@ -6,18 +6,8 @@
|
|
|
6
6
|
* Anthropic's older streaming) handle their own parsing.
|
|
7
7
|
*/
|
|
8
8
|
export declare function fetchJson(url: string, init?: any): Promise<any>;
|
|
9
|
-
export declare class NetworkStallError extends Error {
|
|
10
|
-
readonly code = "NETWORK_STALL";
|
|
11
|
-
readonly bytesReceived: number;
|
|
12
|
-
constructor(message: string, bytesReceived?: number);
|
|
13
|
-
}
|
|
14
|
-
export interface StreamSseOptions {
|
|
15
|
-
idleTimeoutMs?: number;
|
|
16
|
-
totalTimeoutMs?: number;
|
|
17
|
-
}
|
|
18
9
|
/** Async iterator over SSE events from a streaming HTTP response. */
|
|
19
|
-
export declare function streamSSE(res: any
|
|
10
|
+
export declare function streamSSE(res: any): AsyncGenerator<{
|
|
20
11
|
event: any;
|
|
21
12
|
data: string;
|
|
22
13
|
}, void, unknown>;
|
|
23
|
-
export declare function probeConnectivity(url: string, timeoutMs?: number): Promise<boolean>;
|