cerebras-cli 1.0.1 → 1.0.3

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 (313) hide show
  1. package/cerebras-cli-1.0.0.tgz +0 -0
  2. package/package.json +7 -88
  3. package/AGENTS.md +0 -27
  4. package/Dockerfile +0 -10
  5. package/bunfig.toml +0 -4
  6. package/parsers-config.ts +0 -239
  7. package/script/build.ts +0 -151
  8. package/script/postinstall.mjs +0 -122
  9. package/script/publish.ts +0 -256
  10. package/script/schema.ts +0 -47
  11. package/src/acp/README.md +0 -164
  12. package/src/acp/agent.ts +0 -812
  13. package/src/acp/session.ts +0 -70
  14. package/src/acp/types.ts +0 -22
  15. package/src/agent/agent.ts +0 -310
  16. package/src/agent/generate.txt +0 -75
  17. package/src/auth/index.ts +0 -70
  18. package/src/bun/index.ts +0 -152
  19. package/src/bus/global.ts +0 -10
  20. package/src/bus/index.ts +0 -142
  21. package/src/cli/bootstrap.ts +0 -17
  22. package/src/cli/cmd/acp.ts +0 -88
  23. package/src/cli/cmd/agent.ts +0 -165
  24. package/src/cli/cmd/auth.ts +0 -369
  25. package/src/cli/cmd/cmd.ts +0 -7
  26. package/src/cli/cmd/debug/config.ts +0 -15
  27. package/src/cli/cmd/debug/file.ts +0 -91
  28. package/src/cli/cmd/debug/index.ts +0 -41
  29. package/src/cli/cmd/debug/lsp.ts +0 -47
  30. package/src/cli/cmd/debug/ripgrep.ts +0 -83
  31. package/src/cli/cmd/debug/scrap.ts +0 -15
  32. package/src/cli/cmd/debug/snapshot.ts +0 -48
  33. package/src/cli/cmd/export.ts +0 -88
  34. package/src/cli/cmd/generate.ts +0 -38
  35. package/src/cli/cmd/github.ts +0 -1200
  36. package/src/cli/cmd/import.ts +0 -98
  37. package/src/cli/cmd/mcp.ts +0 -400
  38. package/src/cli/cmd/models.ts +0 -77
  39. package/src/cli/cmd/pr.ts +0 -112
  40. package/src/cli/cmd/run.ts +0 -342
  41. package/src/cli/cmd/serve.ts +0 -31
  42. package/src/cli/cmd/session.ts +0 -106
  43. package/src/cli/cmd/stats.ts +0 -298
  44. package/src/cli/cmd/tui/app.tsx +0 -732
  45. package/src/cli/cmd/tui/attach.ts +0 -25
  46. package/src/cli/cmd/tui/component/border.tsx +0 -21
  47. package/src/cli/cmd/tui/component/dialog-agent.tsx +0 -31
  48. package/src/cli/cmd/tui/component/dialog-command.tsx +0 -124
  49. package/src/cli/cmd/tui/component/dialog-feedback.tsx +0 -160
  50. package/src/cli/cmd/tui/component/dialog-mcp.tsx +0 -86
  51. package/src/cli/cmd/tui/component/dialog-model.tsx +0 -223
  52. package/src/cli/cmd/tui/component/dialog-notification.tsx +0 -78
  53. package/src/cli/cmd/tui/component/dialog-provider.tsx +0 -222
  54. package/src/cli/cmd/tui/component/dialog-session-list.tsx +0 -97
  55. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +0 -31
  56. package/src/cli/cmd/tui/component/dialog-status.tsx +0 -114
  57. package/src/cli/cmd/tui/component/dialog-tag.tsx +0 -44
  58. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +0 -50
  59. package/src/cli/cmd/tui/component/logo.tsx +0 -37
  60. package/src/cli/cmd/tui/component/notification-banner.tsx +0 -58
  61. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +0 -530
  62. package/src/cli/cmd/tui/component/prompt/history.tsx +0 -107
  63. package/src/cli/cmd/tui/component/prompt/index.tsx +0 -931
  64. package/src/cli/cmd/tui/context/args.tsx +0 -14
  65. package/src/cli/cmd/tui/context/directory.ts +0 -12
  66. package/src/cli/cmd/tui/context/exit.tsx +0 -23
  67. package/src/cli/cmd/tui/context/helper.tsx +0 -25
  68. package/src/cli/cmd/tui/context/keybind.tsx +0 -111
  69. package/src/cli/cmd/tui/context/kv.tsx +0 -49
  70. package/src/cli/cmd/tui/context/local.tsx +0 -339
  71. package/src/cli/cmd/tui/context/prompt.tsx +0 -18
  72. package/src/cli/cmd/tui/context/route.tsx +0 -45
  73. package/src/cli/cmd/tui/context/sdk.tsx +0 -75
  74. package/src/cli/cmd/tui/context/sync.tsx +0 -374
  75. package/src/cli/cmd/tui/context/theme/aura.json +0 -69
  76. package/src/cli/cmd/tui/context/theme/ayu.json +0 -80
  77. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +0 -233
  78. package/src/cli/cmd/tui/context/theme/catppuccin.json +0 -112
  79. package/src/cli/cmd/tui/context/theme/cobalt2.json +0 -228
  80. package/src/cli/cmd/tui/context/theme/dracula.json +0 -219
  81. package/src/cli/cmd/tui/context/theme/everforest.json +0 -241
  82. package/src/cli/cmd/tui/context/theme/flexoki.json +0 -237
  83. package/src/cli/cmd/tui/context/theme/github.json +0 -233
  84. package/src/cli/cmd/tui/context/theme/gruvbox.json +0 -95
  85. package/src/cli/cmd/tui/context/theme/kanagawa.json +0 -77
  86. package/src/cli/cmd/tui/context/theme/material.json +0 -235
  87. package/src/cli/cmd/tui/context/theme/matrix.json +0 -77
  88. package/src/cli/cmd/tui/context/theme/mercury.json +0 -252
  89. package/src/cli/cmd/tui/context/theme/monokai.json +0 -221
  90. package/src/cli/cmd/tui/context/theme/nightowl.json +0 -221
  91. package/src/cli/cmd/tui/context/theme/nord.json +0 -223
  92. package/src/cli/cmd/tui/context/theme/one-dark.json +0 -84
  93. package/src/cli/cmd/tui/context/theme/orng.json +0 -245
  94. package/src/cli/cmd/tui/context/theme/palenight.json +0 -222
  95. package/src/cli/cmd/tui/context/theme/rosepine.json +0 -234
  96. package/src/cli/cmd/tui/context/theme/solarized.json +0 -223
  97. package/src/cli/cmd/tui/context/theme/synthwave84.json +0 -226
  98. package/src/cli/cmd/tui/context/theme/tokyonight.json +0 -243
  99. package/src/cli/cmd/tui/context/theme/vercel.json +0 -245
  100. package/src/cli/cmd/tui/context/theme/vesper.json +0 -218
  101. package/src/cli/cmd/tui/context/theme/zenburn.json +0 -223
  102. package/src/cli/cmd/tui/context/theme.tsx +0 -1077
  103. package/src/cli/cmd/tui/event.ts +0 -39
  104. package/src/cli/cmd/tui/routes/home.tsx +0 -104
  105. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +0 -93
  106. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +0 -37
  107. package/src/cli/cmd/tui/routes/session/footer.tsx +0 -76
  108. package/src/cli/cmd/tui/routes/session/header.tsx +0 -183
  109. package/src/cli/cmd/tui/routes/session/index.tsx +0 -1703
  110. package/src/cli/cmd/tui/routes/session/sidebar.tsx +0 -586
  111. package/src/cli/cmd/tui/spawn.ts +0 -60
  112. package/src/cli/cmd/tui/thread.ts +0 -120
  113. package/src/cli/cmd/tui/ui/dialog-alert.tsx +0 -55
  114. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +0 -81
  115. package/src/cli/cmd/tui/ui/dialog-help.tsx +0 -36
  116. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +0 -75
  117. package/src/cli/cmd/tui/ui/dialog-select.tsx +0 -317
  118. package/src/cli/cmd/tui/ui/dialog.tsx +0 -170
  119. package/src/cli/cmd/tui/ui/spinner.ts +0 -368
  120. package/src/cli/cmd/tui/ui/toast.tsx +0 -100
  121. package/src/cli/cmd/tui/util/clipboard.ts +0 -127
  122. package/src/cli/cmd/tui/util/editor.ts +0 -32
  123. package/src/cli/cmd/tui/util/terminal.ts +0 -114
  124. package/src/cli/cmd/tui/worker.ts +0 -63
  125. package/src/cli/cmd/uninstall.ts +0 -344
  126. package/src/cli/cmd/upgrade.ts +0 -67
  127. package/src/cli/cmd/web.ts +0 -84
  128. package/src/cli/error.ts +0 -55
  129. package/src/cli/ui.ts +0 -84
  130. package/src/cli/upgrade.ts +0 -25
  131. package/src/command/index.ts +0 -79
  132. package/src/command/template/initialize.txt +0 -10
  133. package/src/command/template/review.txt +0 -73
  134. package/src/config/config.ts +0 -886
  135. package/src/config/markdown.ts +0 -41
  136. package/src/env/index.ts +0 -26
  137. package/src/file/fzf.ts +0 -124
  138. package/src/file/ignore.ts +0 -83
  139. package/src/file/index.ts +0 -326
  140. package/src/file/ripgrep.ts +0 -391
  141. package/src/file/time.ts +0 -38
  142. package/src/file/watcher.ts +0 -89
  143. package/src/flag/flag.ts +0 -28
  144. package/src/format/formatter.ts +0 -277
  145. package/src/format/index.ts +0 -137
  146. package/src/global/index.ts +0 -52
  147. package/src/id/id.ts +0 -73
  148. package/src/ide/index.ts +0 -75
  149. package/src/index.ts +0 -158
  150. package/src/installation/index.ts +0 -194
  151. package/src/lsp/client.ts +0 -215
  152. package/src/lsp/index.ts +0 -370
  153. package/src/lsp/language.ts +0 -111
  154. package/src/lsp/server.ts +0 -1327
  155. package/src/mcp/auth.ts +0 -82
  156. package/src/mcp/index.ts +0 -576
  157. package/src/mcp/oauth-callback.ts +0 -203
  158. package/src/mcp/oauth-provider.ts +0 -132
  159. package/src/notification/index.ts +0 -101
  160. package/src/patch/index.ts +0 -622
  161. package/src/permission/index.ts +0 -198
  162. package/src/plugin/index.ts +0 -95
  163. package/src/project/bootstrap.ts +0 -31
  164. package/src/project/instance.ts +0 -68
  165. package/src/project/project.ts +0 -133
  166. package/src/project/state.ts +0 -65
  167. package/src/project/vcs.ts +0 -77
  168. package/src/provider/auth.ts +0 -143
  169. package/src/provider/models-macro.ts +0 -11
  170. package/src/provider/models.ts +0 -93
  171. package/src/provider/provider.ts +0 -996
  172. package/src/provider/sdk/openai-compatible/src/README.md +0 -5
  173. package/src/provider/sdk/openai-compatible/src/index.ts +0 -2
  174. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +0 -100
  175. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +0 -303
  176. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +0 -27
  177. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +0 -18
  178. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +0 -22
  179. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +0 -207
  180. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +0 -1713
  181. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +0 -177
  182. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +0 -1
  183. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +0 -88
  184. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +0 -128
  185. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +0 -115
  186. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +0 -65
  187. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +0 -104
  188. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +0 -103
  189. package/src/provider/transform.ts +0 -406
  190. package/src/pty/index.ts +0 -226
  191. package/src/ratelimit/index.ts +0 -185
  192. package/src/server/error.ts +0 -36
  193. package/src/server/project.ts +0 -50
  194. package/src/server/server.ts +0 -2463
  195. package/src/server/tui.ts +0 -71
  196. package/src/session/compaction.ts +0 -257
  197. package/src/session/index.ts +0 -470
  198. package/src/session/message-v2.ts +0 -641
  199. package/src/session/message.ts +0 -189
  200. package/src/session/processor.ts +0 -443
  201. package/src/session/prompt/anthropic-20250930.txt +0 -166
  202. package/src/session/prompt/anthropic.txt +0 -105
  203. package/src/session/prompt/anthropic_spoof.txt +0 -1
  204. package/src/session/prompt/beast.txt +0 -147
  205. package/src/session/prompt/build-switch.txt +0 -5
  206. package/src/session/prompt/codex.txt +0 -318
  207. package/src/session/prompt/compaction.txt +0 -12
  208. package/src/session/prompt/copilot-gpt-5.txt +0 -143
  209. package/src/session/prompt/gemini.txt +0 -155
  210. package/src/session/prompt/max-steps.txt +0 -16
  211. package/src/session/prompt/plan-reminder-anthropic.txt +0 -67
  212. package/src/session/prompt/plan.txt +0 -26
  213. package/src/session/prompt/polaris.txt +0 -107
  214. package/src/session/prompt/qwen.txt +0 -109
  215. package/src/session/prompt/summarize.txt +0 -4
  216. package/src/session/prompt/title.txt +0 -36
  217. package/src/session/prompt.ts +0 -1541
  218. package/src/session/retry.ts +0 -82
  219. package/src/session/revert.ts +0 -108
  220. package/src/session/status.ts +0 -75
  221. package/src/session/summary.ts +0 -203
  222. package/src/session/system.ts +0 -148
  223. package/src/session/todo.ts +0 -36
  224. package/src/share/share-next.ts +0 -195
  225. package/src/share/share.ts +0 -87
  226. package/src/snapshot/index.ts +0 -197
  227. package/src/storage/storage.ts +0 -226
  228. package/src/telemetry/index.ts +0 -232
  229. package/src/tool/bash.ts +0 -365
  230. package/src/tool/bash.txt +0 -128
  231. package/src/tool/batch.ts +0 -173
  232. package/src/tool/batch.txt +0 -28
  233. package/src/tool/codesearch.ts +0 -138
  234. package/src/tool/codesearch.txt +0 -12
  235. package/src/tool/edit.ts +0 -674
  236. package/src/tool/edit.txt +0 -10
  237. package/src/tool/glob.ts +0 -65
  238. package/src/tool/glob.txt +0 -6
  239. package/src/tool/grep.ts +0 -120
  240. package/src/tool/grep.txt +0 -8
  241. package/src/tool/invalid.ts +0 -17
  242. package/src/tool/ls.ts +0 -110
  243. package/src/tool/ls.txt +0 -1
  244. package/src/tool/lsp-diagnostics.ts +0 -26
  245. package/src/tool/lsp-diagnostics.txt +0 -1
  246. package/src/tool/lsp-hover.ts +0 -31
  247. package/src/tool/lsp-hover.txt +0 -1
  248. package/src/tool/multiedit.ts +0 -46
  249. package/src/tool/multiedit.txt +0 -41
  250. package/src/tool/patch.ts +0 -233
  251. package/src/tool/patch.txt +0 -1
  252. package/src/tool/read.ts +0 -217
  253. package/src/tool/read.txt +0 -12
  254. package/src/tool/registry.ts +0 -148
  255. package/src/tool/task.ts +0 -135
  256. package/src/tool/task.txt +0 -60
  257. package/src/tool/todo.ts +0 -39
  258. package/src/tool/todoread.txt +0 -14
  259. package/src/tool/todowrite.txt +0 -167
  260. package/src/tool/tool.ts +0 -66
  261. package/src/tool/webfetch.ts +0 -187
  262. package/src/tool/webfetch.txt +0 -14
  263. package/src/tool/websearch.ts +0 -150
  264. package/src/tool/websearch.txt +0 -11
  265. package/src/tool/write.ts +0 -99
  266. package/src/tool/write.txt +0 -8
  267. package/src/types/shims.d.ts +0 -3
  268. package/src/util/color.ts +0 -19
  269. package/src/util/context.ts +0 -25
  270. package/src/util/defer.ts +0 -12
  271. package/src/util/eventloop.ts +0 -20
  272. package/src/util/filesystem.ts +0 -69
  273. package/src/util/fn.ts +0 -11
  274. package/src/util/iife.ts +0 -3
  275. package/src/util/keybind.ts +0 -79
  276. package/src/util/lazy.ts +0 -11
  277. package/src/util/locale.ts +0 -81
  278. package/src/util/lock.ts +0 -98
  279. package/src/util/log.ts +0 -177
  280. package/src/util/queue.ts +0 -32
  281. package/src/util/rpc.ts +0 -42
  282. package/src/util/scrap.ts +0 -10
  283. package/src/util/signal.ts +0 -12
  284. package/src/util/timeout.ts +0 -14
  285. package/src/util/token.ts +0 -7
  286. package/src/util/wildcard.ts +0 -54
  287. package/sst-env.d.ts +0 -9
  288. package/test/bun.test.ts +0 -53
  289. package/test/config/agent-color.test.ts +0 -66
  290. package/test/config/config.test.ts +0 -503
  291. package/test/config/markdown.test.ts +0 -89
  292. package/test/file/ignore.test.ts +0 -10
  293. package/test/fixture/fixture.ts +0 -28
  294. package/test/fixture/lsp/fake-lsp-server.js +0 -77
  295. package/test/ide/ide.test.ts +0 -82
  296. package/test/keybind.test.ts +0 -317
  297. package/test/lsp/client.test.ts +0 -95
  298. package/test/patch/patch.test.ts +0 -348
  299. package/test/preload.ts +0 -38
  300. package/test/project/project.test.ts +0 -42
  301. package/test/provider/provider.test.ts +0 -1809
  302. package/test/provider/transform.test.ts +0 -305
  303. package/test/session/retry.test.ts +0 -61
  304. package/test/session/session.test.ts +0 -71
  305. package/test/snapshot/snapshot.test.ts +0 -939
  306. package/test/tool/__snapshots__/tool.test.ts.snap +0 -9
  307. package/test/tool/bash.test.ts +0 -55
  308. package/test/tool/patch.test.ts +0 -259
  309. package/test/util/iife.test.ts +0 -36
  310. package/test/util/lazy.test.ts +0 -50
  311. package/test/util/timeout.test.ts +0 -21
  312. package/test/util/wildcard.test.ts +0 -55
  313. package/tsconfig.json +0 -17
