@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.
Files changed (246) hide show
  1. package/README.md +6 -24
  2. package/dist/agent/guards.d.ts +0 -8
  3. package/dist/agent/guards.js +0 -195
  4. package/dist/agent/protocol.js +1 -4
  5. package/dist/agent/tools.d.ts +1 -3
  6. package/dist/agent/tools.js +377 -2
  7. package/dist/app.js +103 -335
  8. package/dist/cli.js +311 -362
  9. package/dist/commands/index.js +0 -22
  10. package/dist/commands/login.d.ts +2 -4
  11. package/dist/commands/login.js +10 -12
  12. package/dist/commands/logout.js +16 -8
  13. package/dist/commands/model.d.ts +0 -13
  14. package/dist/commands/model.js +22 -42
  15. package/dist/commands/provider.d.ts +0 -13
  16. package/dist/commands/provider.js +9 -20
  17. package/dist/commands/whoami.js +5 -6
  18. package/dist/config/store.d.ts +12 -32
  19. package/dist/config/store.js +65 -117
  20. package/dist/config/trust.d.ts +8 -21
  21. package/dist/config/trust.js +13 -99
  22. package/dist/lib/diagnostics.d.ts +4 -29
  23. package/dist/lib/diagnostics.js +4 -60
  24. package/dist/lib/http.d.ts +1 -11
  25. package/dist/lib/http.js +4 -62
  26. package/dist/providers/anthropic.d.ts +0 -1
  27. package/dist/providers/anthropic.js +0 -12
  28. package/dist/providers/custom.d.ts +0 -9
  29. package/dist/providers/deepseek.d.ts +0 -10
  30. package/dist/providers/deepseek.js +1 -2
  31. package/dist/providers/google.d.ts +0 -9
  32. package/dist/providers/groq.d.ts +0 -10
  33. package/dist/providers/groq.js +1 -2
  34. package/dist/providers/index.d.ts +201 -10
  35. package/dist/providers/index.js +0 -30
  36. package/dist/providers/mistral.d.ts +0 -10
  37. package/dist/providers/mistral.js +1 -2
  38. package/dist/providers/moonshot.d.ts +0 -10
  39. package/dist/providers/moonshot.js +1 -2
  40. package/dist/providers/ollama.d.ts +0 -9
  41. package/dist/providers/openai.d.ts +0 -10
  42. package/dist/providers/openai.js +1 -2
  43. package/dist/providers/openaiCompatible.d.ts +0 -9
  44. package/dist/providers/openaiCompatible.js +10 -58
  45. package/dist/providers/openrouter.d.ts +0 -10
  46. package/dist/providers/openrouter.js +1 -2
  47. package/dist/providers/qwen.d.ts +0 -10
  48. package/dist/providers/qwen.js +1 -2
  49. package/dist/providers/xai.d.ts +0 -10
  50. package/dist/providers/xai.js +1 -2
  51. package/dist/providers/zhipu.d.ts +0 -10
  52. package/dist/providers/zhipu.js +1 -2
  53. package/dist/session/log.d.ts +12 -35
  54. package/dist/session/log.js +10 -206
  55. package/dist/types.d.ts +1 -60
  56. package/dist/ui/Message.d.ts +7 -1
  57. package/dist/ui/Message.js +2 -13
  58. package/dist/ui/Prompt.d.ts +2 -1
  59. package/dist/ui/Prompt.js +2 -2
  60. package/dist/ui/Spinner.js +5 -11
  61. package/dist/ui/StatusBar.d.ts +1 -2
  62. package/dist/ui/StatusBar.js +5 -6
  63. package/package.json +1 -1
  64. package/src/agent/guards.ts +0 -196
  65. package/src/agent/protocol.ts +1 -4
  66. package/src/agent/tools.ts +377 -3
  67. package/src/app.ts +103 -335
  68. package/src/cli.ts +3 -30
  69. package/src/commands/index.ts +0 -22
  70. package/src/commands/login.ts +10 -12
  71. package/src/commands/logout.ts +16 -8
  72. package/src/commands/model.ts +22 -42
  73. package/src/commands/provider.ts +9 -20
  74. package/src/commands/whoami.ts +5 -6
  75. package/src/config/store.ts +69 -122
  76. package/src/config/trust.ts +21 -137
  77. package/src/lib/diagnostics.ts +4 -60
  78. package/src/lib/http.ts +4 -66
  79. package/src/providers/anthropic.ts +1 -13
  80. package/src/providers/deepseek.ts +1 -2
  81. package/src/providers/groq.ts +1 -2
  82. package/src/providers/index.ts +1 -32
  83. package/src/providers/mistral.ts +1 -2
  84. package/src/providers/moonshot.ts +1 -2
  85. package/src/providers/openai.ts +1 -2
  86. package/src/providers/openaiCompatible.ts +10 -58
  87. package/src/providers/openrouter.ts +1 -2
  88. package/src/providers/qwen.ts +1 -2
  89. package/src/providers/xai.ts +1 -2
  90. package/src/providers/zhipu.ts +1 -2
  91. package/src/session/log.ts +28 -267
  92. package/src/types.ts +1 -63
  93. package/src/ui/Message.ts +2 -13
  94. package/src/ui/Prompt.ts +2 -2
  95. package/src/ui/Spinner.ts +5 -11
  96. package/src/ui/StatusBar.ts +5 -6
  97. package/dist/agent/approval.d.ts +0 -50
  98. package/dist/agent/approval.js +0 -7
  99. package/dist/agent/compaction.d.ts +0 -39
  100. package/dist/agent/compaction.js +0 -227
  101. package/dist/agent/context.d.ts +0 -29
  102. package/dist/agent/context.js +0 -62
  103. package/dist/agent/ignore.d.ts +0 -11
  104. package/dist/agent/ignore.js +0 -129
  105. package/dist/agent/process-tree.d.ts +0 -2
  106. package/dist/agent/process-tree.js +0 -31
  107. package/dist/agent/protocol-mode.d.ts +0 -6
  108. package/dist/agent/protocol-mode.js +0 -51
  109. package/dist/agent/registry.d.ts +0 -17
  110. package/dist/agent/registry.js +0 -90
  111. package/dist/agent/runner.d.ts +0 -106
  112. package/dist/agent/runner.js +0 -352
  113. package/dist/agent/shell-session.d.ts +0 -37
  114. package/dist/agent/shell-session.js +0 -400
  115. package/dist/agent/stream.d.ts +0 -29
  116. package/dist/agent/stream.js +0 -103
  117. package/dist/agent/tool-schemas.d.ts +0 -2
  118. package/dist/agent/tool-schemas.js +0 -63
  119. package/dist/agent/tools/append_file.d.ts +0 -2
  120. package/dist/agent/tools/append_file.js +0 -26
  121. package/dist/agent/tools/apply_patch.d.ts +0 -10
  122. package/dist/agent/tools/apply_patch.js +0 -52
  123. package/dist/agent/tools/copy_file.d.ts +0 -2
  124. package/dist/agent/tools/copy_file.js +0 -30
  125. package/dist/agent/tools/delete_file.d.ts +0 -2
  126. package/dist/agent/tools/delete_file.js +0 -24
  127. package/dist/agent/tools/grep.d.ts +0 -2
  128. package/dist/agent/tools/grep.js +0 -23
  129. package/dist/agent/tools/index.d.ts +0 -2
  130. package/dist/agent/tools/index.js +0 -32
  131. package/dist/agent/tools/list_files.d.ts +0 -2
  132. package/dist/agent/tools/list_files.js +0 -17
  133. package/dist/agent/tools/make_dir.d.ts +0 -2
  134. package/dist/agent/tools/make_dir.js +0 -24
  135. package/dist/agent/tools/move_path.d.ts +0 -2
  136. package/dist/agent/tools/move_path.js +0 -47
  137. package/dist/agent/tools/paths.d.ts +0 -7
  138. package/dist/agent/tools/paths.js +0 -84
  139. package/dist/agent/tools/pwd.d.ts +0 -2
  140. package/dist/agent/tools/pwd.js +0 -10
  141. package/dist/agent/tools/read_file.d.ts +0 -2
  142. package/dist/agent/tools/read_file.js +0 -21
  143. package/dist/agent/tools/read_many.d.ts +0 -2
  144. package/dist/agent/tools/read_many.js +0 -25
  145. package/dist/agent/tools/readers.d.ts +0 -6
  146. package/dist/agent/tools/readers.js +0 -216
  147. package/dist/agent/tools/replace_in_file.d.ts +0 -2
  148. package/dist/agent/tools/replace_in_file.js +0 -30
  149. package/dist/agent/tools/shell.d.ts +0 -2
  150. package/dist/agent/tools/shell.js +0 -48
  151. package/dist/agent/tools/stat_path.d.ts +0 -2
  152. package/dist/agent/tools/stat_path.js +0 -31
  153. package/dist/agent/tools/types.d.ts +0 -39
  154. package/dist/agent/tools/types.js +0 -1
  155. package/dist/agent/tools/validate.d.ts +0 -6
  156. package/dist/agent/tools/validate.js +0 -29
  157. package/dist/agent/tools/write_file.d.ts +0 -2
  158. package/dist/agent/tools/write_file.js +0 -26
  159. package/dist/commands/attach.d.ts +0 -9
  160. package/dist/commands/attach.js +0 -15
  161. package/dist/commands/bg.d.ts +0 -7
  162. package/dist/commands/bg.js +0 -9
  163. package/dist/commands/cancel.d.ts +0 -10
  164. package/dist/commands/cancel.js +0 -10
  165. package/dist/commands/compact.d.ts +0 -10
  166. package/dist/commands/compact.js +0 -22
  167. package/dist/commands/context.d.ts +0 -7
  168. package/dist/commands/context.js +0 -24
  169. package/dist/commands/edit.d.ts +0 -10
  170. package/dist/commands/edit.js +0 -36
  171. package/dist/commands/effort.d.ts +0 -25
  172. package/dist/commands/effort.js +0 -48
  173. package/dist/commands/expand.d.ts +0 -10
  174. package/dist/commands/expand.js +0 -8
  175. package/dist/commands/jobs.d.ts +0 -7
  176. package/dist/commands/jobs.js +0 -16
  177. package/dist/commands/kill.d.ts +0 -7
  178. package/dist/commands/kill.js +0 -11
  179. package/dist/commands/steer.d.ts +0 -11
  180. package/dist/commands/steer.js +0 -13
  181. package/dist/lib/model-meta.d.ts +0 -19
  182. package/dist/lib/model-meta.js +0 -113
  183. package/dist/lib/native-tools.d.ts +0 -12
  184. package/dist/lib/native-tools.js +0 -21
  185. package/dist/lib/net.d.ts +0 -33
  186. package/dist/lib/net.js +0 -168
  187. package/dist/patch/apply.d.ts +0 -15
  188. package/dist/patch/apply.js +0 -172
  189. package/dist/patch/parse.d.ts +0 -29
  190. package/dist/patch/parse.js +0 -112
  191. package/dist/patch/plan.d.ts +0 -49
  192. package/dist/patch/plan.js +0 -273
  193. package/dist/session/projection.d.ts +0 -43
  194. package/dist/session/projection.js +0 -257
  195. package/dist/ui/Picker.d.ts +0 -8
  196. package/dist/ui/Picker.js +0 -24
  197. package/src/agent/approval.ts +0 -47
  198. package/src/agent/compaction.ts +0 -276
  199. package/src/agent/context.ts +0 -97
  200. package/src/agent/ignore.ts +0 -147
  201. package/src/agent/process-tree.ts +0 -32
  202. package/src/agent/protocol-mode.ts +0 -59
  203. package/src/agent/registry.ts +0 -98
  204. package/src/agent/runner.ts +0 -443
  205. package/src/agent/shell-session.ts +0 -449
  206. package/src/agent/stream.ts +0 -143
  207. package/src/agent/tool-schemas.ts +0 -67
  208. package/src/agent/tools/append_file.ts +0 -28
  209. package/src/agent/tools/apply_patch.ts +0 -54
  210. package/src/agent/tools/copy_file.ts +0 -32
  211. package/src/agent/tools/delete_file.ts +0 -26
  212. package/src/agent/tools/grep.ts +0 -25
  213. package/src/agent/tools/index.ts +0 -34
  214. package/src/agent/tools/list_files.ts +0 -19
  215. package/src/agent/tools/make_dir.ts +0 -26
  216. package/src/agent/tools/move_path.ts +0 -50
  217. package/src/agent/tools/paths.ts +0 -92
  218. package/src/agent/tools/pwd.ts +0 -12
  219. package/src/agent/tools/read_file.ts +0 -23
  220. package/src/agent/tools/read_many.ts +0 -27
  221. package/src/agent/tools/readers.ts +0 -228
  222. package/src/agent/tools/replace_in_file.ts +0 -32
  223. package/src/agent/tools/shell.ts +0 -53
  224. package/src/agent/tools/stat_path.ts +0 -33
  225. package/src/agent/tools/types.ts +0 -42
  226. package/src/agent/tools/validate.ts +0 -35
  227. package/src/agent/tools/write_file.ts +0 -28
  228. package/src/commands/attach.ts +0 -16
  229. package/src/commands/bg.ts +0 -9
  230. package/src/commands/cancel.ts +0 -10
  231. package/src/commands/compact.ts +0 -23
  232. package/src/commands/context.ts +0 -25
  233. package/src/commands/edit.ts +0 -37
  234. package/src/commands/effort.ts +0 -49
  235. package/src/commands/expand.ts +0 -8
  236. package/src/commands/jobs.ts +0 -17
  237. package/src/commands/kill.ts +0 -12
  238. package/src/commands/steer.ts +0 -13
  239. package/src/lib/model-meta.ts +0 -138
  240. package/src/lib/native-tools.ts +0 -32
  241. package/src/lib/net.ts +0 -204
  242. package/src/patch/apply.ts +0 -194
  243. package/src/patch/parse.ts +0 -131
  244. package/src/patch/plan.ts +0 -317
  245. package/src/session/projection.ts +0 -308
  246. package/src/ui/Picker.ts +0 -24
