@agentprojectcontext/apx 1.15.6 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/package.json +46 -5
  2. package/src/cli/commands/log.js +113 -0
  3. package/src/cli/commands/overlay.js +253 -0
  4. package/src/cli/commands/sys.js +88 -16
  5. package/src/cli/index.js +23 -1
  6. package/src/cli/terminal-chat/renderer.js +71 -56
  7. package/src/cli-ts/commands/agent.ts +173 -0
  8. package/src/cli-ts/commands/chat.ts +119 -0
  9. package/src/cli-ts/commands/daemon.ts +112 -0
  10. package/src/cli-ts/commands/exec.ts +109 -0
  11. package/src/cli-ts/commands/mcp.ts +235 -0
  12. package/src/cli-ts/commands/session.ts +224 -0
  13. package/src/cli-ts/commands/status.ts +61 -0
  14. package/src/cli-ts/http.ts +36 -0
  15. package/src/cli-ts/index.ts +73 -0
  16. package/src/cli-ts/ui.ts +107 -0
  17. package/src/core/logging.js +81 -0
  18. package/src/daemon/api.js +58 -0
  19. package/src/daemon/engines/anthropic.js +60 -1
  20. package/src/daemon/engines/index.js +2 -1
  21. package/src/daemon/engines/ollama.js +70 -3
  22. package/src/daemon/index.js +58 -0
  23. package/src/daemon/overlay-ws.js +40 -0
  24. package/src/daemon/plugins/index.js +2 -1
  25. package/src/daemon/plugins/overlay.js +177 -0
  26. package/src/daemon/plugins/telegram.js +15 -3
  27. package/src/daemon/super-agent-langchain.js +296 -0
  28. package/src/daemon/super-agent.js +115 -19
  29. package/src/daemon/transcription.js +262 -59
  30. package/src/daemon/whisper-server.py +57 -6
  31. package/src/overlay/index.html +44 -0
  32. package/src/overlay/main.js +480 -0
  33. package/src/overlay/package.json +3 -0
  34. package/src/overlay/preload.js +34 -0
  35. package/src/overlay/renderer.js +371 -0
  36. package/src/overlay/style.css +250 -0
  37. package/src/tui/_shims/cli-error.ts +6 -0
  38. package/src/tui/_shims/cli-logo.ts +18 -0
  39. package/src/tui/_shims/cli-ui.ts +1 -0
  40. package/src/tui/_shims/config-console-state.ts +7 -0
  41. package/src/tui/_shims/core-any.ts +30 -0
  42. package/src/tui/_shims/core-binary.ts +13 -0
  43. package/src/tui/_shims/core-flag.ts +3 -0
  44. package/src/tui/_shims/core-log.ts +14 -0
  45. package/src/tui/_shims/lsp-language.ts +1 -0
  46. package/src/tui/_shims/opencode-any.ts +135 -0
  47. package/src/tui/_shims/opencode-sdk-v2.ts +48 -0
  48. package/src/tui/_shims/plugin-tui.ts +13 -0
  49. package/src/tui/_shims/provider-provider.ts +10 -0
  50. package/src/tui/_shims/session-retry.ts +1 -0
  51. package/src/tui/_shims/session-schema.ts +15 -0
  52. package/src/tui/_shims/session-session.ts +3 -0
  53. package/src/tui/_shims/snapshot.ts +4 -0
  54. package/src/tui/_shims/tool-any.ts +18 -0
  55. package/src/tui/_shims/util-error.ts +7 -0
  56. package/src/tui/_shims/util-filesystem.ts +79 -0
  57. package/src/tui/_shims/util-format.ts +7 -0
  58. package/src/tui/_shims/util-iife.ts +3 -0
  59. package/src/tui/_shims/util-locale.ts +10 -0
  60. package/src/tui/_shims/util-process.ts +38 -0
  61. package/src/tui/app.tsx +783 -0
  62. package/src/tui/asset/charge.wav +0 -0
  63. package/src/tui/asset/pulse-a.wav +0 -0
  64. package/src/tui/asset/pulse-b.wav +0 -0
  65. package/src/tui/asset/pulse-c.wav +0 -0
  66. package/src/tui/attach.ts +100 -0
  67. package/src/tui/component/bg-pulse-render.ts +436 -0
  68. package/src/tui/component/bg-pulse.tsx +99 -0
  69. package/src/tui/component/border.tsx +21 -0
  70. package/src/tui/component/dialog-agent.tsx +31 -0
  71. package/src/tui/component/dialog-console-org.tsx +103 -0
  72. package/src/tui/component/dialog-mcp.tsx +85 -0
  73. package/src/tui/component/dialog-model.tsx +175 -0
  74. package/src/tui/component/dialog-provider.tsx +456 -0
  75. package/src/tui/component/dialog-retry-action.tsx +160 -0
  76. package/src/tui/component/dialog-session-delete-failed.tsx +99 -0
  77. package/src/tui/component/dialog-session-list.tsx +323 -0
  78. package/src/tui/component/dialog-session-rename.tsx +31 -0
  79. package/src/tui/component/dialog-skill.tsx +36 -0
  80. package/src/tui/component/dialog-stash.tsx +87 -0
  81. package/src/tui/component/dialog-status.tsx +168 -0
  82. package/src/tui/component/dialog-tag.tsx +44 -0
  83. package/src/tui/component/dialog-theme-list.tsx +50 -0
  84. package/src/tui/component/dialog-variant.tsx +39 -0
  85. package/src/tui/component/dialog-workspace-create.tsx +302 -0
  86. package/src/tui/component/dialog-workspace-file-changes.tsx +138 -0
  87. package/src/tui/component/dialog-workspace-unavailable.tsx +69 -0
  88. package/src/tui/component/error-component.tsx +92 -0
  89. package/src/tui/component/logo.tsx +896 -0
  90. package/src/tui/component/plugin-route-missing.tsx +14 -0
  91. package/src/tui/component/prompt/autocomplete.tsx +869 -0
  92. package/src/tui/component/prompt/cwd.ts +0 -0
  93. package/src/tui/component/prompt/frecency.tsx +90 -0
  94. package/src/tui/component/prompt/history.tsx +108 -0
  95. package/src/tui/component/prompt/index.tsx +1809 -0
  96. package/src/tui/component/prompt/part.ts +16 -0
  97. package/src/tui/component/prompt/stash.tsx +101 -0
  98. package/src/tui/component/prompt/traits.ts +35 -0
  99. package/src/tui/component/spinner.tsx +24 -0
  100. package/src/tui/component/startup-loading.tsx +63 -0
  101. package/src/tui/component/todo-item.tsx +32 -0
  102. package/src/tui/component/use-connected.tsx +9 -0
  103. package/src/tui/component/workspace-label.tsx +19 -0
  104. package/src/tui/config/cwd.ts +5 -0
  105. package/src/tui/config/keybind.ts +432 -0
  106. package/src/tui/config/tui-migrate.ts +154 -0
  107. package/src/tui/config/tui-schema.ts +34 -0
  108. package/src/tui/config/tui.ts +46 -0
  109. package/src/tui/context/aggregate-failures.ts +34 -0
  110. package/src/tui/context/args.tsx +15 -0
  111. package/src/tui/context/command-palette.tsx +163 -0
  112. package/src/tui/context/directory.ts +15 -0
  113. package/src/tui/context/editor-zed.ts +283 -0
  114. package/src/tui/context/editor.ts +468 -0
  115. package/src/tui/context/event-apx.ts +22 -0
  116. package/src/tui/context/event.ts +6 -0
  117. package/src/tui/context/exit.tsx +60 -0
  118. package/src/tui/context/helper.tsx +25 -0
  119. package/src/tui/context/kv.tsx +81 -0
  120. package/src/tui/context/local.tsx +608 -0
  121. package/src/tui/context/path-format.tsx +39 -0
  122. package/src/tui/context/project-apx.tsx +48 -0
  123. package/src/tui/context/project.tsx +7 -0
  124. package/src/tui/context/prompt.tsx +18 -0
  125. package/src/tui/context/route.tsx +52 -0
  126. package/src/tui/context/sdk-apx.tsx +185 -0
  127. package/src/tui/context/sdk.tsx +6 -0
  128. package/src/tui/context/sync-apx.tsx +178 -0
  129. package/src/tui/context/sync-v2.tsx +16 -0
  130. package/src/tui/context/sync.tsx +118 -0
  131. package/src/tui/context/theme/aura.json +69 -0
  132. package/src/tui/context/theme/ayu.json +80 -0
  133. package/src/tui/context/theme/carbonfox.json +248 -0
  134. package/src/tui/context/theme/catppuccin-frappe.json +230 -0
  135. package/src/tui/context/theme/catppuccin-macchiato.json +230 -0
  136. package/src/tui/context/theme/catppuccin.json +112 -0
  137. package/src/tui/context/theme/cobalt2.json +225 -0
  138. package/src/tui/context/theme/cursor.json +249 -0
  139. package/src/tui/context/theme/dracula.json +219 -0
  140. package/src/tui/context/theme/everforest.json +241 -0
  141. package/src/tui/context/theme/flexoki.json +237 -0
  142. package/src/tui/context/theme/github.json +233 -0
  143. package/src/tui/context/theme/gruvbox.json +242 -0
  144. package/src/tui/context/theme/kanagawa.json +77 -0
  145. package/src/tui/context/theme/lucent-orng.json +234 -0
  146. package/src/tui/context/theme/material.json +235 -0
  147. package/src/tui/context/theme/matrix.json +77 -0
  148. package/src/tui/context/theme/mercury.json +252 -0
  149. package/src/tui/context/theme/monokai.json +221 -0
  150. package/src/tui/context/theme/nightowl.json +221 -0
  151. package/src/tui/context/theme/nord.json +223 -0
  152. package/src/tui/context/theme/one-dark.json +84 -0
  153. package/src/tui/context/theme/opencode.json +245 -0
  154. package/src/tui/context/theme/orng.json +249 -0
  155. package/src/tui/context/theme/osaka-jade.json +93 -0
  156. package/src/tui/context/theme/palenight.json +222 -0
  157. package/src/tui/context/theme/rosepine.json +234 -0
  158. package/src/tui/context/theme/solarized.json +223 -0
  159. package/src/tui/context/theme/synthwave84.json +226 -0
  160. package/src/tui/context/theme/tokyonight.json +243 -0
  161. package/src/tui/context/theme/vercel.json +245 -0
  162. package/src/tui/context/theme/vesper.json +218 -0
  163. package/src/tui/context/theme/zenburn.json +223 -0
  164. package/src/tui/context/theme.tsx +1247 -0
  165. package/src/tui/context/tui-config.tsx +9 -0
  166. package/src/tui/event.ts +16 -0
  167. package/src/tui/feature-plugins/home/footer.tsx +94 -0
  168. package/src/tui/feature-plugins/home/tips-view.tsx +166 -0
  169. package/src/tui/feature-plugins/home/tips.tsx +59 -0
  170. package/src/tui/feature-plugins/sidebar/context.tsx +65 -0
  171. package/src/tui/feature-plugins/sidebar/files.tsx +63 -0
  172. package/src/tui/feature-plugins/sidebar/footer.tsx +94 -0
  173. package/src/tui/feature-plugins/sidebar/lsp.tsx +65 -0
  174. package/src/tui/feature-plugins/sidebar/mcp.tsx +97 -0
  175. package/src/tui/feature-plugins/sidebar/todo.tsx +49 -0
  176. package/src/tui/feature-plugins/system/plugins.tsx +269 -0
  177. package/src/tui/feature-plugins/system/session-v2.tsx +1143 -0
  178. package/src/tui/feature-plugins/system/which-key.tsx +608 -0
  179. package/src/tui/keymap.tsx +166 -0
  180. package/src/tui/layer.ts +6 -0
  181. package/src/tui/plugin/api.tsx +381 -0
  182. package/src/tui/plugin/command-shim.ts +109 -0
  183. package/src/tui/plugin/internal.ts +33 -0
  184. package/src/tui/plugin/runtime.ts +1069 -0
  185. package/src/tui/plugin/slots.tsx +60 -0
  186. package/src/tui/routes/home.tsx +96 -0
  187. package/src/tui/routes/session/dialog-fork-from-timeline.tsx +76 -0
  188. package/src/tui/routes/session/dialog-message.tsx +108 -0
  189. package/src/tui/routes/session/dialog-subagent.tsx +26 -0
  190. package/src/tui/routes/session/dialog-timeline.tsx +47 -0
  191. package/src/tui/routes/session/footer.tsx +91 -0
  192. package/src/tui/routes/session/index.tsx +188 -0
  193. package/src/tui/routes/session/permission.tsx +722 -0
  194. package/src/tui/routes/session/question.tsx +490 -0
  195. package/src/tui/routes/session/sidebar.tsx +102 -0
  196. package/src/tui/routes/session/subagent-footer.tsx +133 -0
  197. package/src/tui/run.ts +84 -0
  198. package/src/tui/thread.ts +261 -0
  199. package/src/tui/tsconfig.json +40 -0
  200. package/src/tui/ui/dialog-alert.tsx +66 -0
  201. package/src/tui/ui/dialog-confirm.tsx +108 -0
  202. package/src/tui/ui/dialog-export-options.tsx +217 -0
  203. package/src/tui/ui/dialog-help.tsx +40 -0
  204. package/src/tui/ui/dialog-prompt.tsx +101 -0
  205. package/src/tui/ui/dialog-select.tsx +553 -0
  206. package/src/tui/ui/dialog.tsx +211 -0
  207. package/src/tui/ui/link.tsx +34 -0
  208. package/src/tui/ui/spinner.ts +368 -0
  209. package/src/tui/ui/toast.tsx +111 -0
  210. package/src/tui/util/clipboard.ts +217 -0
  211. package/src/tui/util/editor.ts +37 -0
  212. package/src/tui/util/model.ts +23 -0
  213. package/src/tui/util/provider-origin.ts +7 -0
  214. package/src/tui/util/revert-diff.ts +18 -0
  215. package/src/tui/util/scroll.ts +25 -0
  216. package/src/tui/util/selection.ts +65 -0
  217. package/src/tui/util/signal.ts +41 -0
  218. package/src/tui/util/sound.ts +156 -0
  219. package/src/tui/util/transcript.ts +112 -0
  220. package/src/tui/validate-session.ts +29 -0
  221. package/src/tui/win32.ts +130 -0
  222. package/src/tui/worker.ts +104 -0