@@ -1,232 +0,0 @@
1
- import { Log } from "@/util/log"
2
- import { Instance } from "@/project/instance"
3
- import z from "zod"
4
-
5
- /**
6
- * Telemetry module for logging API request metrics to Cloudflare worker
7
- *
8
- * Tracks cache hit rates, token usage, conversation turns, and other metrics
9
- * for monitoring and optimization purposes.
10
- */
11
- export namespace Telemetry {
12
- const log = Log.create({ service: "telemetry" })
13
-
14
- // Telemetry endpoint
15
- const TELEMETRY_ENDPOINT =
16
- process.env.OPENCODE_TELEMETRY_URL || "https://opencode-telemetry.kevin-taylor-d8d.workers.dev"
17
-
18
- // Batch settings
19
- const BATCH_SIZE = 10
20
- const BATCH_INTERVAL_MS = 30_000 // 30 seconds
21
-
22
- // Schema for telemetry entry
23
- export const Entry = z.object({
24
- // Identifiers
25
- sessionID: z.string().optional(),
26
- providerID: z.string().optional(),
27
- modelID: z.string().optional(),
28
-
29
- // Per-step token metrics
30
- inputTokens: z.number().default(0),
31
- outputTokens: z.number().default(0),
32
- reasoningTokens: z.number().default(0),
33
- cachedTokens: z.number().default(0),
34
-
35
- // Per-step computed metrics
36
- cacheHitRate: z.number().default(0),
37
-
38
- // Session-level cumulative totals (like sidebar displays)
39
- sessionTotalCachedTokens: z.number().default(0),
40
- sessionTotalPromptTokens: z.number().default(0),
41
- sessionTotalOutputTokens: z.number().default(0),
42
- sessionOverallHitRate: z.number().default(0),
43
-
44
- // Session context
45
- conversationTurns: z.number().default(0),
46
-
47
- // Metadata
48
- finishReason: z.string().optional(),
49
- })
50
- export type Entry = z.infer<typeof Entry>
51
-
52
- // Internal state for batching
53
- const state = Instance.state(
54
- () => {
55
- const queue: Entry[] = []
56
- let timer: ReturnType<typeof setTimeout> | undefined
57
-
58
- return {
59
- queue,
60
- timer,
61
- enabled: true,
62
- }
63
- },
64
- async (entry) => {
65
- // Flush remaining entries on shutdown
66
- if (entry.timer) {
67
- clearTimeout(entry.timer)
68
- }
69
- if (entry.queue.length > 0) {
70
- await flush(entry.queue)
71
- entry.queue.length = 0
72
- }
73
- },
74
- )
75
-
76
- /**
77
- * Check if telemetry is enabled
78
- */
79
- export function isEnabled(): boolean {
80
- return state().enabled
81
- }
82
-
83
- /**
84
- * Enable or disable telemetry
85
- */
86
- export function setEnabled(enabled: boolean): void {
87
- state().enabled = enabled
88
- if (!enabled) {
89
- // Clear any pending entries
90
- state().queue.length = 0
91
- if (state().timer) {
92
- clearTimeout(state().timer)
93
- state().timer = undefined
94
- }
95
- }
96
- }
97
-
98
- /**
99
- * Log a telemetry entry
100
- *
101
- * Entries are batched and sent periodically to reduce network overhead.
102
- */
103
- export function track(entry: Entry): void {
104
- const s = state()
105
- if (!s.enabled) return
106
-
107
- log.info("tracking telemetry", {
108
- providerID: entry.providerID,
109
- modelID: entry.modelID,
110
- cacheHitRate: entry.cacheHitRate,
111
- cachedTokens: entry.cachedTokens,
112
- inputTokens: entry.inputTokens,
113
- })
114
-
115
- s.queue.push(entry)
116
-
117
- // Send immediately if batch is full
118
- if (s.queue.length >= BATCH_SIZE) {
119
- const entries = s.queue.splice(0, BATCH_SIZE)
120
- flush(entries).catch((e) => log.error("flush error", { error: e }))
121
- }
122
-
123
- // Start batch timer if not already running
124
- if (!s.timer) {
125
- s.timer = setTimeout(() => {
126
- s.timer = undefined
127
- if (s.queue.length > 0) {
128
- const entries = s.queue.splice(0)
129
- flush(entries).catch((e) => log.error("flush error", { error: e }))
130
- }
131
- }, BATCH_INTERVAL_MS)
132
- }
133
- }
134
-
135
- /**
136
- * Convenience method to track from session processor data
137
- */
138
- export function trackFromUsage(input: {
139
- sessionID: string
140
- providerID: string
141
- modelID: string
142
- // Per-step tokens
143
- tokens: {
144
- input: number
145
- output: number
146
- reasoning: number
147
- cache: {
148
- read: number
149
- }
150
- }
151
- conversationTurns: number
152
- finishReason?: string
153
- // Session-level cumulative totals
154
- sessionTotals?: {
155
- cachedTokens: number
156
- promptTokens: number
157
- outputTokens: number
158
- }
159
- }): void {
160
- // Calculate per-step cache hit rate
161
- const totalPromptTokens = input.tokens.input + input.tokens.cache.read
162
- const cacheHitRate = totalPromptTokens > 0 ? (input.tokens.cache.read / totalPromptTokens) * 100 : 0
163
-
164
- // Calculate session-level overall hit rate
165
- const sessionOverallHitRate =
166
- input.sessionTotals && input.sessionTotals.promptTokens > 0
167
- ? (input.sessionTotals.cachedTokens / input.sessionTotals.promptTokens) * 100
168
- : 0
169
-
170
- track({
171
- sessionID: input.sessionID,
172
- providerID: input.providerID,
173
- modelID: input.modelID,
174
- // Per-step metrics
175
- inputTokens: input.tokens.input,
176
- outputTokens: input.tokens.output,
177
- reasoningTokens: input.tokens.reasoning,
178
- cachedTokens: input.tokens.cache.read,
179
- cacheHitRate,
180
- // Session-level cumulative totals
181
- sessionTotalCachedTokens: input.sessionTotals?.cachedTokens ?? 0,
182
- sessionTotalPromptTokens: input.sessionTotals?.promptTokens ?? 0,
183
- sessionTotalOutputTokens: input.sessionTotals?.outputTokens ?? 0,
184
- sessionOverallHitRate,
185
- // Context
186
- conversationTurns: input.conversationTurns,
187
- finishReason: input.finishReason,
188
- })
189
- }
190
-
191
- /**
192
- * Flush entries to the telemetry endpoint
193
- */
194
- async function flush(entries: Entry[]): Promise<void> {
195
- if (entries.length === 0) return
196
-
197
- log.info("flushing telemetry", { count: entries.length })
198
-
199
- try {
200
- const enrichedEntries = entries
201
-
202
- const res = await fetch(`${TELEMETRY_ENDPOINT}/batch`, {
203
- method: "POST",
204
- headers: { "Content-Type": "application/json" },
205
- body: JSON.stringify({ entries: enrichedEntries }),
206
- })
207
-
208
- if (!res.ok) {
209
- log.error("telemetry flush failed", { status: res.status })
210
- }
211
- } catch (e) {
212
- // Silently fail - telemetry should not disrupt normal operation
213
- log.error("telemetry error", { error: e })
214
- }
215
- }
216
-
217
- /**
218
- * Force flush any pending entries immediately
219
- */
220
- export async function forceFlush(): Promise<void> {
221
- const s = state()
222
- if (s.timer) {
223
- clearTimeout(s.timer)
224
- s.timer = undefined
225
- }
226
- if (s.queue.length > 0) {
227
- const entries = s.queue.splice(0)
228
- await flush(entries)
229
- }
230
- }
231
- }
232
-
package/src/tool/bash.ts DELETED
@@ -1,365 +0,0 @@
1
- import z from "zod"
2
- import { spawn } from "child_process"
3
- import { Tool } from "./tool"
4
- import DESCRIPTION from "./bash.txt"
5
- import { Log } from "../util/log"
6
- import { Instance } from "../project/instance"
7
- import { lazy } from "@/util/lazy"
8
- import { Language } from "web-tree-sitter"
9
- import { Agent } from "@/agent/agent"
10
- import { $ } from "bun"
11
- import { Filesystem } from "@/util/filesystem"
12
- import { Wildcard } from "@/util/wildcard"
13
- import { Permission } from "@/permission"
14
- import { fileURLToPath } from "url"
15
- import { Flag } from "@/flag/flag.ts"
16
- import path from "path"
17
- import { iife } from "@/util/iife"
18
-
19
- const DEFAULT_MAX_OUTPUT_LENGTH = 30_000
20
- const MAX_OUTPUT_LENGTH = (() => {
21
- const parsed = Number(Flag.OPENCODE_EXPERIMENTAL_BASH_MAX_OUTPUT_LENGTH)
22
- return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_OUTPUT_LENGTH
23
- })()
24
- const DEFAULT_TIMEOUT = 2 * 60 * 1000
25
- const SIGKILL_TIMEOUT_MS = 200
26
-
27
- export const log = Log.create({ service: "bash-tool" })
28
-
29
- const resolveWasm = (asset: string) => {
30
- if (asset.startsWith("file://")) return fileURLToPath(asset)
31
- if (asset.startsWith("/") || /^[a-z]:/i.test(asset)) return asset
32
- const url = new URL(asset, import.meta.url)
33
- return fileURLToPath(url)
34
- }
35
-
36
- const parser = lazy(async () => {
37
- const { Parser } = await import("web-tree-sitter")
38
- const { default: treeWasm } = await import("web-tree-sitter/tree-sitter.wasm" as string, {
39
- with: { type: "wasm" },
40
- })
41
- const treePath = resolveWasm(treeWasm)
42
- await Parser.init({
43
- locateFile() {
44
- return treePath
45
- },
46
- })
47
- const { default: bashWasm } = await import("tree-sitter-bash/tree-sitter-bash.wasm" as string, {
48
- with: { type: "wasm" },
49
- })
50
- const bashPath = resolveWasm(bashWasm)
51
- const bashLanguage = await Language.load(bashPath)
52
- const p = new Parser()
53
- p.setLanguage(bashLanguage)
54
- return p
55
- })
56
-
57
- // TODO: we may wanna rename this tool so it works better on other shells
58
-
59
- export const BashTool = Tool.define("bash", async () => {
60
- const shell = iife(() => {
61
- const s = process.env.SHELL
62
- if (s) {
63
- const basename = path.basename(s)
64
- if (!new Set(["fish", "nu"]).has(basename)) {
65
- return s
66
- }
67
- }
68
-
69
- if (process.platform === "darwin") {
70
- return "/bin/zsh"
71
- }
72
-
73
- if (process.platform === "win32") {
74
- // Let Bun / Node pick COMSPEC (usually cmd.exe)
75
- // or explicitly:
76
- return process.env.COMSPEC || true
77
- }
78
-
79
- const bash = Bun.which("bash")
80
- if (bash) {
81
- return bash
82
- }
83
-
84
- return true
85
- })
86
- log.info("bash tool using shell", { shell })
87
-
88
- return {
89
- description: DESCRIPTION,
90
- parameters: z.object({
91
- command: z.string().describe("The command to execute"),
92
- timeout: z.number().describe("Optional timeout in milliseconds").optional(),
93
- workdir: z
94
- .string()
95
- .describe(
96
- `The working directory to run the command in. Defaults to ${Instance.directory}. Use this instead of 'cd' commands.`,
97
- )
98
- .optional(),
99
- description: z
100
- .string()
101
- .describe(
102
- "Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'",
103
- ),
104
- }),
105
- async execute(params, ctx) {
106
- const cwd = params.workdir || Instance.directory
107
- if (params.timeout !== undefined && params.timeout < 0) {
108
- throw new Error(`Invalid timeout value: ${params.timeout}. Timeout must be a positive number.`)
109
- }
110
- const timeout = params.timeout ?? DEFAULT_TIMEOUT
111
- const tree = await parser().then((p) => p.parse(params.command))
112
- if (!tree) {
113
- throw new Error("Failed to parse command")
114
- }
115
- const agent = await Agent.get(ctx.agent)
116
-
117
- const checkExternalDirectory = async (dir: string) => {
118
- if (Filesystem.contains(Instance.directory, dir)) return
119
- const title = `This command references paths outside of ${Instance.directory}`
120
- if (agent.permission.external_directory === "ask") {
121
- await Permission.ask({
122
- type: "external_directory",
123
- pattern: [dir, path.join(dir, "*")],
124
- sessionID: ctx.sessionID,
125
- messageID: ctx.messageID,
126
- callID: ctx.callID,
127
- title,
128
- metadata: {
129
- command: params.command,
130
- },
131
- })
132
- } else if (agent.permission.external_directory === "deny") {
133
- throw new Permission.RejectedError(
134
- ctx.sessionID,
135
- "external_directory",
136
- ctx.callID,
137
- {
138
- command: params.command,
139
- },
140
- `${title} so this command is not allowed to be executed.`,
141
- )
142
- }
143
- }
144
-
145
- await checkExternalDirectory(cwd)
146
-
147
- const permissions = agent.permission.bash
148
-
149
- const askPatterns = new Set<string>()
150
- for (const node of tree.rootNode.descendantsOfType("command")) {
151
- if (!node) continue
152
- const command = []
153
- for (let i = 0; i < node.childCount; i++) {
154
- const child = node.child(i)
155
- if (!child) continue
156
- if (
157
- child.type !== "command_name" &&
158
- child.type !== "word" &&
159
- child.type !== "string" &&
160
- child.type !== "raw_string" &&
161
- child.type !== "concatenation"
162
- ) {
163
- continue
164
- }
165
- command.push(child.text)
166
- }
167
-
168
- // not an exhaustive list, but covers most common cases
169
- if (["cd", "rm", "cp", "mv", "mkdir", "touch", "chmod", "chown"].includes(command[0])) {
170
- for (const arg of command.slice(1)) {
171
- if (arg.startsWith("-") || (command[0] === "chmod" && arg.startsWith("+"))) continue
172
- const resolved = await $`realpath ${arg}`
173
- .quiet()
174
- .nothrow()
175
- .text()
176
- .then((x) => x.trim())
177
- log.info("resolved path", { arg, resolved })
178
- if (resolved) {
179
- // Git Bash on Windows returns Unix-style paths like /c/Users/...
180
- const normalized =
181
- process.platform === "win32" && resolved.match(/^\/[a-z]\//)
182
- ? resolved.replace(/^\/([a-z])\//, (_, drive) => `${drive.toUpperCase()}:\\`).replace(/\//g, "\\")
183
- : resolved
184
-
185
- await checkExternalDirectory(normalized)
186
- }
187
- }
188
- }
189
-
190
- // always allow cd if it passes above check
191
- if (command[0] !== "cd") {
192
- const action = Wildcard.allStructured({ head: command[0], tail: command.slice(1) }, permissions)
193
- if (action === "deny") {
194
- throw new Error(
195
- `The user has specifically restricted access to this command, you are not allowed to execute it. Here is the configuration: ${JSON.stringify(permissions)}`,
196
- )
197
- }
198
- if (action === "ask") {
199
- const pattern = (() => {
200
- if (command.length === 0) return
201
- const head = command[0]
202
- // Find first non-flag argument as subcommand
203
- const sub = command.slice(1).find((arg) => !arg.startsWith("-"))
204
- return sub ? `${head} ${sub} *` : `${head} *`
205
- })()
206
- if (pattern) {
207
- askPatterns.add(pattern)
208
- }
209
- }
210
- }
211
- }
212
-
213
- if (askPatterns.size > 0) {
214
- const patterns = Array.from(askPatterns)
215
- await Permission.ask({
216
- type: "bash",
217
- pattern: patterns,
218
- sessionID: ctx.sessionID,
219
- messageID: ctx.messageID,
220
- callID: ctx.callID,
221
- title: params.command,
222
- metadata: {
223
- command: params.command,
224
- patterns,
225
- },
226
- })
227
- }
228
-
229
- const proc = spawn(params.command, {
230
- shell,
231
- cwd,
232
- env: {
233
- ...process.env,
234
- },
235
- stdio: ["ignore", "pipe", "pipe"],
236
- detached: process.platform !== "win32",
237
- })
238
-
239
- let output = ""
240
-
241
- // Initialize metadata with empty output
242
- ctx.metadata({
243
- metadata: {
244
- output: "",
245
- description: params.description,
246
- },
247
- })
248
-
249
- const append = (chunk: Buffer) => {
250
- if (output.length <= MAX_OUTPUT_LENGTH) {
251
- output += chunk.toString()
252
- ctx.metadata({
253
- metadata: {
254
- output,
255
- description: params.description,
256
- },
257
- })
258
- }
259
- }
260
-
261
- proc.stdout?.on("data", append)
262
- proc.stderr?.on("data", append)
263
-
264
- let timedOut = false
265
- let aborted = false
266
- let exited = false
267
-
268
- const killTree = async () => {
269
- const pid = proc.pid
270
- if (!pid || exited) {
271
- return
272
- }
273
-
274
- if (process.platform === "win32") {
275
- await new Promise<void>((resolve) => {
276
- const killer = spawn("taskkill", ["/pid", String(pid), "/f", "/t"], { stdio: "ignore" })
277
- killer.once("exit", resolve)
278
- killer.once("error", resolve)
279
- })
280
- return
281
- }
282
-
283
- try {
284
- process.kill(-pid, "SIGTERM")
285
- await Bun.sleep(SIGKILL_TIMEOUT_MS)
286
- if (!exited) {
287
- process.kill(-pid, "SIGKILL")
288
- }
289
- } catch (_e) {
290
- proc.kill("SIGTERM")
291
- await Bun.sleep(SIGKILL_TIMEOUT_MS)
292
- if (!exited) {
293
- proc.kill("SIGKILL")
294
- }
295
- }
296
- }
297
-
298
- if (ctx.abort.aborted) {
299
- aborted = true
300
- await killTree()
301
- }
302
-
303
- const abortHandler = () => {
304
- aborted = true
305
- void killTree()
306
- }
307
-
308
- ctx.abort.addEventListener("abort", abortHandler, { once: true })
309
-
310
- const timeoutTimer = setTimeout(() => {
311
- timedOut = true
312
- void killTree()
313
- }, timeout + 100)
314
-
315
- await new Promise<void>((resolve, reject) => {
316
- const cleanup = () => {
317
- clearTimeout(timeoutTimer)
318
- ctx.abort.removeEventListener("abort", abortHandler)
319
- }
320
-
321
- proc.once("exit", () => {
322
- exited = true
323
- cleanup()
324
- resolve()
325
- })
326
-
327
- proc.once("error", (error) => {
328
- exited = true
329
- cleanup()
330
- reject(error)
331
- })
332
- })
333
-
334
- let resultMetadata: String[] = ["<bash_metadata>"]
335
-
336
- if (output.length > MAX_OUTPUT_LENGTH) {
337
- output = output.slice(0, MAX_OUTPUT_LENGTH)
338
- resultMetadata.push(`bash tool truncated output as it exceeded ${MAX_OUTPUT_LENGTH} char limit`)
339
- }
340
-
341
- if (timedOut) {
342
- resultMetadata.push(`bash tool terminated commmand after exceeding timeout ${timeout} ms`)
343
- }
344
-
345
- if (aborted) {
346
- resultMetadata.push("User aborted the command")
347
- }
348
-
349
- if (resultMetadata.length > 1) {
350
- resultMetadata.push("</bash_metadata>")
351
- output += "\n\n" + resultMetadata.join("\n")
352
- }
353
-
354
- return {
355
- title: params.description,
356
- metadata: {
357
- output,
358
- exit: proc.exitCode,
359
- description: params.description,
360
- },
361
- output,
362
- }
363
- },
364
- }
365
- })