@@ -1,34 +1,12 @@
1
1
  import { fetchJson, streamSSE } from "../lib/http.js";
2
- import { finalizeToolCalls, mergeToolCallDelta } from "../lib/native-tools.js";
3
2
  /** Build a chat-completions body in the classic or the newer (compat) dialect. */
4
- function buildBody(req, compat, opts, includeReasoning = true) {
3
+ function buildBody(req, compat) {
5
4
  const messages = [];
6
5
  if (req.system)
7
6
  messages.push({ role: "system", content: req.system });
8
- for (const m of req.messages) {
9
- if (m.role === "tool") {
10
- messages.push({ role: "tool", tool_call_id: m.toolCallId, content: m.content });
11
- continue;
12
- }
13
- if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
14
- messages.push({
15
- role: "assistant",
16
- content: m.content || null,
17
- tool_calls: m.toolCalls.map((call) => ({
18
- id: call.id,
19
- type: "function",
20
- function: { name: call.name, arguments: call.arguments },
21
- })),
22
- });
23
- continue;
24
- }
7
+ for (const m of req.messages)
25
8
  messages.push({ role: m.role, content: m.content });
26
- }
27
9
  const body = { model: req.model, messages, stream: true };
28
- if (req.tools && req.tools.length > 0) {
29
- body.tools = req.tools;
30
- body.tool_choice = "auto";
31
- }
32
10
  if (req.maxOutputTokens !== undefined) {
33
11
  if (compat)
34
12
  body.max_completion_tokens = req.maxOutputTokens;
@@ -37,18 +15,10 @@ function buildBody(req, compat, opts, includeReasoning = true) {
37
15
  }
38
16
  if (req.temperature !== undefined && !compat)
39
17
  body.temperature = req.temperature;
40
- if (includeReasoning && req.reasoningEffort && req.reasoningEffort !== "auto") {
41
- const effort = req.reasoningEffort === "max" ? "high" : req.reasoningEffort;
42
- if (opts.reasoning === "openai")
43
- body.reasoning_effort = effort;
44
- else if (opts.reasoning === "openrouter")
45
- body.reasoning = { effort };
46
- }
47
18
  return body;
48
19
  }
49
20
  export async function* streamChatCompletion(req, opts) {
50
- const hasReasoning = Boolean(req.reasoningEffort && req.reasoningEffort !== "auto" && opts.reasoning && opts.reasoning !== "none");
51
- const send = async (compat, includeReasoning = hasReasoning) => {
21
+ const send = async (compat) => {
52
22
  const headers = {
53
23
  "content-type": "application/json",
54
24
  accept: "text/event-stream",
@@ -56,36 +26,27 @@ export async function* streamChatCompletion(req, opts) {
56
26
  };
57
27
  if (opts.apiKey)
58
28
  headers["authorization"] = (opts.authHeader ?? "Bearer") + " " + opts.apiKey;
59
- if (req.clientRequestId)
60
- headers["idempotency-key"] = req.clientRequestId;
61
29
  return await fetch(trim(opts.baseUrl) + "/chat/completions", {
62
30
  method: "POST",
63
31
  headers,
64
- body: JSON.stringify(buildBody(req, compat, opts, includeReasoning)),
32
+ body: JSON.stringify(buildBody(req, compat)),
65
33
  signal: req.signal,
66
34
  });
67
35
  };
68
36
  let res = await send(false);
69
37
  if (!res.ok) {
70
- let detail = await res.text().catch(() => "");
71
- // Some models reject the thinking parameter even though the provider
72
- // as a whole accepts it. Drop it once, then keep the request alive.
73
- if (res.status === 400 && hasReasoning && /reasoning|thinking|effort|unsupported|unrecognized|unknown parameter/i.test(detail)) {
74
- res = await send(false, false);
75
- detail = res.ok ? detail : await res.text().catch(() => "");
76
- }
38
+ const detail = await res.text().catch(() => "");
77
39
  // Newer OpenAI-style models reject max_tokens and temperature. Retry once
78
40
  // in the compatibility dialect before surfacing the real error.
79
- if (!res.ok && res.status === 400 && /max_tokens|max_completion_tokens|temperature|unsupported|unrecognized|unknown parameter/i.test(detail)) {
80
- res = await send(true, false);
81
- detail = res.ok ? detail : await res.text().catch(() => "");
41
+ if (res.status === 400 && /max_tokens|max_completion_tokens|temperature|unsupported|unrecognized|unknown parameter/i.test(detail)) {
42
+ res = await send(true);
82
43
  }
83
44
  if (!res.ok) {
84
- throw new Error(res.status + " " + res.statusText + ": " + detail.slice(0, 500));
45
+ const body = await res.text().catch(() => "");
46
+ throw new Error(res.status + " " + res.statusText + ": " + body.slice(0, 500));
85
47
  }
86
48
  }
87
49
  let usage;
88
- const toolCalls = new Map();
89
50
  for await (const ev of streamSSE(res)) {
90
51
  if (ev.data === "[DONE]")
91
52
  break;
@@ -100,14 +61,6 @@ export async function* streamChatCompletion(req, opts) {
100
61
  const choice = obj.choices?.[0];
101
62
  const raw = choice?.delta?.content ?? choice?.text;
102
63
  const reasoning = choice?.delta?.reasoning_content ?? choice?.delta?.reasoning;
103
- if (Array.isArray(choice?.delta?.tool_calls)) {
104
- for (const delta of choice.delta.tool_calls)
105
- mergeToolCallDelta(toolCalls, delta);
106
- }
107
- if (Array.isArray(choice?.message?.tool_calls)) {
108
- for (const delta of choice.message.tool_calls)
109
- mergeToolCallDelta(toolCalls, delta);
110
- }
111
64
  if (obj.usage) {
112
65
  usage = {
113
66
  inputTokens: obj.usage.prompt_tokens,
@@ -125,8 +78,7 @@ export async function* streamChatCompletion(req, opts) {
125
78
  else if (typeof reasoning === "string" && reasoning)
126
79
  yield { delta: "", done: false, reasoning };
127
80
  }
128
- const calls = finalizeToolCalls(toolCalls);
129
- yield calls.length > 0 ? { delta: "", done: true, usage, toolCalls: calls } : { delta: "", done: true, usage };
81
+ yield { delta: "", done: true, usage };
130
82
  }
131
83
  export async function listModelsHttp(opts) {
132
84
  const staticModels = opts.staticModels ?? [];
@@ -10,25 +10,15 @@ export declare const openrouterProvider: {
10
10
  done: boolean;
11
11
  reasoning?: undefined;
12
12
  usage?: undefined;
13
- toolCalls?: undefined;
14
13
  } | {
15
14
  delta: string;
16
15
  done: boolean;
17
16
  reasoning: string;
18
17
  usage?: undefined;
19
- toolCalls?: undefined;
20
18
  } | {
21
19
  delta: string;
22
20
  done: boolean;
23
21
  usage: any;
24
- toolCalls: import("../types.js").NativeToolCall[];
25
22
  reasoning?: undefined;
26
- } | {
27
- delta: string;
28
- done: boolean;
29
- usage: any;
30
- reasoning?: undefined;
31
- toolCalls?: undefined;
32
23
  }, void, unknown>;
33
- supportsReasoning: () => boolean;
34
24
  };
@@ -22,6 +22,5 @@ export const openrouterProvider = {
22
22
  baseUrl: BASE,
23
23
  defaultModel: "anthropic/claude-sonnet-5.5",
24
24
  listModels: (apiKey) => listModelsHttp({ baseUrl: BASE, apiKey, staticModels: STATIC, extraHeaders: EXTRA_HEADERS }),
25
- stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: BASE, apiKey, staticModels: STATIC, extraHeaders: EXTRA_HEADERS, reasoning: "openrouter" }),
26
- supportsReasoning: () => true,
25
+ stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: BASE, apiKey, staticModels: STATIC, extraHeaders: EXTRA_HEADERS }),
27
26
  };
@@ -10,25 +10,15 @@ export declare const qwenProvider: {
10
10
  done: boolean;
11
11
  reasoning?: undefined;
12
12
  usage?: undefined;
13
- toolCalls?: undefined;
14
13
  } | {
15
14
  delta: string;
16
15
  done: boolean;
17
16
  reasoning: string;
18
17
  usage?: undefined;
19
- toolCalls?: undefined;
20
18
  } | {
21
19
  delta: string;
22
20
  done: boolean;
23
21
  usage: any;
24
- toolCalls: import("../types.js").NativeToolCall[];
25
22
  reasoning?: undefined;
26
- } | {
27
- delta: string;
28
- done: boolean;
29
- usage: any;
30
- reasoning?: undefined;
31
- toolCalls?: undefined;
32
23
  }, void, unknown>;
33
- supportsReasoning: () => boolean;
34
24
  };
@@ -19,6 +19,5 @@ export const qwenProvider = {
19
19
  },
20
20
  defaultModel: "qwen3.8-max",
21
21
  listModels: (apiKey) => listModelsHttp({ baseUrl: baseUrl(), apiKey, staticModels: STATIC }),
22
- stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: baseUrl(), apiKey, staticModels: STATIC, reasoning: "openai" }),
23
- supportsReasoning: () => true,
22
+ stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: baseUrl(), apiKey, staticModels: STATIC }),
24
23
  };