@@ -0,0 +1,3 @@
1
+ export const Flag: Record<string, boolean> = new Proxy({} as Record<string, boolean>, {
2
+ get: () => false,
3
+ })
@@ -0,0 +1,14 @@
1
+ export const Default = {
2
+ error: (..._args: unknown[]) => {},
3
+ warn: (..._args: unknown[]) => {},
4
+ info: (..._args: unknown[]) => {},
5
+ }
6
+
7
+ export function create(_opts?: { service?: string }) {
8
+ return {
9
+ error: (..._args: unknown[]) => {},
10
+ warn: (..._args: unknown[]) => {},
11
+ info: (..._args: unknown[]) => {},
12
+ debug: (..._args: unknown[]) => {},
13
+ }
14
+ }
@@ -0,0 +1 @@
1
+ export const LANGUAGE_EXTENSIONS: Record<string, string> = {}
@@ -0,0 +1,135 @@
1
+ // Catch-all shim for any unmapped @/* opencode imports.
2
+ // This file is intentionally vague — it re-exports common shapes that are
3
+ // referenced across the TUI codebase so that Bun can at least resolve them
4
+ // without hard errors.
5
+
6
+ export default {}
7
+
8
+ // Common named exports used across TUI files
9
+ export const Flag: Record<string, boolean> = new Proxy({} as Record<string, boolean>, { get: () => false })
10
+ import os from "os"
11
+ import path from "path"
12
+ const _apxStateDir = path.join(os.homedir(), ".apx", "tui-state")
13
+ export const Global: any = {
14
+ Path: {
15
+ state: _apxStateDir,
16
+ config: path.join(os.homedir(), ".apx"),
17
+ data: _apxStateDir,
18
+ cache: path.join(os.homedir(), ".apx", "cache"),
19
+ },
20
+ }
21
+ export const Binary: any = { search: () => ({ found: false, index: 0 }) }
22
+ export const Filesystem: any = { relative: (_: string, to: string) => to, contains: () => false }
23
+ export const Locale: any = { format: String, number: String, titlecase: (s: string) => s, truncateMiddle: (s: string) => s }
24
+ export const Provider: any = { parseModel: (m: string) => ({ providerID: null, modelID: m }) }
25
+ export const Session: any = { isDefaultTitle: () => true }
26
+ export const SessionRetry: any = {}
27
+ export const MessageID: any = { ascending: () => `msg-${Date.now()}` }
28
+ export const PartID: any = { ascending: () => `part-${Date.now()}` }
29
+ export const SessionID: any = { ascending: () => `sid-${Date.now()}` }
30
+ export const TuiConfig: any = {}
31
+ export const TuiPluginRuntime: any = {
32
+ init: async () => {},
33
+ dispose: async () => {},
34
+ Slot: () => null,
35
+ }
36
+ export const createTuiApi: any = () => ({})
37
+ export const RouteMap: any = Map
38
+ export const UI: any = {}
39
+ export const iife: any = (fn: () => any) => fn()
40
+ export const emptyConsoleState: any = { switchableOrgCount: 0 }
41
+ export const FormatError: any = () => undefined
42
+ export const FormatUnknownError: any = (e: unknown) => String(e)
43
+ export const LANGUAGE_EXTENSIONS: any = {}
44
+ export const ShellTool: any = {}
45
+ export const ShellID: any = { fromString: () => null }
46
+ export const TodoWriteTool: any = {}
47
+ export const webSearchProviderLabel: any = () => ""
48
+
49
+ export function formatDuration(seconds: number): string {
50
+ if (seconds <= 0) return ""
51
+ if (seconds < 60) return `${seconds}s`
52
+ return `${Math.floor(seconds / 60)}m ${seconds % 60}s`
53
+ }
54
+
55
+ export function errorMessage(error: unknown): string {
56
+ return error instanceof Error ? error.message : String(error)
57
+ }
58
+
59
+ export function errorData(_error: unknown): undefined {
60
+ return undefined
61
+ }
62
+
63
+ export function isRecord(v: unknown): v is Record<string, unknown> {
64
+ return typeof v === "object" && v !== null && !Array.isArray(v)
65
+ }
66
+
67
+ export function defer<T>(fn: () => T): T {
68
+ return fn()
69
+ }
70
+
71
+ export const which: any = async () => undefined
72
+
73
+ export const Process: any = {}
74
+ export const Rpc: any = {}
75
+ export const AppRuntime: any = {}
76
+ export const InstanceRuntime: any = {}
77
+ export const BusEvent: any = {}
78
+ export const GlobalBus: any = {}
79
+ export const Config: any = {}
80
+ export const ConfigParse: any = {}
81
+ export const ConfigPlugin: any = {}
82
+ export const ConfigVariable: any = {}
83
+ export const ConfigPaths: any = {}
84
+ export const InvalidError: any = class {}
85
+ export const Installation: any = {}
86
+ export const PluginLoader: any = {}
87
+ export const PluginMeta: any = {}
88
+ export const Reference: any = { resolveAll: () => [] }
89
+ export const Server: any = {}
90
+ export const ServerAuth: any = {}
91
+ export const WithInstance: any = {}
92
+ export const Heap: any = {}
93
+ export const Npm: any = {}
94
+ export const upgrade: any = () => {}
95
+ export const cmd: any = {}
96
+ export const withTimeout: any = (fn: any) => fn
97
+ export const withNetworkOptions: any = () => {}
98
+ export const resolveNetworkOptionsNoConfig: any = () => ({})
99
+ export const displayCharAt: any = () => ""
100
+ export const mentionTriggerIndex: any = () => -1
101
+ export const installPlugin: any = () => {}
102
+ export const patchPluginConfig: any = () => {}
103
+ export const readPluginManifest: any = () => ({})
104
+ export const installModulePlugin: any = () => {}
105
+ export const readPackageThemes: any = () => []
106
+ export const readPluginId: any = () => undefined
107
+ export const readV1Plugin: any = () => undefined
108
+ export const resolvePluginId: any = () => undefined
109
+ export type PluginPackage = any
110
+ export type PluginSource = any
111
+ export const disposeAllInstancesAndEmitGlobalDisposed: any = () => {}
112
+
113
+ // Types (as `any`)
114
+ export type DeepMutable<T> = T
115
+ export type Tool = any
116
+ export type TuiPlugin = any
117
+ export type TuiPluginApi = any
118
+ export type TuiPluginStatus = any
119
+ export type TuiPluginModule = any
120
+ export type TuiCommand = any
121
+ export type TuiDialogSelectOption = any
122
+ export type TuiRouteDefinition = any
123
+ export type TuiSlotProps = any
124
+ export type TuiSlotContext = any
125
+ export type TuiSlotMap = any
126
+ export type TuiThemeCurrent = any
127
+ export type ConsoleState = { switchableOrgCount: number; activeOrgName?: string }
128
+ export type Snapshot = any
129
+ export type RouteMap = any
130
+ export type AppFileSystem = any
131
+ export type AgentPart = any
132
+ export type VcsFileStatus = any
133
+ export type ExperimentalConsoleListOrgsResponse = any
134
+ export type ProviderAuthAuthorization = any
135
+ export type QuestionAnswer = any
@@ -0,0 +1,48 @@
1
+ export type Message = any
2
+ export type AssistantMessage = any
3
+ export type UserMessage = any
4
+ export type Part = any
5
+ export type TextPart = any
6
+ export type ReasoningPart = any
7
+ export type ToolPart = any
8
+ export type FilePart = any
9
+ export type Agent = any
10
+ export type Provider = any
11
+ export type Session = any
12
+ export type Config = any
13
+ export type Todo = any
14
+ export type Command = any
15
+ export type PermissionRequest = any
16
+ export type QuestionRequest = any
17
+ export type LspStatus = any
18
+ export type McpStatus = any
19
+ export type McpResource = any
20
+ export type FormatterStatus = any
21
+ export type SessionStatus = any
22
+ export type ProviderListResponse = any
23
+ export type ProviderAuthMethod = any
24
+ export type VcsInfo = any
25
+ export type GlobalEvent = any
26
+ export type Event = any
27
+ export type Path = any
28
+ export type Workspace = any
29
+ export type SessionMessage = any
30
+ export type SessionMessageAssistant = any
31
+ export type SessionMessageAssistantReasoning = any
32
+ export type SessionMessageAssistantText = any
33
+ export type SessionMessageAssistantTool = any
34
+ export type ReadTool = any
35
+ export type WriteTool = any
36
+ export type GlobTool = any
37
+ export type GrepTool = any
38
+ export type EditTool = any
39
+ export type ApplyPatchTool = any
40
+ export type WebFetchTool = any
41
+ export type WebSearchTool = any
42
+ export type TaskTool = any
43
+ export type QuestionTool = any
44
+ export type SkillTool = any
45
+ export const webSearchProviderLabel = (_tool: any): string => ""
46
+ export function createOpencodeClient(_opts: any): any {
47
+ return {}
48
+ }
@@ -0,0 +1,13 @@
1
+ // Shim for @opencode-ai/plugin/tui
2
+ export type TuiPlugin = any
3
+ export type TuiPluginApi = any
4
+ export type TuiPluginStatus = any
5
+ export type TuiPluginModule = any
6
+ export type TuiCommand = any
7
+ export type TuiDialogSelectOption = any
8
+ export type TuiRouteDefinition = any
9
+ export type TuiSlotProps = any
10
+ export type TuiSlotContext = any
11
+ export type TuiSlotMap = any
12
+ export type TuiThemeCurrent = any
13
+ export default {}
@@ -0,0 +1,10 @@
1
+ export const Provider = {
2
+ parseModel: (model: string) => {
3
+ const parts = model.split(":")
4
+ if (parts.length >= 2) return { providerID: parts[0], modelID: parts.slice(1).join(":") }
5
+ // Also support slash separator
6
+ const slashParts = model.split("/")
7
+ if (slashParts.length >= 2) return { providerID: slashParts[0], modelID: slashParts.slice(1).join("/") }
8
+ return { providerID: null, modelID: model }
9
+ },
10
+ }
@@ -0,0 +1 @@
1
+ export const SessionRetry: Record<string, unknown> = {}
@@ -0,0 +1,15 @@
1
+ let _msgCounter = 0
2
+ let _partCounter = 0
3
+ let _sidCounter = 0
4
+
5
+ export const MessageID = {
6
+ ascending: () => `msg-${Date.now()}-${_msgCounter++}`,
7
+ }
8
+
9
+ export const PartID = {
10
+ ascending: () => `part-${Date.now()}-${_partCounter++}`,
11
+ }
12
+
13
+ export const SessionID = {
14
+ ascending: () => `sid-${Date.now()}-${_sidCounter++}`,
15
+ }
@@ -0,0 +1,3 @@
1
+ export const Session = {
2
+ isDefaultTitle: (_title: string) => true,
3
+ }
@@ -0,0 +1,4 @@
1
+ export type Snapshot = { FileDiff: any }
2
+ export namespace Snapshot {
3
+ export type FileDiff = any
4
+ }
@@ -0,0 +1,18 @@
1
+ // Catch-all shim for @/tool/* imports
2
+ export const ShellTool: any = {}
3
+ export const ShellID: any = { fromString: () => null }
4
+ export const TodoWriteTool: any = {}
5
+ export type Tool = any
6
+ export type ReadTool = any
7
+ export type WriteTool = any
8
+ export type GlobTool = any
9
+ export type GrepTool = any
10
+ export type EditTool = any
11
+ export type ApplyPatchTool = any
12
+ export type WebFetchTool = any
13
+ export type WebSearchTool = any
14
+ export type TaskTool = any
15
+ export type QuestionTool = any
16
+ export type SkillTool = any
17
+ export const webSearchProviderLabel = (_tool: any): string => ""
18
+ export default {}
@@ -0,0 +1,7 @@
1
+ export function errorMessage(error: unknown): string {
2
+ return error instanceof Error ? error.message : String(error)
3
+ }
4
+
5
+ export function errorData(_error: unknown): undefined {
6
+ return undefined
7
+ }
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs"
2
+ import path from "node:path"
3
+
4
+ export const Filesystem = {
5
+ relative: (_from: string, to: string) => to,
6
+ contains: (parent: string, child: string): boolean => {
7
+ const rel = path.relative(parent, child)
8
+ return !rel.startsWith("..") && !path.isAbsolute(rel)
9
+ },
10
+ mimeType: async (filepath: string): Promise<string> => {
11
+ const ext = path.extname(filepath).toLowerCase()
12
+ const map: Record<string, string> = {
13
+ ".png": "image/png",
14
+ ".jpg": "image/jpeg",
15
+ ".jpeg": "image/jpeg",
16
+ ".gif": "image/gif",
17
+ ".webp": "image/webp",
18
+ ".svg": "image/svg+xml",
19
+ ".pdf": "application/pdf",
20
+ }
21
+ return map[ext] ?? "application/octet-stream"
22
+ },
23
+ readText: async (filepath: string): Promise<string> => {
24
+ return fs.promises.readFile(filepath, "utf8")
25
+ },
26
+ readArrayBuffer: async (filepath: string): Promise<ArrayBuffer> => {
27
+ const buf = await fs.promises.readFile(filepath)
28
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer
29
+ },
30
+ readBytes: async (filepath: string): Promise<Buffer> => {
31
+ return fs.promises.readFile(filepath)
32
+ },
33
+ readJson: async <T = unknown>(filepath: string): Promise<T> => {
34
+ const text = await fs.promises.readFile(filepath, "utf8")
35
+ return JSON.parse(text) as T
36
+ },
37
+ writeJson: async (filepath: string, data: unknown): Promise<void> => {
38
+ await fs.promises.mkdir(path.dirname(filepath), { recursive: true })
39
+ await fs.promises.writeFile(filepath, JSON.stringify(data, null, 2), "utf8")
40
+ },
41
+ write: async (filepath: string, content: string): Promise<void> => {
42
+ await fs.promises.mkdir(path.dirname(filepath), { recursive: true })
43
+ await fs.promises.writeFile(filepath, content, "utf8")
44
+ },
45
+ writeArrayBuffer: async (filepath: string, data: ArrayBuffer): Promise<void> => {
46
+ await fs.promises.mkdir(path.dirname(filepath), { recursive: true })
47
+ await fs.promises.writeFile(filepath, Buffer.from(data))
48
+ },
49
+ exists: async (filepath: string): Promise<boolean> => {
50
+ try {
51
+ await fs.promises.access(filepath)
52
+ return true
53
+ } catch {
54
+ return false
55
+ }
56
+ },
57
+ findUp: async (
58
+ names: string[],
59
+ cwd: string,
60
+ _root?: string,
61
+ _opts?: { rootFirst?: boolean },
62
+ ): Promise<string[]> => {
63
+ const results: string[] = []
64
+ let current = cwd
65
+ while (true) {
66
+ for (const name of names) {
67
+ const candidate = path.join(current, name)
68
+ try {
69
+ await fs.promises.access(candidate)
70
+ results.push(candidate)
71
+ } catch {}
72
+ }
73
+ const parent = path.dirname(current)
74
+ if (parent === current) break
75
+ current = parent
76
+ }
77
+ return results
78
+ },
79
+ }
@@ -0,0 +1,7 @@
1
+ export function formatDuration(seconds: number): string {
2
+ if (seconds <= 0) return ""
3
+ if (seconds < 60) return `${seconds}s`
4
+ const m = Math.floor(seconds / 60)
5
+ const s = seconds % 60
6
+ return s > 0 ? `${m}m ${s}s` : `${m}m`
7
+ }
@@ -0,0 +1,3 @@
1
+ export function iife<T>(fn: () => T): T {
2
+ return fn()
3
+ }
@@ -0,0 +1,10 @@
1
+ export const Locale = {
2
+ format: (n: number) => String(n),
3
+ number: (n: number) => n.toLocaleString(),
4
+ titlecase: (s: string) => s.charAt(0).toUpperCase() + s.slice(1),
5
+ truncateMiddle: (s: string, maxLen: number): string => {
6
+ if (s.length <= maxLen) return s
7
+ const half = Math.floor((maxLen - 3) / 2)
8
+ return s.slice(0, half) + "..." + s.slice(s.length - half)
9
+ },
10
+ }
@@ -0,0 +1,38 @@
1
+ import { exec, spawn as nodeSpawn } from "node:child_process"
2
+ import { promisify } from "node:util"
3
+
4
+ const execAsync = promisify(exec)
5
+
6
+ export const Process = {
7
+ async run(args: string[], opts: { nothrow?: boolean } = {}) {
8
+ try {
9
+ const [cmd, ...rest] = args
10
+ const { stdout, stderr } = await execAsync(
11
+ [cmd, ...rest.map((a) => (a.includes(" ") ? JSON.stringify(a) : a))].join(" "),
12
+ )
13
+ return { stdout: Buffer.from(stdout), stderr: Buffer.from(stderr), exitCode: 0 }
14
+ } catch (e: any) {
15
+ if (opts.nothrow) {
16
+ return { stdout: Buffer.alloc(0), stderr: Buffer.alloc(0), exitCode: 1 }
17
+ }
18
+ throw e
19
+ }
20
+ },
21
+
22
+ async text(args: string[], opts: { nothrow?: boolean } = {}) {
23
+ const result = await Process.run(args, opts)
24
+ return { text: result.stdout.toString("utf8"), exitCode: result.exitCode }
25
+ },
26
+
27
+ spawn(args: string[], opts: { stdin?: string; stdout?: string; stderr?: string } = {}) {
28
+ const [cmd, ...rest] = args
29
+ const child = nodeSpawn(cmd, rest, {
30
+ stdio: [(opts.stdin ?? "inherit") as any, (opts.stdout ?? "inherit") as any, (opts.stderr ?? "inherit") as any],
31
+ })
32
+ const exited = new Promise<number>((resolve, reject) => {
33
+ child.on("exit", (code) => resolve(code ?? 0))
34
+ child.on("error", reject)
35
+ })
36
+ return { stdin: child.stdin, stdout: child.stdout, stderr: child.stderr, exited }
37
+ },
38
+ }