@@ -10,25 +10,15 @@ export declare const xaiProvider: {
10
10
  done: boolean;
11
11
  reasoning?: undefined;
12
12
  usage?: undefined;
13
- toolCalls?: undefined;
14
13
  } | {
15
14
  delta: string;
16
15
  done: boolean;
17
16
  reasoning: string;
18
17
  usage?: undefined;
19
- toolCalls?: undefined;
20
18
  } | {
21
19
  delta: string;
22
20
  done: boolean;
23
21
  usage: any;
24
- toolCalls: import("../types.js").NativeToolCall[];
25
22
  reasoning?: undefined;
26
- } | {
27
- delta: string;
28
- done: boolean;
29
- usage: any;
30
- reasoning?: undefined;
31
- toolCalls?: undefined;
32
23
  }, void, unknown>;
33
- supportsReasoning: () => boolean;
34
24
  };
@@ -14,6 +14,5 @@ export const xaiProvider = {
14
14
  baseUrl: BASE,
15
15
  defaultModel: "grok-4.7",
16
16
  listModels: (apiKey) => listModelsHttp({ baseUrl: BASE, apiKey, staticModels: STATIC }),
17
- stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: BASE, apiKey, staticModels: STATIC, reasoning: "openai" }),
18
- supportsReasoning: () => true,
17
+ stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: BASE, apiKey, staticModels: STATIC }),
19
18
  };
@@ -10,25 +10,15 @@ export declare const zhipuProvider: {
10
10
  done: boolean;
11
11
  reasoning?: undefined;
12
12
  usage?: undefined;
13
- toolCalls?: undefined;
14
13
  } | {
15
14
  delta: string;
16
15
  done: boolean;
17
16
  reasoning: string;
18
17
  usage?: undefined;
19
- toolCalls?: undefined;
20
18
  } | {
21
19
  delta: string;
22
20
  done: boolean;
23
21
  usage: any;
24
- toolCalls: import("../types.js").NativeToolCall[];
25
22
  reasoning?: undefined;
26
- } | {
27
- delta: string;
28
- done: boolean;
29
- usage: any;
30
- reasoning?: undefined;
31
- toolCalls?: undefined;
32
23
  }, void, unknown>;
33
- supportsReasoning: () => boolean;
34
24
  };
@@ -19,6 +19,5 @@ export const zhipuProvider = {
19
19
  },
20
20
  defaultModel: "glm-5.3",
21
21
  listModels: (apiKey) => listModelsHttp({ baseUrl: baseUrl(), apiKey, staticModels: STATIC }),
22
- stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: baseUrl(), apiKey, staticModels: STATIC, reasoning: "openai" }),
23
- supportsReasoning: () => true,
22
+ stream: (req, apiKey) => streamChatCompletion(req, { baseUrl: baseUrl(), apiKey, staticModels: STATIC }),
24
23
  };
@@ -1,36 +1,15 @@
1
- export interface ActiveFile {
2
- path: string;
3
- sha1_8: string;
4
- mtime: string;
5
- }
6
- export interface SessionSummary {
7
- id: string;
8
- file: string;
9
- cwd: string;
10
- providerId: string;
11
- model: string;
12
- turns: number;
13
- activeFiles: ActiveFile[];
14
- messages: number;
15
- lastTs: number;
16
- }
17
1
  export declare function sessionCacheLimitBytes(): number;
18
2
  export declare function loggingEnabled(): boolean;
19
- export declare function projectionPath(file: string): string;
20
- export declare function fsyncMode(): "on" | "off" | "auto";
21
- export declare function fsyncEnabled(type?: string): boolean;
22
- export declare function createSessionLog(meta?: Record<string, any>): {
23
- id: string;
24
- file: string;
25
- append: (entry: Record<string, any>) => number;
26
- count(): number;
3
+ export declare function createSessionLog(meta?: {}): {
4
+ id: any;
5
+ file: any;
6
+ append: (entry: any) => void;
27
7
  close(): void;
28
8
  };
29
- export declare function openSessionLog(file: string, meta?: Record<string, any>): {
30
- id: string;
31
- file: string;
32
- append: (entry: Record<string, any>) => number;
33
- count(): number;
9
+ export declare function openSessionLog(file: any): {
10
+ id: any;
11
+ file: any;
12
+ append: (entry: any) => void;
34
13
  close(): void;
35
14
  };
36
15
  export declare function listSessions(): {
@@ -40,13 +19,11 @@ export declare function listSessions(): {
40
19
  modified: string;
41
20
  messages: number;
42
21
  }[];
43
- export declare function resolveSessionFile(idOrFile: string): string;
44
- export declare function readSession(idOrFile: string): any[];
45
- export declare function loadSessionMessages(idOrFile: string): {
22
+ export declare function resolveSessionFile(idOrFile: any): any;
23
+ export declare function readSession(idOrFile: any): any[];
24
+ export declare function loadSessionMessages(idOrFile: any): {
46
25
  role: any;
47
26
  content: any;
48
27
  }[];
49
- export declare function latestSessionFile(): string | undefined;
50
- export declare function findUnclosedSessions(): SessionSummary[];
51
- export declare function latestUnclosedSession(): SessionSummary | undefined;
28
+ export declare function latestSessionFile(): string;
52
29
  export declare function pruneSessions(limit?: number): number;
@@ -8,10 +8,9 @@
8
8
  *
9
9
  * FASTCODE_SESSION_LOG=0 disable logging
10
10
  * FASTCODE_SESSION_CACHE_MB=N sessions cache cap in MB (default 256)
11
- * FASTCODE_FSYNC=0|1 force checkpoint fsync off/on
12
11
  */
13
- import { appendFileSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
14
- import { basename, join } from "node:path";
12
+ import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync } from "node:fs";
13
+ import { join } from "node:path";
15
14
  import { getPaths } from "../config/paths.js";
16
15
  const NL = String.fromCharCode(10);
17
16
  export function sessionCacheLimitBytes() {
@@ -21,76 +20,19 @@ export function sessionCacheLimitBytes() {
21
20
  export function loggingEnabled() {
22
21
  return process.env["FASTCODE_SESSION_LOG"] !== "0";
23
22
  }
24
- export function projectionPath(file) {
25
- return file.replace(/[.]jsonl$/, ".projection.json");
26
- }
27
- export function fsyncMode() {
28
- const raw = (process.env["FASTCODE_FSYNC"] ?? "").trim().toLowerCase();
29
- if (["1", "true", "yes", "on"].includes(raw))
30
- return "on";
31
- if (["0", "false", "no", "off"].includes(raw))
32
- return "off";
33
- return "auto";
34
- }
35
- function onSharedStorage(root) {
36
- const normalized = root.replace(/\\/g, "/");
37
- return normalized === "/sdcard"
38
- || normalized.startsWith("/sdcard/")
39
- || normalized === "/storage/emulated"
40
- || normalized.startsWith("/storage/emulated/");
41
- }
42
- export function fsyncEnabled(type = "checkpoint") {
43
- if (type !== "checkpoint")
44
- return false;
45
- const mode = fsyncMode();
46
- if (mode === "on")
47
- return true;
48
- if (mode === "off")
49
- return false;
50
- return onSharedStorage(getPaths().root);
51
- }
52
- function writeLine(file, line, type) {
53
- if (!fsyncEnabled(type)) {
54
- appendFileSync(file, line, "utf8");
55
- return;
56
- }
57
- const fd = openSync(file, "a");
58
- try {
59
- writeSync(fd, line);
60
- fsyncSync(fd);
61
- }
62
- finally {
63
- closeSync(fd);
64
- }
65
- }
66
- function countLines(file) {
67
- if (!existsSync(file))
68
- return 0;
69
- try {
70
- return readFileSync(file, "utf8").split(NL).filter(Boolean).length;
71
- }
72
- catch {
73
- return 0;
74
- }
75
- }
76
23
  function newId() {
77
24
  return new Date().toISOString().replace(/[:.]/g, "-") + "-" + Math.random().toString(36).slice(2, 6);
78
25
  }
79
26
  function openLog(id, file, meta) {
80
27
  let closed = false;
81
- let seq = countLines(file);
82
28
  const append = (entry) => {
83
29
  if (closed || !loggingEnabled())
84
- return 0;
85
- const next = seq + 1;
86
- const line = JSON.stringify({ ts: Date.now(), seq: next, ...entry }) + NL;
30
+ return;
87
31
  try {
88
- writeLine(file, line, String(entry.type ?? ""));
89
- seq = next;
90
- return next;
32
+ appendFileSync(file, JSON.stringify({ ts: Date.now(), ...entry }) + NL, "utf8");
91
33
  }
92
34
  catch {
93
- return 0;
35
+ // A read-only or full filesystem must not break the TUI.
94
36
  }
95
37
  };
96
38
  append({ type: "session_start", id, cwd: process.cwd(), ...meta });
@@ -98,9 +40,6 @@ function openLog(id, file, meta) {
98
40
  id,
99
41
  file,
100
42
  append,
101
- count() {
102
- return seq;
103
- },
104
43
  close() {
105
44
  append({ type: "session_end" });
106
45
  closed = true;
@@ -120,10 +59,10 @@ export function createSessionLog(meta = {}) {
120
59
  const file = join(sessions, id + ".jsonl");
121
60
  return openLog(id, file, meta);
122
61
  }
123
- export function openSessionLog(file, meta = {}) {
62
+ export function openSessionLog(file) {
124
63
  const { sessions } = getPaths();
125
64
  mkdirSync(sessions, { recursive: true });
126
- return openLog(undefined, existsSync(file) ? file : join(sessions, file), meta);
65
+ return openLog(undefined, existsSync(file) ? file : join(sessions, file), {});
127
66
  }
128
67
  export function listSessions() {
129
68
  const { sessions } = getPaths();
@@ -140,8 +79,7 @@ export function listSessions() {
140
79
  const info = statSync(file);
141
80
  bytes = info.size;
142
81
  modified = info.mtime.toISOString();
143
- messages = readFileSync(file, "utf8").split(NL).filter((line) => line.includes('"type":"user"') ||
144
- (line.includes('"type":"message"') && line.includes('"role":"user"'))).length;
82
+ messages = readFileSync(file, "utf8").split(NL).filter((line) => line.includes('"type":"message"')).length;
145
83
  }
146
84
  catch {
147
85
  // unreadable: report what we have
@@ -174,152 +112,18 @@ export function readSession(idOrFile) {
174
112
  }
175
113
  export function loadSessionMessages(idOrFile) {
176
114
  return readSession(idOrFile)
177
- .filter((entry) => (entry.type === "message" || entry.type === "user" || entry.type === "assistant_raw") && typeof entry.content === "string")
178
- .map((entry) => ({
179
- role: entry.type === "assistant_raw" ? "assistant" : entry.role ?? "user",
180
- content: entry.content,
181
- }));
115
+ .filter((entry) => entry.type === "message" && typeof entry.content === "string")
116
+ .map((entry) => ({ role: entry.role, content: entry.content }));
182
117
  }
183
118
  export function latestSessionFile() {
184
119
  const all = listSessions();
185
120
  return all.length > 0 ? all[0].file : undefined;
186
121
  }
187
- function summarize(id, file, entries) {
188
- let cwd = "";
189
- let providerId = "";
190
- let model = "";
191
- let turns = 0;
192
- let activeFiles = [];
193
- let messages = 0;
194
- let lastTs = 0;
195
- for (const entry of entries) {
196
- if (typeof entry.ts === "number")
197
- lastTs = entry.ts;
198
- if (entry.type === "session_start") {
199
- cwd = typeof entry.cwd === "string" ? entry.cwd : cwd;
200
- providerId = typeof entry.providerId === "string" ? entry.providerId : providerId;
201
- model = typeof entry.model === "string" ? entry.model : model;
202
- }
203
- else if (entry.type === "message") {
204
- messages += 1;
205
- }
206
- else if (entry.type === "checkpoint") {
207
- cwd = typeof entry.cwd === "string" ? entry.cwd : cwd;
208
- providerId = typeof entry.providerId === "string" ? entry.providerId : providerId;
209
- model = typeof entry.model === "string" ? entry.model : model;
210
- if (typeof entry.turn === "number")
211
- turns = entry.turn;
212
- if (Array.isArray(entry.activeFiles))
213
- activeFiles = entry.activeFiles;
214
- }
215
- }
216
- return { id, file, cwd, providerId, model, turns, activeFiles, messages, lastTs };
217
- }
218
- function readLastEntry(file) {
219
- let size = 0;
220
- try {
221
- size = statSync(file).size;
222
- }
223
- catch {
224
- return undefined;
225
- }
226
- if (size === 0)
227
- return undefined;
228
- const length = Math.min(size, 64 * 1024);
229
- const fd = openSync(file, "r");
230
- try {
231
- const buffer = Buffer.alloc(length);
232
- readSync(fd, buffer, 0, length, size - length);
233
- const lines = buffer.toString("utf8").trimEnd().split(NL);
234
- for (let i = lines.length - 1; i >= 0; i -= 1) {
235
- if (!lines[i])
236
- continue;
237
- try {
238
- return JSON.parse(lines[i]);
239
- }
240
- catch {
241
- return { type: "unparsable_tail" };
242
- }
243
- }
244
- return undefined;
245
- }
246
- finally {
247
- closeSync(fd);
248
- }
249
- }
250
- export function findUnclosedSessions() {
251
- const { sessions } = getPaths();
252
- if (!existsSync(sessions))
253
- return [];
254
- const files = readdirSync(sessions)
255
- .filter((name) => name.endsWith(".jsonl"))
256
- .map((name) => {
257
- const file = join(sessions, name);
258
- let modified = 0;
259
- try {
260
- modified = statSync(file).mtimeMs;
261
- }
262
- catch {
263
- // unreadable
264
- }
265
- return { name, file, modified };
266
- })
267
- .sort((a, b) => b.modified - a.modified);
268
- const out = [];
269
- for (const entry of files) {
270
- const last = readLastEntry(entry.file);
271
- if (!last || last.type === "session_end")
272
- continue;
273
- let entries;
274
- try {
275
- entries = readSession(entry.file);
276
- }
277
- catch {
278
- continue;
279
- }
280
- if (entries.length === 0 || !entries.some((item) => item.type === "session_start"))
281
- continue;
282
- out.push(summarize(entry.name.replace(/[.]jsonl$/, ""), entry.file, entries));
283
- }
284
- return out;
285
- }
286
- export function latestUnclosedSession() {
287
- return findUnclosedSessions()[0];
288
- }
289
- function ensureProjection(file) {
290
- const target = projectionPath(file);
291
- if (existsSync(target))
292
- return;
293
- const entries = readSession(file);
294
- if (entries.length === 0)
295
- return;
296
- const summary = summarize(basename(file).replace(/[.]jsonl$/, ""), file, entries);
297
- const lastUser = [...entries].reverse().find((entry) => entry.type === "message" && entry.role === "user");
298
- const lastAssistant = [...entries].reverse().find((entry) => entry.type === "message" && entry.role === "assistant");
299
- const payload = {
300
- version: 1,
301
- kind: "pruned_session",
302
- source: basename(file),
303
- createdAt: new Date().toISOString(),
304
- summary: {
305
- cwd: summary.cwd,
306
- providerId: summary.providerId,
307
- model: summary.model,
308
- turns: summary.turns,
309
- messages: summary.messages,
310
- activeFiles: summary.activeFiles.slice(0, 200),
311
- lastUser: typeof lastUser?.content === "string" ? lastUser.content.slice(0, 2000) : "",
312
- lastAssistant: typeof lastAssistant?.content === "string" ? lastAssistant.content.slice(0, 2000) : "",
313
- },
314
- };
315
- writeFileSync(target, JSON.stringify(payload, null, 2), "utf8");
316
- }
317
122
  export function pruneSessions(limit = sessionCacheLimitBytes()) {
318
123
  const all = listSessions();
319
124
  let total = all.reduce((sum, entry) => sum + entry.bytes, 0);
320
125
  for (let i = all.length - 1; i >= 0 && total > limit; i -= 1) {
321
126
  try {
322
- ensureProjection(all[i].file);
323
127
  rmSync(all[i].file, { force: true });
324
128
  total -= all[i].bytes;
325
129
  }